diff options
1314 files changed, 24098 insertions, 15339 deletions
diff --git a/.github/ISSUE_TEMPLATE/documentation.md b/.github/ISSUE_TEMPLATE/documentation.md new file mode 100644 index 00000000000..1d93939e233 --- /dev/null +++ b/.github/ISSUE_TEMPLATE/documentation.md @@ -0,0 +1,16 @@ +--- +name: Documentation problem +about: Create a report for a documentation problem. +labels: A-docs +--- +<!-- +Thank you for finding a documentation problem! 📚 + +Documentation problems might be grammatical issues, typos, or unclear wording, please provide details regarding the documentation including where it is present. + +--> + +### Location + +### Summary + diff --git a/.github/ISSUE_TEMPLATE/library_tracking_issue.md b/.github/ISSUE_TEMPLATE/library_tracking_issue.md index 32fccfcfb16..91c06402ca1 100644 --- a/.github/ISSUE_TEMPLATE/library_tracking_issue.md +++ b/.github/ISSUE_TEMPLATE/library_tracking_issue.md @@ -50,7 +50,7 @@ If the feature is changed later, please add those PRs here as well. --> - [ ] Implementation: #... -- [ ] Final comment period (FCP) +- [ ] Final comment period (FCP)[^1] - [ ] Stabilization PR <!-- @@ -81,3 +81,5 @@ Zulip, or the internals forum) here. --> - None yet. + +[^1]: https://std-dev-guide.rust-lang.org/feature-lifecycle/stabilization.html diff --git a/Cargo.lock b/Cargo.lock index c0905982467..75b9c0fce22 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -298,7 +298,7 @@ dependencies = [ [[package]] name = "cargo" -version = "0.64.0" +version = "0.65.0" dependencies = [ "anyhow", "atty", @@ -445,7 +445,7 @@ dependencies = [ [[package]] name = "cargo-util" -version = "0.1.4" +version = "0.2.1" dependencies = [ "anyhow", "core-foundation", @@ -638,7 +638,7 @@ dependencies = [ [[package]] name = "clippy" -version = "0.1.63" +version = "0.1.64" dependencies = [ "clippy_lints", "clippy_utils", @@ -661,6 +661,7 @@ dependencies = [ "termize", "tester", "tokio", + "toml", ] [[package]] @@ -679,10 +680,9 @@ dependencies = [ [[package]] name = "clippy_lints" -version = "0.1.63" +version = "0.1.64" dependencies = [ "cargo_metadata", - "clippy_dev", "clippy_utils", "if_chain", "itertools", @@ -702,7 +702,7 @@ dependencies = [ [[package]] name = "clippy_utils" -version = "0.1.63" +version = "0.1.64" dependencies = [ "arrayvec", "if_chain", @@ -2617,9 +2617,9 @@ checksum = "dd20eec3dbe4376829cb7d80ae6ac45e0a766831dca50202ff2d40db46a8a024" [[package]] name = "os_info" -version = "3.0.7" +version = "3.4.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6ac91020bfed8cc3f8aa450d4c3b5fa1d3373fc091c8a92009f3b27749d5a227" +checksum = "0eca3ecae1481e12c3d9379ec541b238a16f0b75c9a409942daa8ec20dbfdb62" dependencies = [ "log", "serde", @@ -4009,6 +4009,7 @@ dependencies = [ "rustc_hir", "rustc_index", "rustc_infer", + "rustc_macros", "rustc_middle", "rustc_parse_format", "rustc_session", diff --git a/RELEASES.md b/RELEASES.md index 7479735012c..8154eab2059 100644 --- a/RELEASES.md +++ b/RELEASES.md @@ -5,7 +5,7 @@ Language -------- - [Stabilize `#[derive(Default)]` on enums with a `#[default]` variant][94457] -- [Stop validating some checks in dead code after functions with uninhabited return types][93313] +- [Teach flow sensitive checks that visibly uninhabited call expressions never return][93313] - [Fix constants not getting dropped if part of a diverging expression][94775] - [Support unit struct/enum variant in destructuring assignment][95380] - [Remove mutable_borrow_reservation_conflict lint and allow the code pattern][96268] @@ -75,8 +75,11 @@ Compatibility Notes - `cargo test` now passes `--target` to `rustdoc` if the specified target is the same as the host target. [#10594](https://github.com/rust-lang/cargo/pull/10594) +- [rustdoc: doctests are now run on unexported `macro_rules!` macros, matching other private items][96630] - [rustdoc: Remove .woff font files][96279] - [Enforce Copy bounds for repeat elements while considering lifetimes][95819] +- [Windows: Fix potentinal unsoundness by aborting if `File` reads or writes cannot + complete synchronously][95469]. Internal Changes ---------------- @@ -98,6 +101,7 @@ and related tools. [95372]: https://github.com/rust-lang/rust/pull/95372/ [95380]: https://github.com/rust-lang/rust/pull/95380/ [95431]: https://github.com/rust-lang/rust/pull/95431/ +[95469]: https://github.com/rust-lang/rust/pull/95469/ [95705]: https://github.com/rust-lang/rust/pull/95705/ [95801]: https://github.com/rust-lang/rust/pull/95801/ [95819]: https://github.com/rust-lang/rust/pull/95819/ @@ -109,6 +113,7 @@ and related tools. [96393]: https://github.com/rust-lang/rust/pull/96393/ [96436]: https://github.com/rust-lang/rust/pull/96436/ [96557]: https://github.com/rust-lang/rust/pull/96557/ +[96630]: https://github.com/rust-lang/rust/pull/96630/ [`bool::then_some`]: https://doc.rust-lang.org/stable/std/primitive.bool.html#method.then_some [`f32::total_cmp`]: https://doc.rust-lang.org/stable/std/primitive.f32.html#method.total_cmp diff --git a/compiler/rustc_ast_lowering/src/index.rs b/compiler/rustc_ast_lowering/src/index.rs index 4be22020ba1..ddd54f7c208 100644 --- a/compiler/rustc_ast_lowering/src/index.rs +++ b/compiler/rustc_ast_lowering/src/index.rs @@ -192,9 +192,7 @@ impl<'a, 'hir> Visitor<'hir> for NodeCollector<'a, 'hir> { } fn visit_pat(&mut self, pat: &'hir Pat<'hir>) { - let node = - if let PatKind::Binding(..) = pat.kind { Node::Binding(pat) } else { Node::Pat(pat) }; - self.insert(pat.span, pat.hir_id, node); + self.insert(pat.span, pat.hir_id, Node::Pat(pat)); self.with_parent(pat.hir_id, |this| { intravisit::walk_pat(this, pat); diff --git a/compiler/rustc_borrowck/src/borrow_set.rs b/compiler/rustc_borrowck/src/borrow_set.rs index c7d0e336133..41279588e63 100644 --- a/compiler/rustc_borrowck/src/borrow_set.rs +++ b/compiler/rustc_borrowck/src/borrow_set.rs @@ -92,9 +92,9 @@ impl LocalsStateAtExit { struct HasStorageDead(BitSet<Local>); impl<'tcx> Visitor<'tcx> for HasStorageDead { - fn visit_local(&mut self, local: &Local, ctx: PlaceContext, _: Location) { + fn visit_local(&mut self, local: Local, ctx: PlaceContext, _: Location) { if ctx == PlaceContext::NonUse(NonUseContext::StorageDead) { - self.0.insert(*local); + self.0.insert(local); } } } @@ -223,7 +223,7 @@ impl<'a, 'tcx> Visitor<'tcx> for GatherBorrows<'a, 'tcx> { self.super_assign(assigned_place, rvalue, location) } - fn visit_local(&mut self, temp: &Local, context: PlaceContext, location: Location) { + fn visit_local(&mut self, temp: Local, context: PlaceContext, location: Location) { if !context.is_use() { return; } @@ -232,7 +232,7 @@ impl<'a, 'tcx> Visitor<'tcx> for GatherBorrows<'a, 'tcx> { // check whether we (earlier) saw a 2-phase borrow like // // TMP = &mut place - if let Some(&borrow_index) = self.pending_activations.get(temp) { + if let Some(&borrow_index) = self.pending_activations.get(&temp) { let borrow_data = &mut self.location_map[borrow_index.as_usize()]; // Watch out: the use of TMP in the borrow itself diff --git a/compiler/rustc_borrowck/src/borrowck_errors.rs b/compiler/rustc_borrowck/src/borrowck_errors.rs index 708fe8719a1..a5d9a2bc597 100644 --- a/compiler/rustc_borrowck/src/borrowck_errors.rs +++ b/compiler/rustc_borrowck/src/borrowck_errors.rs @@ -478,7 +478,7 @@ 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)] + #[rustc_lint_diagnostics] fn struct_span_err_with_code<S: Into<MultiSpan>>( &self, sp: S, diff --git a/compiler/rustc_borrowck/src/constraint_generation.rs b/compiler/rustc_borrowck/src/constraint_generation.rs index e4ffae38c33..5e9cec5c350 100644 --- a/compiler/rustc_borrowck/src/constraint_generation.rs +++ b/compiler/rustc_borrowck/src/constraint_generation.rs @@ -5,8 +5,8 @@ use rustc_middle::mir::{ BasicBlock, BasicBlockData, Body, Local, Location, Place, PlaceRef, ProjectionElem, Rvalue, SourceInfo, Statement, StatementKind, Terminator, TerminatorKind, UserTypeProjection, }; -use rustc_middle::ty::fold::TypeFoldable; use rustc_middle::ty::subst::SubstsRef; +use rustc_middle::ty::visit::TypeVisitable; use rustc_middle::ty::{self, RegionVid, Ty}; use crate::{ @@ -149,7 +149,7 @@ impl<'cg, 'cx, 'tcx> Visitor<'tcx> for ConstraintGeneration<'cg, 'cx, 'tcx> { fn visit_ascribe_user_ty( &mut self, _place: &Place<'tcx>, - _variance: &ty::Variance, + _variance: ty::Variance, _user_ty: &UserTypeProjection, _location: Location, ) { @@ -163,7 +163,7 @@ impl<'cx, 'cg, 'tcx> ConstraintGeneration<'cx, 'cg, 'tcx> { /// `location`. fn add_regular_live_constraint<T>(&mut self, live_ty: T, location: Location) where - T: TypeFoldable<'tcx>, + T: TypeVisitable<'tcx>, { debug!("add_regular_live_constraint(live_ty={:?}, location={:?})", live_ty, location); diff --git a/compiler/rustc_borrowck/src/diagnostics/find_all_local_uses.rs b/compiler/rustc_borrowck/src/diagnostics/find_all_local_uses.rs index 49d9caae711..b3edc35dc36 100644 --- a/compiler/rustc_borrowck/src/diagnostics/find_all_local_uses.rs +++ b/compiler/rustc_borrowck/src/diagnostics/find_all_local_uses.rs @@ -18,8 +18,8 @@ struct AllLocalUsesVisitor { } impl<'tcx> Visitor<'tcx> for AllLocalUsesVisitor { - fn visit_local(&mut self, local: &Local, _context: PlaceContext, location: Location) { - if *local == self.for_local { + fn visit_local(&mut self, local: Local, _context: PlaceContext, location: Location) { + if local == self.for_local { self.uses.insert(location); } } diff --git a/compiler/rustc_borrowck/src/diagnostics/find_use.rs b/compiler/rustc_borrowck/src/diagnostics/find_use.rs index 06fca4db0cf..b5a3081e56a 100644 --- a/compiler/rustc_borrowck/src/diagnostics/find_use.rs +++ b/compiler/rustc_borrowck/src/diagnostics/find_use.rs @@ -106,7 +106,7 @@ enum DefUseResult { } impl<'cx, 'tcx> Visitor<'tcx> for DefUseVisitor<'cx, 'tcx> { - fn visit_local(&mut self, &local: &Local, context: PlaceContext, _: Location) { + fn visit_local(&mut self, local: Local, context: PlaceContext, _: Location) { let local_ty = self.body.local_decls[local].ty; let mut found_it = false; diff --git a/compiler/rustc_borrowck/src/diagnostics/mutability_errors.rs b/compiler/rustc_borrowck/src/diagnostics/mutability_errors.rs index 49b24a05071..3c5dd32d281 100644 --- a/compiler/rustc_borrowck/src/diagnostics/mutability_errors.rs +++ b/compiler/rustc_borrowck/src/diagnostics/mutability_errors.rs @@ -362,7 +362,7 @@ impl<'a, 'tcx> MirBorrowckCtxt<'a, 'tcx> { let upvar_hir_id = captured_place.get_root_variable(); - if let Some(Node::Binding(pat)) = self.infcx.tcx.hir().find(upvar_hir_id) + if let Some(Node::Pat(pat)) = self.infcx.tcx.hir().find(upvar_hir_id) && let hir::PatKind::Binding( hir::BindingAnnotation::Unannotated, _, diff --git a/compiler/rustc_borrowck/src/region_infer/mod.rs b/compiler/rustc_borrowck/src/region_infer/mod.rs index f5c9392948b..d0e0203bf8c 100644 --- a/compiler/rustc_borrowck/src/region_infer/mod.rs +++ b/compiler/rustc_borrowck/src/region_infer/mod.rs @@ -19,7 +19,9 @@ use rustc_middle::mir::{ }; use rustc_middle::traits::ObligationCause; use rustc_middle::traits::ObligationCauseCode; -use rustc_middle::ty::{self, subst::SubstsRef, RegionVid, Ty, TyCtxt, TypeFoldable}; +use rustc_middle::ty::{ + self, subst::SubstsRef, RegionVid, Ty, TyCtxt, TypeFoldable, TypeVisitable, +}; use rustc_span::Span; use crate::{ diff --git a/compiler/rustc_borrowck/src/region_infer/opaque_types.rs b/compiler/rustc_borrowck/src/region_infer/opaque_types.rs index d182c0cf4e8..d129e845426 100644 --- a/compiler/rustc_borrowck/src/region_infer/opaque_types.rs +++ b/compiler/rustc_borrowck/src/region_infer/opaque_types.rs @@ -2,7 +2,9 @@ use rustc_data_structures::vec_map::VecMap; use rustc_hir::def_id::DefId; use rustc_hir::OpaqueTyOrigin; use rustc_infer::infer::InferCtxt; -use rustc_middle::ty::{self, OpaqueHiddenType, OpaqueTypeKey, TyCtxt, TypeFoldable}; +use rustc_middle::ty::{ + self, OpaqueHiddenType, OpaqueTypeKey, TyCtxt, TypeFoldable, TypeVisitable, +}; use rustc_trait_selection::opaque_types::InferCtxtExt; use super::RegionInferenceContext; diff --git a/compiler/rustc_borrowck/src/type_check/constraint_conversion.rs b/compiler/rustc_borrowck/src/type_check/constraint_conversion.rs index 5e33d9d25c2..3f9c0cecccc 100644 --- a/compiler/rustc_borrowck/src/type_check/constraint_conversion.rs +++ b/compiler/rustc_borrowck/src/type_check/constraint_conversion.rs @@ -6,7 +6,7 @@ use rustc_infer::infer::region_constraints::{GenericKind, VerifyBound}; use rustc_infer::infer::{self, InferCtxt, SubregionOrigin}; use rustc_middle::mir::ConstraintCategory; use rustc_middle::ty::subst::GenericArgKind; -use rustc_middle::ty::TypeFoldable; +use rustc_middle::ty::TypeVisitable; use rustc_middle::ty::{self, TyCtxt}; use rustc_span::{Span, DUMMY_SP}; diff --git a/compiler/rustc_borrowck/src/type_check/liveness/local_use_map.rs b/compiler/rustc_borrowck/src/type_check/liveness/local_use_map.rs index b88f6e689cc..fda2cee43fb 100644 --- a/compiler/rustc_borrowck/src/type_check/liveness/local_use_map.rs +++ b/compiler/rustc_borrowck/src/type_check/liveness/local_use_map.rs @@ -157,7 +157,7 @@ impl LocalUseMapBuild<'_> { } impl Visitor<'_> for LocalUseMapBuild<'_> { - fn visit_local(&mut self, &local: &Local, context: PlaceContext, location: Location) { + fn visit_local(&mut self, local: Local, context: PlaceContext, location: Location) { if self.locals_with_use_data[local] { match def_use::categorize(context) { Some(DefUse::Def) => self.insert_def(local, location), diff --git a/compiler/rustc_borrowck/src/type_check/liveness/mod.rs b/compiler/rustc_borrowck/src/type_check/liveness/mod.rs index ac8670a5138..d5c401ae1c6 100644 --- a/compiler/rustc_borrowck/src/type_check/liveness/mod.rs +++ b/compiler/rustc_borrowck/src/type_check/liveness/mod.rs @@ -1,11 +1,11 @@ +use itertools::{Either, Itertools}; use rustc_data_structures::fx::FxHashSet; use rustc_middle::mir::{Body, Local}; use rustc_middle::ty::{RegionVid, TyCtxt}; -use std::rc::Rc; - use rustc_mir_dataflow::impls::MaybeInitializedPlaces; use rustc_mir_dataflow::move_paths::MoveData; use rustc_mir_dataflow::ResultsCursor; +use std::rc::Rc; use crate::{ constraints::OutlivesConstraintSet, @@ -46,7 +46,8 @@ pub(super) fn generate<'mir, 'tcx>( &typeck.borrowck_context.universal_regions, &typeck.borrowck_context.constraints.outlives_constraints, ); - let live_locals = compute_live_locals(typeck.tcx(), &free_regions, &body); + let (relevant_live_locals, boring_locals) = + compute_relevant_live_locals(typeck.tcx(), &free_regions, &body); let facts_enabled = use_polonius || AllFacts::enabled(typeck.tcx()); let polonius_drop_used = if facts_enabled { @@ -57,48 +58,44 @@ pub(super) fn generate<'mir, 'tcx>( None }; - if !live_locals.is_empty() || facts_enabled { - trace::trace( - typeck, - body, - elements, - flow_inits, - move_data, - live_locals, - polonius_drop_used, - ); - } + trace::trace( + typeck, + body, + elements, + flow_inits, + move_data, + relevant_live_locals, + boring_locals, + polonius_drop_used, + ); } -// The purpose of `compute_live_locals` is to define the subset of `Local` +// The purpose of `compute_relevant_live_locals` is to define the subset of `Local` // variables for which we need to do a liveness computation. We only need // to compute whether a variable `X` is live if that variable contains // some region `R` in its type where `R` is not known to outlive a free // region (i.e., where `R` may be valid for just a subset of the fn body). -fn compute_live_locals<'tcx>( +fn compute_relevant_live_locals<'tcx>( tcx: TyCtxt<'tcx>, free_regions: &FxHashSet<RegionVid>, body: &Body<'tcx>, -) -> Vec<Local> { - let live_locals: Vec<Local> = body - .local_decls - .iter_enumerated() - .filter_map(|(local, local_decl)| { +) -> (Vec<Local>, Vec<Local>) { + let (boring_locals, relevant_live_locals): (Vec<_>, Vec<_>) = + body.local_decls.iter_enumerated().partition_map(|(local, local_decl)| { if tcx.all_free_regions_meet(&local_decl.ty, |r| { free_regions.contains(&r.to_region_vid()) }) { - None + Either::Left(local) } else { - Some(local) + Either::Right(local) } - }) - .collect(); + }); debug!("{} total variables", body.local_decls.len()); - debug!("{} variables need liveness", live_locals.len()); + debug!("{} variables need liveness", relevant_live_locals.len()); debug!("{} regions outlive free regions", free_regions.len()); - live_locals + (relevant_live_locals, boring_locals) } /// Computes all regions that are (currently) known to outlive free diff --git a/compiler/rustc_borrowck/src/type_check/liveness/polonius.rs b/compiler/rustc_borrowck/src/type_check/liveness/polonius.rs index 8070f357919..bc76a465e3c 100644 --- a/compiler/rustc_borrowck/src/type_check/liveness/polonius.rs +++ b/compiler/rustc_borrowck/src/type_check/liveness/polonius.rs @@ -54,7 +54,7 @@ impl UseFactsExtractor<'_, '_> { } impl<'a, 'tcx> Visitor<'tcx> for UseFactsExtractor<'a, 'tcx> { - fn visit_local(&mut self, &local: &Local, context: PlaceContext, location: Location) { + fn visit_local(&mut self, local: Local, context: PlaceContext, location: Location) { match def_use::categorize(context) { Some(DefUse::Def) => self.insert_def(local, location), Some(DefUse::Use) => self.insert_use(local, location), diff --git a/compiler/rustc_borrowck/src/type_check/liveness/trace.rs b/compiler/rustc_borrowck/src/type_check/liveness/trace.rs index 169de23facc..d4e61ec213b 100644 --- a/compiler/rustc_borrowck/src/type_check/liveness/trace.rs +++ b/compiler/rustc_borrowck/src/type_check/liveness/trace.rs @@ -3,7 +3,7 @@ use rustc_index::bit_set::HybridBitSet; use rustc_index::interval::IntervalSet; use rustc_infer::infer::canonical::QueryRegionConstraints; use rustc_middle::mir::{BasicBlock, Body, ConstraintCategory, Local, Location}; -use rustc_middle::ty::{Ty, TypeFoldable}; +use rustc_middle::ty::{Ty, TypeVisitable}; use rustc_trait_selection::traits::query::dropck_outlives::DropckOutlivesResult; use rustc_trait_selection::traits::query::type_op::outlives::DropckOutlives; use rustc_trait_selection::traits::query::type_op::{TypeOp, TypeOpOutput}; @@ -41,12 +41,13 @@ pub(super) fn trace<'mir, 'tcx>( elements: &Rc<RegionValueElements>, flow_inits: &mut ResultsCursor<'mir, 'tcx, MaybeInitializedPlaces<'mir, 'tcx>>, move_data: &MoveData<'tcx>, - live_locals: Vec<Local>, + relevant_live_locals: Vec<Local>, + boring_locals: Vec<Local>, polonius_drop_used: Option<Vec<(Local, Location)>>, ) { debug!("trace()"); - let local_use_map = &LocalUseMap::build(&live_locals, elements, body); + let local_use_map = &LocalUseMap::build(&relevant_live_locals, elements, body); let cx = LivenessContext { typeck, @@ -61,10 +62,12 @@ pub(super) fn trace<'mir, 'tcx>( let mut results = LivenessResults::new(cx); if let Some(drop_used) = polonius_drop_used { - results.add_extra_drop_facts(drop_used, live_locals.iter().copied().collect()) + results.add_extra_drop_facts(drop_used, relevant_live_locals.iter().copied().collect()) } - results.compute_for_all_locals(live_locals); + results.compute_for_all_locals(relevant_live_locals); + + results.dropck_boring_locals(boring_locals); } /// Contextual state for the type-liveness generator. @@ -133,8 +136,8 @@ impl<'me, 'typeck, 'flow, 'tcx> LivenessResults<'me, 'typeck, 'flow, 'tcx> { } } - fn compute_for_all_locals(&mut self, live_locals: Vec<Local>) { - for local in live_locals { + fn compute_for_all_locals(&mut self, relevant_live_locals: Vec<Local>) { + for local in relevant_live_locals { self.reset_local_state(); self.add_defs_for(local); self.compute_use_live_points_for(local); @@ -157,6 +160,24 @@ impl<'me, 'typeck, 'flow, 'tcx> LivenessResults<'me, 'typeck, 'flow, 'tcx> { } } + // Runs dropck for locals whose liveness isn't relevant. This is + // necessary to eagerly detect unbound recursion during drop glue computation. + fn dropck_boring_locals(&mut self, boring_locals: Vec<Local>) { + for local in boring_locals { + let local_ty = self.cx.body.local_decls[local].ty; + let drop_data = self.cx.drop_data.entry(local_ty).or_insert_with({ + let typeck = &mut self.cx.typeck; + move || LivenessContext::compute_drop_data(typeck, local_ty) + }); + + drop_data.dropck_result.report_overflows( + self.cx.typeck.infcx.tcx, + self.cx.body.local_decls[local].source_info.span, + local_ty, + ); + } + } + /// Add extra drop facts needed for Polonius. /// /// Add facts for all locals with free regions, since regions may outlive @@ -164,12 +185,12 @@ impl<'me, 'typeck, 'flow, 'tcx> LivenessResults<'me, 'typeck, 'flow, 'tcx> { fn add_extra_drop_facts( &mut self, drop_used: Vec<(Local, Location)>, - live_locals: FxHashSet<Local>, + relevant_live_locals: FxHashSet<Local>, ) { let locations = IntervalSet::new(self.cx.elements.num_points()); for (local, location) in drop_used { - if !live_locals.contains(&local) { + if !relevant_live_locals.contains(&local) { let local_ty = self.cx.body.local_decls[local].ty; if local_ty.has_free_regions() { self.cx.add_drop_live_facts_for(local, local_ty, &[location], &locations); @@ -456,7 +477,7 @@ impl<'tcx> LivenessContext<'_, '_, '_, 'tcx> { /// points `live_at`. fn add_use_live_facts_for( &mut self, - value: impl TypeFoldable<'tcx>, + value: impl TypeVisitable<'tcx>, live_at: &IntervalSet<PointIndex>, ) { debug!("add_use_live_facts_for(value={:?})", value); @@ -521,7 +542,7 @@ impl<'tcx> LivenessContext<'_, '_, '_, 'tcx> { fn make_all_regions_live( elements: &RegionValueElements, typeck: &mut TypeChecker<'_, 'tcx>, - value: impl TypeFoldable<'tcx>, + value: impl TypeVisitable<'tcx>, live_at: &IntervalSet<PointIndex>, ) { debug!("make_all_regions_live(value={:?})", value); diff --git a/compiler/rustc_borrowck/src/type_check/mod.rs b/compiler/rustc_borrowck/src/type_check/mod.rs index 5ee1f5a8e8e..d71a4983a92 100644 --- a/compiler/rustc_borrowck/src/type_check/mod.rs +++ b/compiler/rustc_borrowck/src/type_check/mod.rs @@ -27,8 +27,8 @@ use rustc_middle::mir::AssertKind; use rustc_middle::mir::*; use rustc_middle::ty::adjustment::PointerCast; use rustc_middle::ty::cast::CastTy; -use rustc_middle::ty::fold::TypeFoldable; use rustc_middle::ty::subst::{GenericArgKind, SubstsRef, UserSubsts}; +use rustc_middle::ty::visit::TypeVisitable; use rustc_middle::ty::{ self, CanonicalUserTypeAnnotation, CanonicalUserTypeAnnotations, OpaqueHiddenType, OpaqueTypeKey, RegionVid, ToPredicate, Ty, TyCtxt, UserType, UserTypeAnnotationIndex, @@ -333,9 +333,9 @@ struct TypeVerifier<'a, 'b, 'tcx> { } impl<'a, 'b, 'tcx> Visitor<'tcx> for TypeVerifier<'a, 'b, 'tcx> { - fn visit_span(&mut self, span: &Span) { + fn visit_span(&mut self, span: Span) { if !span.is_dummy() { - self.last_span = *span; + self.last_span = span; } } diff --git a/compiler/rustc_borrowck/src/used_muts.rs b/compiler/rustc_borrowck/src/used_muts.rs index 1093167fa82..8833753b12c 100644 --- a/compiler/rustc_borrowck/src/used_muts.rs +++ b/compiler/rustc_borrowck/src/used_muts.rs @@ -91,8 +91,8 @@ impl<'visit, 'cx, 'tcx> Visitor<'tcx> for GatherUsedMutsVisitor<'visit, 'cx, 'tc self.super_statement(statement, location); } - fn visit_local(&mut self, local: &Local, place_context: PlaceContext, location: Location) { - if place_context.is_place_assignment() && self.temporary_used_locals.contains(local) { + fn visit_local(&mut self, local: Local, place_context: PlaceContext, location: Location) { + if place_context.is_place_assignment() && self.temporary_used_locals.contains(&local) { // Propagate the Local assigned at this Location as a used mutable local variable for moi in &self.mbcx.move_data.loc_map[location] { let mpi = &self.mbcx.move_data.moves[*moi].path; diff --git a/compiler/rustc_builtin_macros/src/deriving/bounds.rs b/compiler/rustc_builtin_macros/src/deriving/bounds.rs index 12ef166b8b0..5ef68c6aeaa 100644 --- a/compiler/rustc_builtin_macros/src/deriving/bounds.rs +++ b/compiler/rustc_builtin_macros/src/deriving/bounds.rs @@ -19,7 +19,6 @@ pub fn expand_deriving_copy( path: path_std!(marker::Copy), additional_bounds: Vec::new(), generics: Bounds::empty(), - is_unsafe: false, supports_unions: true, methods: Vec::new(), associated_types: Vec::new(), diff --git a/compiler/rustc_builtin_macros/src/deriving/clone.rs b/compiler/rustc_builtin_macros/src/deriving/clone.rs index 83317106990..1c507678489 100644 --- a/compiler/rustc_builtin_macros/src/deriving/clone.rs +++ b/compiler/rustc_builtin_macros/src/deriving/clone.rs @@ -15,23 +15,22 @@ pub fn expand_deriving_clone( item: &Annotatable, push: &mut dyn FnMut(Annotatable), ) { - // check if we can use a short form + // The simple form is `fn clone(&self) -> Self { *self }`, possibly with + // some additional `AssertParamIsClone` assertions. // - // the short form is `fn clone(&self) -> Self { *self }` - // - // we can use the short form if: - // - the item is Copy (unfortunately, all we can check is whether it's also deriving Copy) - // - there are no generic parameters (after specialization this limitation can be removed) - // if we used the short form with generics, we'd have to bound the generics with - // Clone + Copy, and then there'd be no Clone impl at all if the user fills in something - // that is Clone but not Copy. and until specialization we can't write both impls. - // - the item is a union with Copy fields - // Unions with generic parameters still can derive Clone because they require Copy - // for deriving, Clone alone is not enough. - // Wherever Clone is implemented for fields is irrelevant so we don't assert it. + // We can use the simple form if either of the following are true. + // - The type derives Copy and there are no generic parameters. (If we + // used the simple form with generics, we'd have to bound the generics + // with Clone + Copy, and then there'd be no Clone impl at all if the + // user fills in something that is Clone but not Copy. After + // specialization we can remove this no-generics limitation.) + // - The item is a union. (Unions with generic parameters still can derive + // Clone because they require Copy for deriving, Clone alone is not + // enough. Whether Clone is implemented for fields is irrelevant so we + // don't assert it.) let bounds; let substructure; - let is_shallow; + let is_simple; match *item { Annotatable::Item(ref annitem) => match annitem.kind { ItemKind::Struct(_, Generics { ref params, .. }) @@ -44,30 +43,25 @@ pub fn expand_deriving_clone( .any(|param| matches!(param.kind, ast::GenericParamKind::Type { .. })) { bounds = vec![]; - is_shallow = true; + is_simple = true; substructure = combine_substructure(Box::new(|c, s, sub| { - cs_clone_shallow("Clone", c, s, sub, false) + cs_clone_simple("Clone", c, s, sub, false) })); } else { bounds = vec![]; - is_shallow = false; + is_simple = false; substructure = combine_substructure(Box::new(|c, s, sub| cs_clone("Clone", c, s, sub))); } } ItemKind::Union(..) => { - bounds = vec![Literal(path_std!(marker::Copy))]; - is_shallow = true; + bounds = vec![Path(path_std!(marker::Copy))]; + is_simple = true; substructure = combine_substructure(Box::new(|c, s, sub| { - cs_clone_shallow("Clone", c, s, sub, true) + cs_clone_simple("Clone", c, s, sub, true) })); } - _ => { - bounds = vec![]; - is_shallow = false; - substructure = - combine_substructure(Box::new(|c, s, sub| cs_clone("Clone", c, s, sub))); - } + _ => cx.span_bug(span, "`#[derive(Clone)]` on wrong item kind"), }, _ => cx.span_bug(span, "`#[derive(Clone)]` on trait item or impl item"), @@ -81,26 +75,24 @@ pub fn expand_deriving_clone( path: path_std!(clone::Clone), additional_bounds: bounds, generics: Bounds::empty(), - is_unsafe: false, supports_unions: true, methods: vec![MethodDef { name: sym::clone, generics: Bounds::empty(), - explicit_self: borrowed_explicit_self(), + explicit_self: true, args: Vec::new(), ret_ty: Self_, attributes: attrs, - is_unsafe: false, unify_fieldless_variants: false, combine_substructure: substructure, }], associated_types: Vec::new(), }; - trait_def.expand_ext(cx, mitem, item, push, is_shallow) + trait_def.expand_ext(cx, mitem, item, push, is_simple) } -fn cs_clone_shallow( +fn cs_clone_simple( name: &str, cx: &mut ExtCtxt<'_>, trait_span: Span, @@ -143,7 +135,7 @@ fn cs_clone_shallow( } _ => cx.span_bug( trait_span, - &format!("unexpected substructure in shallow `derive({})`", name), + &format!("unexpected substructure in simple `derive({})`", name), ), } } diff --git a/compiler/rustc_builtin_macros/src/deriving/cmp/eq.rs b/compiler/rustc_builtin_macros/src/deriving/cmp/eq.rs index f54ded3c87c..cb2ad283a19 100644 --- a/compiler/rustc_builtin_macros/src/deriving/cmp/eq.rs +++ b/compiler/rustc_builtin_macros/src/deriving/cmp/eq.rs @@ -27,16 +27,14 @@ pub fn expand_deriving_eq( path: path_std!(cmp::Eq), additional_bounds: Vec::new(), generics: Bounds::empty(), - is_unsafe: false, supports_unions: true, methods: vec![MethodDef { name: sym::assert_receiver_is_total_eq, generics: Bounds::empty(), - explicit_self: borrowed_explicit_self(), + explicit_self: true, args: vec![], - ret_ty: nil_ty(), + ret_ty: Unit, attributes: attrs, - is_unsafe: false, unify_fieldless_variants: true, combine_substructure: combine_substructure(Box::new(|a, b, c| { cs_total_eq_assert(a, b, c) diff --git a/compiler/rustc_builtin_macros/src/deriving/cmp/ord.rs b/compiler/rustc_builtin_macros/src/deriving/cmp/ord.rs index 2b3ac0a86c1..c7850cd4b4c 100644 --- a/compiler/rustc_builtin_macros/src/deriving/cmp/ord.rs +++ b/compiler/rustc_builtin_macros/src/deriving/cmp/ord.rs @@ -23,16 +23,14 @@ pub fn expand_deriving_ord( path: path_std!(cmp::Ord), additional_bounds: Vec::new(), generics: Bounds::empty(), - is_unsafe: false, supports_unions: false, methods: vec![MethodDef { name: sym::cmp, generics: Bounds::empty(), - explicit_self: borrowed_explicit_self(), - args: vec![(borrowed_self(), sym::other)], - ret_ty: Literal(path_std!(cmp::Ordering)), + explicit_self: true, + args: vec![(self_ref(), sym::other)], + ret_ty: Path(path_std!(cmp::Ordering)), attributes: attrs, - is_unsafe: false, unify_fieldless_variants: true, combine_substructure: combine_substructure(Box::new(|a, b, c| cs_cmp(a, b, c))), }], @@ -99,8 +97,8 @@ pub fn cs_cmp(cx: &mut ExtCtxt<'_>, span: Span, substr: &Substructure<'_>) -> P< cx.expr_match(span, new, vec![eq_arm, neq_arm]) }, cx.expr_path(equals_path.clone()), - Box::new(|cx, span, (self_args, tag_tuple), _non_self_args| { - if self_args.len() != 2 { + Box::new(|cx, span, tag_tuple| { + if tag_tuple.len() != 2 { cx.span_bug(span, "not exactly 2 arguments in `derive(Ord)`") } else { ordering_collapsed(cx, span, tag_tuple) diff --git a/compiler/rustc_builtin_macros/src/deriving/cmp/partial_eq.rs b/compiler/rustc_builtin_macros/src/deriving/cmp/partial_eq.rs index eead8b37024..ca5ca29eb82 100644 --- a/compiler/rustc_builtin_macros/src/deriving/cmp/partial_eq.rs +++ b/compiler/rustc_builtin_macros/src/deriving/cmp/partial_eq.rs @@ -48,7 +48,7 @@ pub fn expand_deriving_partial_eq( None => cx.expr_bool(span, base), } }, - Box::new(|cx, span, _, _| cx.expr_bool(span, !base)), + Box::new(|cx, span, _| cx.expr_bool(span, !base)), cx, span, substr, @@ -69,11 +69,10 @@ pub fn expand_deriving_partial_eq( MethodDef { name: $name, generics: Bounds::empty(), - explicit_self: borrowed_explicit_self(), - args: vec![(borrowed_self(), sym::other)], - ret_ty: Literal(path_local!(bool)), + explicit_self: true, + args: vec![(self_ref(), sym::other)], + ret_ty: Path(path_local!(bool)), attributes: attrs, - is_unsafe: false, unify_fieldless_variants: true, combine_substructure: combine_substructure(Box::new(|a, b, c| $f(a, b, c))), } @@ -102,7 +101,6 @@ pub fn expand_deriving_partial_eq( path: path_std!(cmp::PartialEq), additional_bounds: Vec::new(), generics: Bounds::empty(), - is_unsafe: false, supports_unions: false, methods, associated_types: Vec::new(), diff --git a/compiler/rustc_builtin_macros/src/deriving/cmp/partial_ord.rs b/compiler/rustc_builtin_macros/src/deriving/cmp/partial_ord.rs index d28ac822a1e..07db82fee93 100644 --- a/compiler/rustc_builtin_macros/src/deriving/cmp/partial_ord.rs +++ b/compiler/rustc_builtin_macros/src/deriving/cmp/partial_ord.rs @@ -15,13 +15,9 @@ pub fn expand_deriving_partial_ord( item: &Annotatable, push: &mut dyn FnMut(Annotatable), ) { - let ordering_ty = Literal(path_std!(cmp::Ordering)); - let ret_ty = Literal(Path::new_( - pathvec_std!(option::Option), - None, - vec![Box::new(ordering_ty)], - PathKind::Std, - )); + let ordering_ty = Path(path_std!(cmp::Ordering)); + let ret_ty = + Path(Path::new_(pathvec_std!(option::Option), vec![Box::new(ordering_ty)], PathKind::Std)); let inline = cx.meta_word(span, sym::inline); let attrs = vec![cx.attribute(inline)]; @@ -29,11 +25,10 @@ pub fn expand_deriving_partial_ord( let partial_cmp_def = MethodDef { name: sym::partial_cmp, generics: Bounds::empty(), - explicit_self: borrowed_explicit_self(), - args: vec![(borrowed_self(), sym::other)], + explicit_self: true, + args: vec![(self_ref(), sym::other)], ret_ty, attributes: attrs, - is_unsafe: false, unify_fieldless_variants: true, combine_substructure: combine_substructure(Box::new(|cx, span, substr| { cs_partial_cmp(cx, span, substr) @@ -46,7 +41,6 @@ pub fn expand_deriving_partial_ord( path: path_std!(cmp::PartialOrd), additional_bounds: vec![], generics: Bounds::empty(), - is_unsafe: false, supports_unions: false, methods: vec![partial_cmp_def], associated_types: Vec::new(), @@ -102,8 +96,8 @@ pub fn cs_partial_cmp(cx: &mut ExtCtxt<'_>, span: Span, substr: &Substructure<'_ cx.expr_match(span, new, vec![eq_arm, neq_arm]) }, equals_expr, - Box::new(|cx, span, (self_args, tag_tuple), _non_self_args| { - if self_args.len() != 2 { + Box::new(|cx, span, tag_tuple| { + if tag_tuple.len() != 2 { cx.span_bug(span, "not exactly 2 arguments in `derive(PartialOrd)`") } else { let lft = cx.expr_addr_of(span, cx.expr_ident(span, tag_tuple[0])); diff --git a/compiler/rustc_builtin_macros/src/deriving/debug.rs b/compiler/rustc_builtin_macros/src/deriving/debug.rs index 1fffd6f9727..1411c60c0bf 100644 --- a/compiler/rustc_builtin_macros/src/deriving/debug.rs +++ b/compiler/rustc_builtin_macros/src/deriving/debug.rs @@ -16,8 +16,7 @@ pub fn expand_deriving_debug( push: &mut dyn FnMut(Annotatable), ) { // &mut ::std::fmt::Formatter - let fmtr = - Ptr(Box::new(Literal(path_std!(fmt::Formatter))), Borrowed(None, ast::Mutability::Mut)); + let fmtr = Ref(Box::new(Path(path_std!(fmt::Formatter))), ast::Mutability::Mut); let trait_def = TraitDef { span, @@ -25,16 +24,14 @@ pub fn expand_deriving_debug( path: path_std!(fmt::Debug), additional_bounds: Vec::new(), generics: Bounds::empty(), - is_unsafe: false, supports_unions: false, methods: vec![MethodDef { name: sym::fmt, generics: Bounds::empty(), - explicit_self: borrowed_explicit_self(), + explicit_self: true, args: vec![(fmtr, sym::f)], - ret_ty: Literal(path_std!(fmt::Result)), + ret_ty: Path(path_std!(fmt::Result)), attributes: Vec::new(), - is_unsafe: false, unify_fieldless_variants: false, combine_substructure: combine_substructure(Box::new(|a, b, c| { show_substructure(a, b, c) @@ -64,8 +61,6 @@ fn show_substructure(cx: &mut ExtCtxt<'_>, span: Span, substr: &Substructure<'_> let (is_struct, args_per_field) = match vdata { ast::VariantData::Unit(..) => { // Special fast path for unit variants. - //let fn_path_write_str = cx.std_path(&[sym::fmt, sym::Formatter, sym::write_str]); - //return cx.expr_call_global(span, fn_path_write_str, vec![fmt, name]); assert!(fields.is_empty()); (false, 0) } diff --git a/compiler/rustc_builtin_macros/src/deriving/decodable.rs b/compiler/rustc_builtin_macros/src/deriving/decodable.rs index b39f35a9d40..16154fb4d03 100644 --- a/compiler/rustc_builtin_macros/src/deriving/decodable.rs +++ b/compiler/rustc_builtin_macros/src/deriving/decodable.rs @@ -23,40 +23,29 @@ pub fn expand_deriving_rustc_decodable( let trait_def = TraitDef { span, attributes: Vec::new(), - path: Path::new_(vec![krate, sym::Decodable], None, vec![], PathKind::Global), + path: Path::new_(vec![krate, sym::Decodable], vec![], PathKind::Global), additional_bounds: Vec::new(), generics: Bounds::empty(), - is_unsafe: false, supports_unions: false, methods: vec![MethodDef { name: sym::decode, generics: Bounds { bounds: vec![( typaram, - vec![Path::new_(vec![krate, sym::Decoder], None, vec![], PathKind::Global)], + vec![Path::new_(vec![krate, sym::Decoder], vec![], PathKind::Global)], )], }, - explicit_self: None, - args: vec![( - Ptr(Box::new(Literal(Path::new_local(typaram))), Borrowed(None, Mutability::Mut)), - sym::d, - )], - ret_ty: Literal(Path::new_( + explicit_self: false, + args: vec![(Ref(Box::new(Path(Path::new_local(typaram))), Mutability::Mut), sym::d)], + ret_ty: Path(Path::new_( pathvec_std!(result::Result), - None, vec![ Box::new(Self_), - Box::new(Literal(Path::new_( - vec![typaram, sym::Error], - None, - vec![], - PathKind::Local, - ))), + Box::new(Path(Path::new_(vec![typaram, sym::Error], vec![], PathKind::Local))), ], PathKind::Std, )), attributes: Vec::new(), - is_unsafe: false, unify_fieldless_variants: false, combine_substructure: combine_substructure(Box::new(|a, b, c| { decodable_substructure(a, b, c, krate) diff --git a/compiler/rustc_builtin_macros/src/deriving/default.rs b/compiler/rustc_builtin_macros/src/deriving/default.rs index b49331e2875..d41b25343b0 100644 --- a/compiler/rustc_builtin_macros/src/deriving/default.rs +++ b/compiler/rustc_builtin_macros/src/deriving/default.rs @@ -30,16 +30,14 @@ pub fn expand_deriving_default( path: Path::new(vec![kw::Default, sym::Default]), additional_bounds: Vec::new(), generics: Bounds::empty(), - is_unsafe: false, supports_unions: false, methods: vec![MethodDef { name: kw::Default, generics: Bounds::empty(), - explicit_self: None, + explicit_self: false, args: Vec::new(), ret_ty: Self_, attributes: attrs, - is_unsafe: false, unify_fieldless_variants: false, combine_substructure: combine_substructure(Box::new(|cx, trait_span, substr| { match substr.fields { diff --git a/compiler/rustc_builtin_macros/src/deriving/encodable.rs b/compiler/rustc_builtin_macros/src/deriving/encodable.rs index 6151a80a56d..7dc0584618d 100644 --- a/compiler/rustc_builtin_macros/src/deriving/encodable.rs +++ b/compiler/rustc_builtin_macros/src/deriving/encodable.rs @@ -108,40 +108,29 @@ pub fn expand_deriving_rustc_encodable( let trait_def = TraitDef { span, attributes: Vec::new(), - path: Path::new_(vec![krate, sym::Encodable], None, vec![], PathKind::Global), + path: Path::new_(vec![krate, sym::Encodable], vec![], PathKind::Global), additional_bounds: Vec::new(), generics: Bounds::empty(), - is_unsafe: false, supports_unions: false, methods: vec![MethodDef { name: sym::encode, generics: Bounds { bounds: vec![( typaram, - vec![Path::new_(vec![krate, sym::Encoder], None, vec![], PathKind::Global)], + vec![Path::new_(vec![krate, sym::Encoder], vec![], PathKind::Global)], )], }, - explicit_self: borrowed_explicit_self(), - args: vec![( - Ptr(Box::new(Literal(Path::new_local(typaram))), Borrowed(None, Mutability::Mut)), - sym::s, - )], - ret_ty: Literal(Path::new_( + explicit_self: true, + args: vec![(Ref(Box::new(Path(Path::new_local(typaram))), Mutability::Mut), sym::s)], + ret_ty: Path(Path::new_( pathvec_std!(result::Result), - None, vec![ - Box::new(Tuple(Vec::new())), - Box::new(Literal(Path::new_( - vec![typaram, sym::Error], - None, - vec![], - PathKind::Local, - ))), + Box::new(Unit), + Box::new(Path(Path::new_(vec![typaram, sym::Error], vec![], PathKind::Local))), ], PathKind::Std, )), attributes: Vec::new(), - is_unsafe: false, unify_fieldless_variants: false, combine_substructure: combine_substructure(Box::new(|a, b, c| { encodable_substructure(a, b, c, krate) diff --git a/compiler/rustc_builtin_macros/src/deriving/generic/mod.rs b/compiler/rustc_builtin_macros/src/deriving/generic/mod.rs index 8347cded2fe..2a9e37081e0 100644 --- a/compiler/rustc_builtin_macros/src/deriving/generic/mod.rs +++ b/compiler/rustc_builtin_macros/src/deriving/generic/mod.rs @@ -66,7 +66,7 @@ //! //! # "`cs`" functions //! -//! The `cs_...` functions ("combine substructure) are designed to +//! The `cs_...` functions ("combine substructure") are designed to //! make life easier by providing some pre-made recipes for common //! threads; mostly calling the function being derived on all the //! arguments and then combining them back together in some way (or @@ -146,8 +146,6 @@ //! //! ```{.text} //! EnumNonMatchingCollapsed( -//! vec![<ident of self>, <ident of __arg_1>], -//! &[<ast::Variant for C0>, <ast::Variant for C1>], //! &[<ident for self index value>, <ident of __arg_1 index value>]) //! ``` //! @@ -190,7 +188,7 @@ use rustc_expand::base::{Annotatable, ExtCtxt}; use rustc_span::symbol::{kw, sym, Ident, Symbol}; use rustc_span::Span; -use ty::{Bounds, Path, Ptr, PtrTy, Self_, Ty}; +use ty::{Bounds, Path, Ref, Self_, Ty}; use crate::deriving; @@ -212,9 +210,6 @@ pub struct TraitDef<'a> { /// Any extra lifetimes and/or bounds, e.g., `D: serialize::Decoder` pub generics: Bounds, - /// Is it an `unsafe` trait? - pub is_unsafe: bool, - /// Can this trait be derived for unions? pub supports_unions: bool, @@ -229,10 +224,8 @@ pub struct MethodDef<'a> { /// List of generics, e.g., `R: rand::Rng` pub generics: Bounds, - /// Whether there is a self argument (outer Option) i.e., whether - /// this is a static function, and whether it is a pointer (inner - /// Option) - pub explicit_self: Option<Option<PtrTy>>, + /// Is there is a `&self` argument? If not, it is a static function. + pub explicit_self: bool, /// Arguments other than the self argument pub args: Vec<(Ty, Symbol)>, @@ -242,9 +235,6 @@ pub struct MethodDef<'a> { pub attributes: Vec<ast::Attribute>, - // Is it an `unsafe fn`? - pub is_unsafe: bool, - /// Can we combine fieldless variants for enums into a single match arm? pub unify_fieldless_variants: bool, @@ -255,14 +245,7 @@ pub struct MethodDef<'a> { pub struct Substructure<'a> { /// ident of self pub type_ident: Ident, - /// ident of the method - pub method_ident: Ident, - /// dereferenced access to any [`Self_`] or [`Ptr(Self_, _)`][ptr] arguments - /// - /// [`Self_`]: ty::Ty::Self_ - /// [ptr]: ty::Ty::Ptr - pub self_args: &'a [P<Expr>], - /// verbatim access to any other arguments + /// verbatim access to any non-self arguments pub nonself_args: &'a [P<Expr>], pub fields: &'a SubstructureFields<'a>, } @@ -299,13 +282,10 @@ pub enum SubstructureFields<'a> { /// variant. EnumMatching(usize, usize, &'a ast::Variant, Vec<FieldInfo<'a>>), - /// Non-matching variants of the enum, but with all state hidden from - /// the consequent code. The first component holds `Ident`s for all of - /// the `Self` arguments; the second component is a slice of all of the - /// variants for the enum itself, and the third component is a list of - /// `Ident`s bound to the variant index values for each of the actual - /// input `Self` arguments. - EnumNonMatchingCollapsed(Vec<Ident>, &'a [ast::Variant], &'a [Ident]), + /// Non-matching variants of the enum, but with all state hidden from the + /// consequent code. The field is a list of `Ident`s bound to the variant + /// index values for each of the actual input `Self` arguments. + EnumNonMatchingCollapsed(&'a [Ident]), /// A static method where `Self` is a struct. StaticStruct(&'a ast::VariantData, StaticFields), @@ -318,13 +298,10 @@ pub enum SubstructureFields<'a> { pub type CombineSubstructureFunc<'a> = Box<dyn FnMut(&mut ExtCtxt<'_>, Span, &Substructure<'_>) -> P<Expr> + 'a>; -/// Deal with non-matching enum variants. The tuple is a list of -/// identifiers (one for each `Self` argument, which could be any of the -/// variants since they have been collapsed together) and the identifiers -/// holding the variant index value for each of the `Self` arguments. The -/// last argument is all the non-`Self` args of the method being derived. +/// Deal with non-matching enum variants. The slice is the identifiers holding +/// the variant index value for each of the `Self` arguments. pub type EnumNonMatchCollapsedFunc<'a> = - Box<dyn FnMut(&mut ExtCtxt<'_>, Span, (&[Ident], &[Ident]), &[P<Expr>]) -> P<Expr> + 'a>; + Box<dyn FnMut(&mut ExtCtxt<'_>, Span, &[Ident]) -> P<Expr> + 'a>; pub fn combine_substructure( f: CombineSubstructureFunc<'_>, @@ -452,6 +429,7 @@ impl<'a> TraitDef<'a> { generics, from_scratch, use_temporaries, + is_packed, ), ast::ItemKind::Enum(ref enum_def, ref generics) => { // We ignore `use_temporaries` here, because @@ -471,6 +449,7 @@ impl<'a> TraitDef<'a> { generics, from_scratch, use_temporaries, + is_packed, ) } else { cx.span_err(mitem.span, "this trait cannot be derived for unions"); @@ -727,14 +706,12 @@ impl<'a> TraitDef<'a> { let mut a = vec![attr, unused_qual]; a.extend(self.attributes.iter().cloned()); - let unsafety = if self.is_unsafe { ast::Unsafe::Yes(self.span) } else { ast::Unsafe::No }; - cx.item( self.span, Ident::empty(), a, ast::ItemKind::Impl(Box::new(ast::Impl { - unsafety, + unsafety: ast::Unsafe::No, polarity: ast::ImplPolarity::Positive, defaultness: ast::Defaultness::Final, constness: ast::Const::No, @@ -754,6 +731,7 @@ impl<'a> TraitDef<'a> { generics: &Generics, from_scratch: bool, use_temporaries: bool, + is_packed: bool, ) -> P<ast::Item> { let field_tys: Vec<P<ast::Ty>> = struct_def.fields().iter().map(|field| field.ty.clone()).collect(); @@ -771,7 +749,6 @@ impl<'a> TraitDef<'a> { self, struct_def, type_ident, - &self_args, &nonself_args, ) } else { @@ -783,6 +760,7 @@ impl<'a> TraitDef<'a> { &self_args, &nonself_args, use_temporaries, + is_packed, ) }; @@ -820,7 +798,6 @@ impl<'a> TraitDef<'a> { self, enum_def, type_ident, - &self_args, &nonself_args, ) } else { @@ -848,18 +825,11 @@ impl<'a> MethodDef<'a> { cx: &mut ExtCtxt<'_>, trait_: &TraitDef<'_>, type_ident: Ident, - self_args: &[P<Expr>], nonself_args: &[P<Expr>], fields: &SubstructureFields<'_>, ) -> P<Expr> { let span = trait_.span; - let substructure = Substructure { - type_ident, - method_ident: Ident::new(self.name, span), - self_args, - nonself_args, - fields, - }; + let substructure = Substructure { type_ident, nonself_args, fields }; let mut f = self.combine_substructure.borrow_mut(); let f: &mut CombineSubstructureFunc<'_> = &mut *f; f(cx, span, &substructure) @@ -876,7 +846,7 @@ impl<'a> MethodDef<'a> { } fn is_static(&self) -> bool { - self.explicit_self.is_none() + !self.explicit_self } fn split_self_nonself_args( @@ -889,17 +859,15 @@ impl<'a> MethodDef<'a> { let mut self_args = Vec::new(); let mut nonself_args = Vec::new(); let mut arg_tys = Vec::new(); - let mut nonstatic = false; let span = trait_.span; - let ast_explicit_self = self.explicit_self.as_ref().map(|self_ptr| { - let (self_expr, explicit_self) = ty::get_explicit_self(cx, span, self_ptr); - + let ast_explicit_self = if self.explicit_self { + let (self_expr, explicit_self) = ty::get_explicit_self(cx, span); self_args.push(self_expr); - nonstatic = true; - - explicit_self - }); + Some(explicit_self) + } else { + None + }; for (ty, name) in self.args.iter() { let ast_ty = ty.to_ty(cx, span, type_ident, generics); @@ -911,10 +879,10 @@ impl<'a> MethodDef<'a> { match *ty { // for static methods, just treat any Self // arguments as a normal arg - Self_ if nonstatic => { + Self_ if !self.is_static() => { self_args.push(arg_expr); } - Ptr(ref ty, _) if matches!(**ty, Self_) && nonstatic => { + Ref(ref ty, _) if matches!(**ty, Self_) && !self.is_static() => { self_args.push(cx.expr_deref(span, arg_expr)) } _ => { @@ -955,15 +923,9 @@ impl<'a> MethodDef<'a> { let fn_decl = cx.fn_decl(args, ast::FnRetTy::Ty(ret_type)); let body_block = cx.block_expr(body); - let unsafety = if self.is_unsafe { ast::Unsafe::Yes(span) } else { ast::Unsafe::No }; - let trait_lo_sp = span.shrink_to_lo(); - let sig = ast::FnSig { - header: ast::FnHeader { unsafety, ext: ast::Extern::None, ..ast::FnHeader::default() }, - decl: fn_decl, - span, - }; + let sig = ast::FnSig { header: ast::FnHeader::default(), decl: fn_decl, span }; let defaultness = ast::Defaultness::Final; // Create the method. @@ -987,6 +949,7 @@ impl<'a> MethodDef<'a> { }) } + /// The normal case uses field access. /// ``` /// #[derive(PartialEq)] /// # struct Dummy; @@ -995,33 +958,21 @@ impl<'a> MethodDef<'a> { /// // equivalent to: /// impl PartialEq for A { /// fn eq(&self, other: &A) -> bool { - /// match *self { - /// A {x: ref __self_0_0, y: ref __self_0_1} => { - /// match *other { - /// A {x: ref __self_1_0, y: ref __self_1_1} => { - /// __self_0_0.eq(__self_1_0) && __self_0_1.eq(__self_1_1) - /// } - /// } - /// } - /// } + /// self.x == other.x && self.y == other.y /// } /// } /// ``` - /// or if A is repr(packed) - note fields are matched by-value - /// instead of by-reference. + /// But if the struct is `repr(packed)`, we can't use something like + /// `&self.x` on a packed type (as required for e.g. `Debug` and `Hash`) + /// because that might cause an unaligned ref. So we use let-destructuring + /// instead. /// ``` /// # struct A { x: i32, y: i32 } /// impl PartialEq for A { /// fn eq(&self, other: &A) -> bool { - /// match *self { - /// A {x: __self_0_0, y: __self_0_1} => { - /// match other { - /// A {x: __self_1_0, y: __self_1_1} => { - /// __self_0_0.eq(&__self_1_0) && __self_0_1.eq(&__self_1_1) - /// } - /// } - /// } - /// } + /// let Self { x: ref __self_0_0, y: ref __self_0_1 } = *self; + /// let Self { x: ref __self_1_0, y: ref __self_1_1 } = *other; + /// *__self_0_0 == *__self_1_0 && *__self_0_1 == *__self_1_1 /// } /// } /// ``` @@ -1034,24 +985,33 @@ impl<'a> MethodDef<'a> { self_args: &[P<Expr>], nonself_args: &[P<Expr>], use_temporaries: bool, + is_packed: bool, ) -> P<Expr> { let mut raw_fields = Vec::new(); // Vec<[fields of self], [fields of next Self arg], [etc]> let span = trait_.span; let mut patterns = Vec::new(); - for i in 0..self_args.len() { - // We could use `type_ident` instead of `Self`, but in the case of a type parameter - // shadowing the struct name, that causes a second, unnecessary E0578 error. #97343 - let struct_path = cx.path(span, vec![Ident::new(kw::SelfUpper, type_ident.span)]); - let (pat, ident_expr) = trait_.create_struct_pattern( - cx, - struct_path, - struct_def, - &format!("__self_{}", i), - ast::Mutability::Not, - use_temporaries, - ); - patterns.push(pat); - raw_fields.push(ident_expr); + + for (i, self_arg) in self_args.iter().enumerate() { + let ident_exprs = if !is_packed { + trait_.create_struct_field_accesses(cx, self_arg, struct_def) + } else { + // Get the pattern for the let-destructuring. + // + // We could use `type_ident` instead of `Self`, but in the case of a type parameter + // shadowing the struct name, that causes a second, unnecessary E0578 error. #97343 + let struct_path = cx.path(span, vec![Ident::new(kw::SelfUpper, type_ident.span)]); + let (pat, ident_exprs) = trait_.create_struct_pattern( + cx, + struct_path, + struct_def, + &format!("__self_{}", i), + ast::Mutability::Not, + use_temporaries, + ); + patterns.push(pat); + ident_exprs + }; + raw_fields.push(ident_exprs); } // transpose raw_fields @@ -1078,24 +1038,26 @@ impl<'a> MethodDef<'a> { cx.span_bug(span, "no `self` parameter for method in generic `derive`") }; - // body of the inner most destructuring match let mut body = self.call_substructure_method( cx, trait_, type_ident, - self_args, nonself_args, &Struct(struct_def, fields), ); - // make a series of nested matches, to destructure the - // structs. This is actually right-to-left, but it shouldn't - // matter. - for (arg_expr, pat) in iter::zip(self_args, patterns) { - body = cx.expr_match(span, arg_expr.clone(), vec![cx.arm(span, pat.clone(), body)]) - } + if !is_packed { + body.span = span; + body + } else { + // Do the let-destructuring. + let mut stmts: Vec<_> = iter::zip(self_args, patterns) + .map(|(arg_expr, pat)| cx.stmt_let_pat(span, pat, arg_expr.clone())) + .collect(); + stmts.push(cx.stmt_expr(body)); - body + cx.expr_block(cx.block(span, stmts)) + } } fn expand_static_struct_method_body( @@ -1104,7 +1066,6 @@ impl<'a> MethodDef<'a> { trait_: &TraitDef<'_>, struct_def: &VariantData, type_ident: Ident, - self_args: &[P<Expr>], nonself_args: &[P<Expr>], ) -> P<Expr> { let summary = trait_.summarise_struct(cx, struct_def); @@ -1113,7 +1074,6 @@ impl<'a> MethodDef<'a> { cx, trait_, type_ident, - self_args, nonself_args, &StaticStruct(struct_def, summary), ) @@ -1184,11 +1144,6 @@ impl<'a> MethodDef<'a> { ) .collect::<Vec<String>>(); - let self_arg_idents = self_arg_names - .iter() - .map(|name| Ident::from_str_and_span(name, span)) - .collect::<Vec<Ident>>(); - // The `vi_idents` will be bound, solely in the catch-all, to // a series of let statements mapping each self_arg to an int // value corresponding to its discriminant. @@ -1203,8 +1158,7 @@ impl<'a> MethodDef<'a> { // Builds, via callback to call_substructure_method, the // delegated expression that handles the catch-all case, // using `__variants_tuple` to drive logic if necessary. - let catch_all_substructure = - EnumNonMatchingCollapsed(self_arg_idents, &variants, &vi_idents); + let catch_all_substructure = EnumNonMatchingCollapsed(&vi_idents); let first_fieldless = variants.iter().find(|v| v.data.fields().is_empty()); @@ -1303,7 +1257,6 @@ impl<'a> MethodDef<'a> { cx, trait_, type_ident, - &self_args[..], nonself_args, &substructure, ); @@ -1322,7 +1275,6 @@ impl<'a> MethodDef<'a> { cx, trait_, type_ident, - &self_args[..], nonself_args, &substructure, )) @@ -1393,7 +1345,6 @@ impl<'a> MethodDef<'a> { cx, trait_, type_ident, - &self_args[..], nonself_args, &catch_all_substructure, ); @@ -1491,7 +1442,6 @@ impl<'a> MethodDef<'a> { trait_: &TraitDef<'_>, enum_def: &EnumDef, type_ident: Ident, - self_args: &[P<Expr>], nonself_args: &[P<Expr>], ) -> P<Expr> { let summary = enum_def @@ -1507,7 +1457,6 @@ impl<'a> MethodDef<'a> { cx, trait_, type_ident, - self_args, nonself_args, &StaticEnum(enum_def, summary), ) @@ -1578,8 +1527,6 @@ impl<'a> TraitDef<'a> { paths.push(ident.with_span_pos(sp)); let val = cx.expr_path(cx.path_ident(sp, ident)); let val = if use_temporaries { val } else { cx.expr_deref(sp, val) }; - let val = cx.expr(sp, ast::ExprKind::Paren(val)); - ident_exprs.push((sp, struct_field.ident, val, &struct_field.attrs[..])); } @@ -1611,6 +1558,39 @@ impl<'a> TraitDef<'a> { (pattern, ident_exprs) } + fn create_struct_field_accesses( + &self, + cx: &mut ExtCtxt<'_>, + mut self_arg: &P<Expr>, + struct_def: &'a VariantData, + ) -> Vec<(Span, Option<Ident>, P<Expr>, &'a [ast::Attribute])> { + let mut ident_exprs = Vec::new(); + for (i, struct_field) in struct_def.fields().iter().enumerate() { + let sp = struct_field.span.with_ctxt(self.span.ctxt()); + + // We don't the need the deref, if there is one. + if let ast::ExprKind::Unary(ast::UnOp::Deref, inner) = &self_arg.kind { + self_arg = inner; + } + + // Note: we must use `struct_field.span` rather than `span` in the + // `unwrap_or_else` case otherwise the hygiene is wrong and we get + // "field `0` of struct `Point` is private" errors on tuple + // structs. + let val = cx.expr( + sp, + ast::ExprKind::Field( + self_arg.clone(), + struct_field.ident.unwrap_or_else(|| { + Ident::from_str_and_span(&i.to_string(), struct_field.span) + }), + ), + ); + ident_exprs.push((sp, struct_field.ident, val, &struct_field.attrs[..])); + } + ident_exprs + } + fn create_enum_variant_pattern( &self, cx: &mut ExtCtxt<'_>, @@ -1628,7 +1608,7 @@ impl<'a> TraitDef<'a> { // helpful premade recipes -pub fn cs_fold_fields<'a, F>( +fn cs_fold_fields<'a, F>( use_foldl: bool, mut f: F, base: P<Expr>, @@ -1650,21 +1630,19 @@ where } } -pub fn cs_fold_enumnonmatch( +fn cs_fold_enumnonmatch( mut enum_nonmatch_f: EnumNonMatchCollapsedFunc<'_>, cx: &mut ExtCtxt<'_>, trait_span: Span, substructure: &Substructure<'_>, ) -> P<Expr> { match *substructure.fields { - EnumNonMatchingCollapsed(ref all_args, _, tuple) => { - enum_nonmatch_f(cx, trait_span, (&all_args[..], tuple), substructure.nonself_args) - } + EnumNonMatchingCollapsed(tuple) => enum_nonmatch_f(cx, trait_span, tuple), _ => cx.span_bug(trait_span, "cs_fold_enumnonmatch expected an EnumNonMatchingCollapsed"), } } -pub fn cs_fold_static(cx: &mut ExtCtxt<'_>, trait_span: Span) -> P<Expr> { +fn cs_fold_static(cx: &mut ExtCtxt<'_>, trait_span: Span) -> P<Expr> { cx.span_bug(trait_span, "static function in `derive`") } @@ -1701,7 +1679,6 @@ where /// fields. /// When the `substructure` is an `EnumNonMatchingCollapsed`, the result of `enum_nonmatch_f` /// is returned. Statics may not be folded over. -/// See `cs_op` in `partial_ord.rs` for a model example. pub fn cs_fold1<F, B>( use_foldl: bool, f: F, @@ -1717,22 +1694,21 @@ where { match *substructure.fields { EnumMatching(.., ref all_fields) | Struct(_, ref all_fields) => { - let (base, all_fields) = match (all_fields.is_empty(), use_foldl) { + let (base, rest) = match (all_fields.is_empty(), use_foldl) { (false, true) => { - let field = &all_fields[0]; - let args = (field.span, field.self_.clone(), &field.other[..]); - (b(cx, Some(args)), &all_fields[1..]) + let (first, rest) = all_fields.split_first().unwrap(); + let args = (first.span, first.self_.clone(), &first.other[..]); + (b(cx, Some(args)), rest) } (false, false) => { - let idx = all_fields.len() - 1; - let field = &all_fields[idx]; - let args = (field.span, field.self_.clone(), &field.other[..]); - (b(cx, Some(args)), &all_fields[..idx]) + let (last, rest) = all_fields.split_last().unwrap(); + let args = (last.span, last.self_.clone(), &last.other[..]); + (b(cx, Some(args)), rest) } (true, _) => (b(cx, None), &all_fields[..]), }; - cs_fold_fields(use_foldl, f, base, cx, all_fields) + cs_fold_fields(use_foldl, f, base, cx, rest) } EnumNonMatchingCollapsed(..) => { cs_fold_enumnonmatch(enum_nonmatch_f, cx, trait_span, substructure) diff --git a/compiler/rustc_builtin_macros/src/deriving/generic/ty.rs b/compiler/rustc_builtin_macros/src/deriving/generic/ty.rs index 7a418003250..4b20d87629d 100644 --- a/compiler/rustc_builtin_macros/src/deriving/generic/ty.rs +++ b/compiler/rustc_builtin_macros/src/deriving/generic/ty.rs @@ -1,7 +1,6 @@ //! A mini version of ast::Ty, which is easier to use, and features an explicit `Self` type to use //! when specifying impls to be derived. -pub use PtrTy::*; pub use Ty::*; use rustc_ast::ptr::P; @@ -11,22 +10,11 @@ use rustc_span::source_map::{respan, DUMMY_SP}; use rustc_span::symbol::{kw, Ident, Symbol}; use rustc_span::Span; -/// The types of pointers -#[derive(Clone)] -pub enum PtrTy { - /// &'lifetime mut - Borrowed(Option<Ident>, ast::Mutability), - /// *mut - #[allow(dead_code)] - Raw(ast::Mutability), -} - /// A path, e.g., `::std::option::Option::<i32>` (global). Has support -/// for type parameters and a lifetime. +/// for type parameters. #[derive(Clone)] pub struct Path { path: Vec<Symbol>, - lifetime: Option<Ident>, params: Vec<Box<Ty>>, kind: PathKind, } @@ -40,18 +28,13 @@ pub enum PathKind { impl Path { pub fn new(path: Vec<Symbol>) -> Path { - Path::new_(path, None, Vec::new(), PathKind::Std) + Path::new_(path, Vec::new(), PathKind::Std) } pub fn new_local(path: Symbol) -> Path { - Path::new_(vec![path], None, Vec::new(), PathKind::Local) + Path::new_(vec![path], Vec::new(), PathKind::Local) } - pub fn new_( - path: Vec<Symbol>, - lifetime: Option<Ident>, - params: Vec<Box<Ty>>, - kind: PathKind, - ) -> Path { - Path { path, lifetime, params, kind } + pub fn new_(path: Vec<Symbol>, params: Vec<Box<Ty>>, kind: PathKind) -> Path { + Path { path, params, kind } } pub fn to_ty( @@ -71,10 +54,8 @@ impl Path { self_generics: &Generics, ) -> ast::Path { let mut idents = self.path.iter().map(|s| Ident::new(*s, span)).collect(); - let lt = mk_lifetimes(cx, span, &self.lifetime); let tys = self.params.iter().map(|t| t.to_ty(cx, span, self_ty, self_generics)); - let params = - lt.into_iter().map(GenericArg::Lifetime).chain(tys.map(GenericArg::Type)).collect(); + let params = tys.map(GenericArg::Type).collect(); match self.kind { PathKind::Global => cx.path_all(span, true, idents, params), @@ -92,40 +73,17 @@ impl Path { #[derive(Clone)] pub enum Ty { Self_, - /// &/Box/ Ty - Ptr(Box<Ty>, PtrTy), + /// A reference. + Ref(Box<Ty>, ast::Mutability), /// `mod::mod::Type<[lifetime], [Params...]>`, including a plain type /// parameter, and things like `i32` - Literal(Path), - /// includes unit - Tuple(Vec<Ty>), -} - -pub fn borrowed_ptrty() -> PtrTy { - Borrowed(None, ast::Mutability::Not) -} -pub fn borrowed(ty: Box<Ty>) -> Ty { - Ptr(ty, borrowed_ptrty()) -} - -pub fn borrowed_explicit_self() -> Option<Option<PtrTy>> { - Some(Some(borrowed_ptrty())) -} - -pub fn borrowed_self() -> Ty { - borrowed(Box::new(Self_)) + Path(Path), + /// For () return types. + Unit, } -pub fn nil_ty() -> Ty { - Tuple(Vec::new()) -} - -fn mk_lifetime(cx: &ExtCtxt<'_>, span: Span, lt: &Option<Ident>) -> Option<ast::Lifetime> { - lt.map(|ident| cx.lifetime(span, ident)) -} - -fn mk_lifetimes(cx: &ExtCtxt<'_>, span: Span, lt: &Option<Ident>) -> Vec<ast::Lifetime> { - mk_lifetime(cx, span, lt).into_iter().collect() +pub fn self_ref() -> Ty { + Ref(Box::new(Self_), ast::Mutability::Not) } impl Ty { @@ -136,23 +94,15 @@ impl Ty { self_ty: Ident, self_generics: &Generics, ) -> P<ast::Ty> { - match *self { - Ptr(ref ty, ref ptr) => { + match self { + Ref(ty, mutbl) => { let raw_ty = ty.to_ty(cx, span, self_ty, self_generics); - match *ptr { - Borrowed(ref lt, mutbl) => { - let lt = mk_lifetime(cx, span, lt); - cx.ty_rptr(span, raw_ty, lt, mutbl) - } - Raw(mutbl) => cx.ty_ptr(span, raw_ty, mutbl), - } + cx.ty_rptr(span, raw_ty, None, *mutbl) } - Literal(ref p) => p.to_ty(cx, span, self_ty, self_generics), + Path(p) => p.to_ty(cx, span, self_ty, self_generics), Self_ => cx.ty_path(self.to_path(cx, span, self_ty, self_generics)), - Tuple(ref fields) => { - let ty = ast::TyKind::Tup( - fields.iter().map(|f| f.to_ty(cx, span, self_ty, self_generics)).collect(), - ); + Unit => { + let ty = ast::TyKind::Tup(vec![]); cx.ty(span, ty) } } @@ -185,9 +135,9 @@ impl Ty { cx.path_all(span, false, vec![self_ty], params) } - Literal(ref p) => p.to_path(cx, span, self_ty, generics), - Ptr(..) => cx.span_bug(span, "pointer in a path in generic `derive`"), - Tuple(..) => cx.span_bug(span, "tuple in a path in generic `derive`"), + Path(ref p) => p.to_path(cx, span, self_ty, generics), + Ref(..) => cx.span_bug(span, "ref in a path in generic `derive`"), + Unit => cx.span_bug(span, "unit in a path in generic `derive`"), } } } @@ -245,28 +195,10 @@ impl Bounds { } } -pub fn get_explicit_self( - cx: &ExtCtxt<'_>, - span: Span, - self_ptr: &Option<PtrTy>, -) -> (P<Expr>, ast::ExplicitSelf) { +pub fn get_explicit_self(cx: &ExtCtxt<'_>, span: Span) -> (P<Expr>, ast::ExplicitSelf) { // this constructs a fresh `self` path let self_path = cx.expr_self(span); - match *self_ptr { - None => (self_path, respan(span, SelfKind::Value(ast::Mutability::Not))), - Some(ref ptr) => { - let self_ty = respan( - span, - match *ptr { - Borrowed(ref lt, mutbl) => { - let lt = lt.map(|s| cx.lifetime(span, s)); - SelfKind::Region(lt, mutbl) - } - Raw(_) => cx.span_bug(span, "attempted to use *self in deriving definition"), - }, - ); - let self_expr = cx.expr_deref(span, self_path); - (self_expr, self_ty) - } - } + let self_ty = respan(span, SelfKind::Region(None, ast::Mutability::Not)); + let self_expr = cx.expr_deref(span, self_path); + (self_expr, self_ty) } diff --git a/compiler/rustc_builtin_macros/src/deriving/hash.rs b/compiler/rustc_builtin_macros/src/deriving/hash.rs index f1d46f03bad..9790449c4b3 100644 --- a/compiler/rustc_builtin_macros/src/deriving/hash.rs +++ b/compiler/rustc_builtin_macros/src/deriving/hash.rs @@ -15,7 +15,7 @@ pub fn expand_deriving_hash( item: &Annotatable, push: &mut dyn FnMut(Annotatable), ) { - let path = Path::new_(pathvec_std!(hash::Hash), None, vec![], PathKind::Std); + let path = Path::new_(pathvec_std!(hash::Hash), vec![], PathKind::Std); let typaram = sym::__H; @@ -26,16 +26,14 @@ pub fn expand_deriving_hash( path, additional_bounds: Vec::new(), generics: Bounds::empty(), - is_unsafe: false, supports_unions: false, methods: vec![MethodDef { name: sym::hash, generics: Bounds { bounds: vec![(typaram, vec![path_std!(hash::Hasher)])] }, - explicit_self: borrowed_explicit_self(), - args: vec![(Ptr(Box::new(Literal(arg)), Borrowed(None, Mutability::Mut)), sym::state)], - ret_ty: nil_ty(), + explicit_self: true, + args: vec![(Ref(Box::new(Path(arg)), Mutability::Mut), sym::state)], + ret_ty: Unit, attributes: vec![], - is_unsafe: false, unify_fieldless_variants: true, combine_substructure: combine_substructure(Box::new(|a, b, c| { hash_substructure(a, b, c) diff --git a/compiler/rustc_codegen_cranelift/src/base.rs b/compiler/rustc_codegen_cranelift/src/base.rs index fbe830b2b10..f71d749df62 100644 --- a/compiler/rustc_codegen_cranelift/src/base.rs +++ b/compiler/rustc_codegen_cranelift/src/base.rs @@ -635,29 +635,6 @@ fn codegen_stmt<'tcx>( let (ptr, _extra) = operand.load_scalar_pair(fx); lval.write_cvalue(fx, CValue::by_val(ptr, dest_layout)) } - } else if let ty::Adt(adt_def, _substs) = from_ty.kind() { - // enum -> discriminant value - assert!(adt_def.is_enum()); - match to_ty.kind() { - ty::Uint(_) | ty::Int(_) => {} - _ => unreachable!("cast adt {} -> {}", from_ty, to_ty), - } - let to_clif_ty = fx.clif_type(to_ty).unwrap(); - - let discriminant = crate::discriminant::codegen_get_discriminant( - fx, - operand, - fx.layout_of(operand.layout().ty.discriminant_ty(fx.tcx)), - ) - .load_scalar(fx); - - let res = crate::cast::clif_intcast( - fx, - discriminant, - to_clif_ty, - to_ty.is_signed(), - ); - lval.write_cvalue(fx, CValue::by_val(res, dest_layout)); } else { let to_clif_ty = fx.clif_type(to_ty).unwrap(); let from = operand.load_scalar(fx); @@ -686,6 +663,7 @@ fn codegen_stmt<'tcx>( substs, ty::ClosureKind::FnOnce, ) + .expect("failed to normalize and resolve closure during codegen") .polymorphize(fx.tcx); let func_ref = fx.get_function_ref(instance); let func_addr = fx.bcx.ins().func_addr(fx.pointer_type, func_ref); diff --git a/compiler/rustc_codegen_cranelift/src/lib.rs b/compiler/rustc_codegen_cranelift/src/lib.rs index 9d2e12f9898..be2d3108c5f 100644 --- a/compiler/rustc_codegen_cranelift/src/lib.rs +++ b/compiler/rustc_codegen_cranelift/src/lib.rs @@ -79,7 +79,7 @@ mod prelude { pub(crate) use rustc_middle::ty::layout::{self, LayoutOf, TyAndLayout}; pub(crate) use rustc_middle::ty::{ self, FloatTy, Instance, InstanceDef, IntTy, ParamEnv, Ty, TyCtxt, TypeAndMut, - TypeFoldable, UintTy, + TypeFoldable, TypeVisitable, UintTy, }; pub(crate) use rustc_target::abi::{Abi, Scalar, Size, VariantIdx}; diff --git a/compiler/rustc_codegen_gcc/src/callee.rs b/compiler/rustc_codegen_gcc/src/callee.rs index 76419b103d0..c1041125ecc 100644 --- a/compiler/rustc_codegen_gcc/src/callee.rs +++ b/compiler/rustc_codegen_gcc/src/callee.rs @@ -1,6 +1,6 @@ use gccjit::{FunctionType, RValue}; use rustc_codegen_ssa::traits::BaseTypeMethods; -use rustc_middle::ty::{self, Instance, TypeFoldable}; +use rustc_middle::ty::{self, Instance, TypeVisitable}; use rustc_middle::ty::layout::{FnAbiOf, HasTyCtxt}; use crate::abi::FnAbiGccExt; diff --git a/compiler/rustc_codegen_gcc/src/mono_item.rs b/compiler/rustc_codegen_gcc/src/mono_item.rs index e21d40b6c37..9468a1ef4bb 100644 --- a/compiler/rustc_codegen_gcc/src/mono_item.rs +++ b/compiler/rustc_codegen_gcc/src/mono_item.rs @@ -1,7 +1,7 @@ use rustc_codegen_ssa::traits::PreDefineMethods; use rustc_middle::middle::codegen_fn_attrs::CodegenFnAttrFlags; use rustc_middle::mir::mono::{Linkage, Visibility}; -use rustc_middle::ty::{self, Instance, TypeFoldable}; +use rustc_middle::ty::{self, Instance, TypeVisitable}; use rustc_middle::ty::layout::{FnAbiOf, LayoutOf}; use rustc_span::def_id::DefId; diff --git a/compiler/rustc_codegen_gcc/src/type_of.rs b/compiler/rustc_codegen_gcc/src/type_of.rs index 569ee2925b1..524d10fb5e2 100644 --- a/compiler/rustc_codegen_gcc/src/type_of.rs +++ b/compiler/rustc_codegen_gcc/src/type_of.rs @@ -3,7 +3,7 @@ use std::fmt::Write; use gccjit::{Struct, Type}; use crate::rustc_codegen_ssa::traits::{BaseTypeMethods, DerivedTypeMethods, LayoutTypeMethods}; use rustc_middle::bug; -use rustc_middle::ty::{self, Ty, TypeFoldable}; +use rustc_middle::ty::{self, Ty, TypeVisitable}; use rustc_middle::ty::layout::{FnAbiOf, LayoutOf, TyAndLayout}; use rustc_middle::ty::print::with_no_trimmed_paths; use rustc_target::abi::{self, Abi, F32, F64, FieldsShape, Int, Integer, Pointer, PointeeInfo, Size, TyAbiInterface, Variants}; diff --git a/compiler/rustc_codegen_llvm/src/builder.rs b/compiler/rustc_codegen_llvm/src/builder.rs index 8c1e865762c..4a4cccb490d 100644 --- a/compiler/rustc_codegen_llvm/src/builder.rs +++ b/compiler/rustc_codegen_llvm/src/builder.rs @@ -28,7 +28,7 @@ use std::ffi::CStr; use std::iter; use std::ops::Deref; use std::ptr; -use tracing::debug; +use tracing::{debug, instrument}; // All Builders must have an llfn associated with them #[must_use] @@ -464,15 +464,15 @@ impl<'a, 'll, 'tcx> BuilderMethods<'a, 'tcx> for Builder<'a, 'll, 'tcx> { } } + #[instrument(level = "trace", skip(self))] fn load_operand(&mut self, place: PlaceRef<'tcx, &'ll Value>) -> OperandRef<'tcx, &'ll Value> { - debug!("PlaceRef::load: {:?}", place); - assert_eq!(place.llextra.is_some(), place.layout.is_unsized()); if place.layout.is_zst() { return OperandRef::new_zst(self, place.layout); } + #[instrument(level = "trace", skip(bx))] fn scalar_load_metadata<'a, 'll, 'tcx>( bx: &mut Builder<'a, 'll, 'tcx>, load: &'ll Value, diff --git a/compiler/rustc_codegen_llvm/src/callee.rs b/compiler/rustc_codegen_llvm/src/callee.rs index ac423a22703..72155d874a2 100644 --- a/compiler/rustc_codegen_llvm/src/callee.rs +++ b/compiler/rustc_codegen_llvm/src/callee.rs @@ -13,7 +13,7 @@ use rustc_codegen_ssa::traits::*; use tracing::debug; use rustc_middle::ty::layout::{FnAbiOf, HasTyCtxt}; -use rustc_middle::ty::{self, Instance, TypeFoldable}; +use rustc_middle::ty::{self, Instance, TypeVisitable}; /// Codegens a reference to a fn/method item, monomorphizing and /// inlining as it goes. diff --git a/compiler/rustc_codegen_llvm/src/common.rs b/compiler/rustc_codegen_llvm/src/common.rs index b69d7a000ee..d37aadeb523 100644 --- a/compiler/rustc_codegen_llvm/src/common.rs +++ b/compiler/rustc_codegen_llvm/src/common.rs @@ -109,8 +109,7 @@ impl<'ll> CodegenCx<'ll, '_> { pub fn const_get_elt(&self, v: &'ll Value, idx: u64) -> &'ll Value { unsafe { assert_eq!(idx as c_uint as u64, idx); - let us = &[idx as c_uint]; - let r = llvm::LLVMConstExtractValue(v, us.as_ptr(), us.len() as c_uint); + let r = llvm::LLVMGetAggregateElement(v, idx as c_uint).unwrap(); debug!("const_get_elt(v={:?}, idx={}, r={:?})", v, idx, r); diff --git a/compiler/rustc_codegen_llvm/src/debuginfo/mod.rs b/compiler/rustc_codegen_llvm/src/debuginfo/mod.rs index 71699b5cf38..64ecbc82c56 100644 --- a/compiler/rustc_codegen_llvm/src/debuginfo/mod.rs +++ b/compiler/rustc_codegen_llvm/src/debuginfo/mod.rs @@ -27,7 +27,7 @@ use rustc_index::vec::IndexVec; use rustc_middle::mir; use rustc_middle::ty::layout::LayoutOf; use rustc_middle::ty::subst::{GenericArgKind, SubstsRef}; -use rustc_middle::ty::{self, Instance, ParamEnv, Ty, TypeFoldable}; +use rustc_middle::ty::{self, Instance, ParamEnv, Ty, TypeVisitable}; use rustc_session::config::{self, DebugInfo}; use rustc_session::Session; use rustc_span::symbol::Symbol; diff --git a/compiler/rustc_codegen_llvm/src/llvm/ffi.rs b/compiler/rustc_codegen_llvm/src/llvm/ffi.rs index b831423994f..5ebc2d6139f 100644 --- a/compiler/rustc_codegen_llvm/src/llvm/ffi.rs +++ b/compiler/rustc_codegen_llvm/src/llvm/ffi.rs @@ -1134,11 +1134,7 @@ extern "C" { pub fn LLVMConstIntToPtr<'a>(ConstantVal: &'a Value, ToType: &'a Type) -> &'a Value; pub fn LLVMConstBitCast<'a>(ConstantVal: &'a Value, ToType: &'a Type) -> &'a Value; pub fn LLVMConstPointerCast<'a>(ConstantVal: &'a Value, ToType: &'a Type) -> &'a Value; - pub fn LLVMConstExtractValue( - AggConstant: &Value, - IdxList: *const c_uint, - NumIdx: c_uint, - ) -> &Value; + pub fn LLVMGetAggregateElement(ConstantVal: &Value, Idx: c_uint) -> Option<&Value>; // Operations on global variables, functions, and aliases (globals) pub fn LLVMIsDeclaration(Global: &Value) -> Bool; @@ -1623,7 +1619,7 @@ extern "C" { B: &Builder<'a>, Val: &'a Value, DestTy: &'a Type, - IsSized: bool, + IsSigned: bool, ) -> &'a Value; // Comparisons diff --git a/compiler/rustc_codegen_llvm/src/mono_item.rs b/compiler/rustc_codegen_llvm/src/mono_item.rs index a3053742aad..6e94284852f 100644 --- a/compiler/rustc_codegen_llvm/src/mono_item.rs +++ b/compiler/rustc_codegen_llvm/src/mono_item.rs @@ -8,7 +8,7 @@ use rustc_hir::def_id::{DefId, LOCAL_CRATE}; pub use rustc_middle::mir::mono::MonoItem; use rustc_middle::mir::mono::{Linkage, Visibility}; use rustc_middle::ty::layout::{FnAbiOf, LayoutOf}; -use rustc_middle::ty::{self, Instance, TypeFoldable}; +use rustc_middle::ty::{self, Instance, TypeVisitable}; use rustc_session::config::CrateType; use rustc_target::spec::RelocModel; use tracing::debug; diff --git a/compiler/rustc_codegen_llvm/src/type_of.rs b/compiler/rustc_codegen_llvm/src/type_of.rs index 86280523631..9f0e6c80b19 100644 --- a/compiler/rustc_codegen_llvm/src/type_of.rs +++ b/compiler/rustc_codegen_llvm/src/type_of.rs @@ -6,7 +6,7 @@ use rustc_codegen_ssa::traits::*; use rustc_middle::bug; use rustc_middle::ty::layout::{FnAbiOf, LayoutOf, TyAndLayout}; use rustc_middle::ty::print::{with_no_trimmed_paths, with_no_visible_paths}; -use rustc_middle::ty::{self, Ty, TypeFoldable}; +use rustc_middle::ty::{self, Ty, TypeVisitable}; use rustc_target::abi::{Abi, AddressSpace, Align, FieldsShape}; use rustc_target::abi::{Int, Pointer, F32, F64}; use rustc_target::abi::{PointeeInfo, Scalar, Size, TyAbiInterface, Variants}; diff --git a/compiler/rustc_codegen_ssa/src/mir/analyze.rs b/compiler/rustc_codegen_ssa/src/mir/analyze.rs index 80dab115fac..5c26168b50d 100644 --- a/compiler/rustc_codegen_ssa/src/mir/analyze.rs +++ b/compiler/rustc_codegen_ssa/src/mir/analyze.rs @@ -143,13 +143,13 @@ impl<'mir, 'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>> LocalAnalyzer<'mir, 'a, 'tcx, // now that we have moved to the "slice of projections" representation. if let mir::ProjectionElem::Index(local) = elem { self.visit_local( - &local, + local, PlaceContext::NonMutatingUse(NonMutatingUseContext::Copy), location, ); } } else { - self.visit_local(&place_ref.local, context, location); + self.visit_local(place_ref.local, context, location); } } } @@ -185,7 +185,7 @@ impl<'mir, 'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>> Visitor<'tcx> self.process_place(&place.as_ref(), context, location); } - fn visit_local(&mut self, &local: &mir::Local, context: PlaceContext, location: Location) { + fn visit_local(&mut self, local: mir::Local, context: PlaceContext, location: Location) { match context { PlaceContext::MutatingUse(MutatingUseContext::Call) | PlaceContext::MutatingUse(MutatingUseContext::Yield) => { diff --git a/compiler/rustc_codegen_ssa/src/mir/block.rs b/compiler/rustc_codegen_ssa/src/mir/block.rs index 0503d723240..f296a04dea1 100644 --- a/compiler/rustc_codegen_ssa/src/mir/block.rs +++ b/compiler/rustc_codegen_ssa/src/mir/block.rs @@ -17,7 +17,7 @@ use rustc_middle::mir::AssertKind; use rustc_middle::mir::{self, SwitchTargets}; use rustc_middle::ty::layout::{HasTyCtxt, LayoutOf}; use rustc_middle::ty::print::{with_no_trimmed_paths, with_no_visible_paths}; -use rustc_middle::ty::{self, Instance, Ty, TypeFoldable}; +use rustc_middle::ty::{self, Instance, Ty, TypeVisitable}; use rustc_span::source_map::Span; use rustc_span::{sym, Symbol}; use rustc_symbol_mangling::typeid_for_fnabi; diff --git a/compiler/rustc_codegen_ssa/src/mir/mod.rs b/compiler/rustc_codegen_ssa/src/mir/mod.rs index 0c958de64fa..ec3f7a2156a 100644 --- a/compiler/rustc_codegen_ssa/src/mir/mod.rs +++ b/compiler/rustc_codegen_ssa/src/mir/mod.rs @@ -2,7 +2,7 @@ use crate::traits::*; use rustc_middle::mir; use rustc_middle::mir::interpret::ErrorHandled; use rustc_middle::ty::layout::{FnAbiOf, HasTyCtxt, TyAndLayout}; -use rustc_middle::ty::{self, Instance, Ty, TypeFoldable}; +use rustc_middle::ty::{self, Instance, Ty, TypeFoldable, TypeVisitable}; use rustc_symbol_mangling::typeid_for_fnabi; use rustc_target::abi::call::{FnAbi, PassMode}; diff --git a/compiler/rustc_codegen_ssa/src/mir/place.rs b/compiler/rustc_codegen_ssa/src/mir/place.rs index 5b88635982f..58cee0c8bb0 100644 --- a/compiler/rustc_codegen_ssa/src/mir/place.rs +++ b/compiler/rustc_codegen_ssa/src/mir/place.rs @@ -204,6 +204,7 @@ impl<'a, 'tcx, V: CodegenObject> PlaceRef<'tcx, V> { } /// Obtain the actual discriminant of a value. + #[instrument(level = "trace", skip(bx))] pub fn codegen_get_discr<Bx: BuilderMethods<'a, 'tcx, Value = V>>( self, bx: &mut Bx, @@ -420,12 +421,12 @@ impl<'a, 'tcx, V: CodegenObject> PlaceRef<'tcx, V> { } impl<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>> FunctionCx<'a, 'tcx, Bx> { + #[instrument(level = "trace", skip(self, bx))] pub fn codegen_place( &mut self, bx: &mut Bx, place_ref: mir::PlaceRef<'tcx>, ) -> PlaceRef<'tcx, Bx::Value> { - debug!("codegen_place(place_ref={:?})", place_ref); let cx = self.cx; let tcx = self.cx.tcx(); diff --git a/compiler/rustc_codegen_ssa/src/mir/rvalue.rs b/compiler/rustc_codegen_ssa/src/mir/rvalue.rs index 81c1897694c..7ff12823bf7 100644 --- a/compiler/rustc_codegen_ssa/src/mir/rvalue.rs +++ b/compiler/rustc_codegen_ssa/src/mir/rvalue.rs @@ -12,17 +12,15 @@ use rustc_middle::ty::cast::{CastTy, IntTy}; use rustc_middle::ty::layout::{HasTyCtxt, LayoutOf}; use rustc_middle::ty::{self, adjustment::PointerCast, Instance, Ty, TyCtxt}; use rustc_span::source_map::{Span, DUMMY_SP}; -use rustc_target::abi::{Abi, Int, Variants}; impl<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>> FunctionCx<'a, 'tcx, Bx> { + #[instrument(level = "trace", skip(self, bx))] pub fn codegen_rvalue( &mut self, mut bx: Bx, dest: PlaceRef<'tcx, Bx::Value>, rvalue: &mir::Rvalue<'tcx>, ) -> Bx { - debug!("codegen_rvalue(dest.llval={:?}, rvalue={:?})", dest.llval, rvalue); - match *rvalue { mir::Rvalue::Use(ref operand) => { let cg_operand = self.codegen_operand(&mut bx, operand); @@ -213,6 +211,7 @@ impl<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>> FunctionCx<'a, 'tcx, Bx> { substs, ty::ClosureKind::FnOnce, ) + .expect("failed to normalize and resolve closure during codegen") .polymorphize(bx.cx().tcx()); OperandValue::Immediate(bx.cx().get_fn_addr(instance)) } @@ -284,74 +283,12 @@ impl<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>> FunctionCx<'a, 'tcx, Bx> { CastTy::from_ty(operand.layout.ty).expect("bad input type for cast"); let r_t_out = CastTy::from_ty(cast.ty).expect("bad output type for cast"); let ll_t_in = bx.cx().immediate_backend_type(operand.layout); - match operand.layout.variants { - Variants::Single { index } => { - if let Some(discr) = - operand.layout.ty.discriminant_for_variant(bx.tcx(), index) - { - let discr_layout = bx.cx().layout_of(discr.ty); - let discr_t = bx.cx().immediate_backend_type(discr_layout); - let discr_val = bx.cx().const_uint_big(discr_t, discr.val); - let discr_val = - bx.intcast(discr_val, ll_t_out, discr.ty.is_signed()); - - return ( - bx, - OperandRef { - val: OperandValue::Immediate(discr_val), - layout: cast, - }, - ); - } - } - Variants::Multiple { .. } => {} - } let llval = operand.immediate(); - let mut signed = false; - if let Abi::Scalar(scalar) = operand.layout.abi { - if let Int(_, s) = scalar.primitive() { - // We use `i1` for bytes that are always `0` or `1`, - // e.g., `#[repr(i8)] enum E { A, B }`, but we can't - // let LLVM interpret the `i1` as signed, because - // then `i1 1` (i.e., E::B) is effectively `i8 -1`. - signed = !scalar.is_bool() && s; - - if !scalar.is_always_valid(bx.cx()) - && scalar.valid_range(bx.cx()).end - >= scalar.valid_range(bx.cx()).start - { - // We want `table[e as usize ± k]` to not - // have bound checks, and this is the most - // convenient place to put the `assume`s. - if scalar.valid_range(bx.cx()).start > 0 { - let enum_value_lower_bound = bx.cx().const_uint_big( - ll_t_in, - scalar.valid_range(bx.cx()).start, - ); - let cmp_start = bx.icmp( - IntPredicate::IntUGE, - llval, - enum_value_lower_bound, - ); - bx.assume(cmp_start); - } - - let enum_value_upper_bound = bx - .cx() - .const_uint_big(ll_t_in, scalar.valid_range(bx.cx()).end); - let cmp_end = bx.icmp( - IntPredicate::IntULE, - llval, - enum_value_upper_bound, - ); - bx.assume(cmp_end); - } - } - } - let newval = match (r_t_in, r_t_out) { - (CastTy::Int(_), CastTy::Int(_)) => bx.intcast(llval, ll_t_out, signed), + (CastTy::Int(i), CastTy::Int(_)) => { + bx.intcast(llval, ll_t_out, i.is_signed()) + } (CastTy::Float, CastTy::Float) => { let srcsz = bx.cx().float_width(ll_t_in); let dstsz = bx.cx().float_width(ll_t_out); @@ -363,8 +300,8 @@ impl<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>> FunctionCx<'a, 'tcx, Bx> { llval } } - (CastTy::Int(_), CastTy::Float) => { - if signed { + (CastTy::Int(i), CastTy::Float) => { + if i.is_signed() { bx.sitofp(llval, ll_t_out) } else { bx.uitofp(llval, ll_t_out) @@ -373,8 +310,9 @@ impl<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>> FunctionCx<'a, 'tcx, Bx> { (CastTy::Ptr(_) | CastTy::FnPtr, CastTy::Ptr(_)) => { bx.pointercast(llval, ll_t_out) } - (CastTy::Int(_), CastTy::Ptr(_)) => { - let usize_llval = bx.intcast(llval, bx.cx().type_isize(), signed); + (CastTy::Int(i), CastTy::Ptr(_)) => { + let usize_llval = + bx.intcast(llval, bx.cx().type_isize(), i.is_signed()); bx.inttoptr(usize_llval, ll_t_out) } (CastTy::Float, CastTy::Int(IntTy::I)) => { diff --git a/compiler/rustc_codegen_ssa/src/mir/statement.rs b/compiler/rustc_codegen_ssa/src/mir/statement.rs index d9ebfc3e871..f452f29883f 100644 --- a/compiler/rustc_codegen_ssa/src/mir/statement.rs +++ b/compiler/rustc_codegen_ssa/src/mir/statement.rs @@ -6,9 +6,8 @@ use crate::traits::BuilderMethods; use crate::traits::*; impl<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>> FunctionCx<'a, 'tcx, Bx> { + #[instrument(level = "debug", skip(self, bx))] pub fn codegen_statement(&mut self, mut bx: Bx, statement: &mir::Statement<'tcx>) -> Bx { - debug!("codegen_statement(statement={:?})", statement); - self.set_debug_loc(&mut bx, statement.source_info); match statement.kind { mir::StatementKind::Assign(box (ref place, ref rvalue)) => { diff --git a/compiler/rustc_const_eval/src/const_eval/eval_queries.rs b/compiler/rustc_const_eval/src/const_eval/eval_queries.rs index 09a2977af04..0dac4f8978e 100644 --- a/compiler/rustc_const_eval/src/const_eval/eval_queries.rs +++ b/compiler/rustc_const_eval/src/const_eval/eval_queries.rs @@ -19,11 +19,9 @@ use rustc_target::abi::{self, Abi}; use std::borrow::Cow; use std::convert::TryInto; -pub fn note_on_undefined_behavior_error() -> &'static str { - "The rules on what exactly is undefined behavior aren't clear, \ +const NOTE_ON_UNDEFINED_BEHAVIOR_ERROR: &str = "The rules on what exactly is undefined behavior aren't clear, \ so this check might be overzealous. Please open an issue on the rustc \ - repository if you believe it should not be considered undefined behavior." -} + repository if you believe it should not be considered undefined behavior."; // Returns a pointer to where the result lives fn eval_body_using_ecx<'mir, 'tcx>( @@ -375,7 +373,7 @@ pub fn eval_to_allocation_raw_provider<'tcx>( ecx.tcx, "it is undefined behavior to use this value", |diag| { - diag.note(note_on_undefined_behavior_error()); + diag.note(NOTE_ON_UNDEFINED_BEHAVIOR_ERROR); diag.note(&format!( "the raw bytes of the constant ({}", display_allocation( diff --git a/compiler/rustc_const_eval/src/const_eval/valtrees.rs b/compiler/rustc_const_eval/src/const_eval/valtrees.rs index 4849a07e3b4..f8b390aaf50 100644 --- a/compiler/rustc_const_eval/src/const_eval/valtrees.rs +++ b/compiler/rustc_const_eval/src/const_eval/valtrees.rs @@ -346,7 +346,7 @@ fn valtree_into_mplace<'tcx>( ty::FnDef(_, _) => { ecx.write_immediate( Immediate::Scalar(ScalarMaybeUninit::Scalar(Scalar::ZST)), - &(*place).into(), + &place.into(), ) .unwrap(); } @@ -355,7 +355,7 @@ fn valtree_into_mplace<'tcx>( debug!("writing trivial valtree {:?} to place {:?}", scalar_int, place); ecx.write_immediate( Immediate::Scalar(ScalarMaybeUninit::Scalar(scalar_int.into())), - &(*place).into(), + &place.into(), ) .unwrap(); } @@ -382,7 +382,7 @@ fn valtree_into_mplace<'tcx>( }; debug!(?imm); - ecx.write_immediate(imm, &(*place).into()).unwrap(); + ecx.write_immediate(imm, &place.into()).unwrap(); } ty::Adt(_, _) | ty::Tuple(_) | ty::Array(_, _) | ty::Str | ty::Slice(_) => { let branches = valtree.unwrap_branch(); @@ -464,11 +464,11 @@ fn valtree_into_mplace<'tcx>( if let Some(variant_idx) = variant_idx { // don't forget filling the place with the discriminant of the enum - ecx.write_discriminant(variant_idx, &(*place).into()).unwrap(); + ecx.write_discriminant(variant_idx, &place.into()).unwrap(); } debug!("dump of place after writing discriminant:"); - dump_place(ecx, (*place).into()); + dump_place(ecx, place.into()); } _ => bug!("shouldn't have created a ValTree for {:?}", ty), } diff --git a/compiler/rustc_const_eval/src/interpret/cast.rs b/compiler/rustc_const_eval/src/interpret/cast.rs index 076415b2d1b..fc81b22b406 100644 --- a/compiler/rustc_const_eval/src/interpret/cast.rs +++ b/compiler/rustc_const_eval/src/interpret/cast.rs @@ -8,7 +8,7 @@ use rustc_middle::mir::CastKind; use rustc_middle::ty::adjustment::PointerCast; use rustc_middle::ty::layout::{IntegerExt, LayoutOf, TyAndLayout}; use rustc_middle::ty::{self, FloatTy, Ty, TypeAndMut}; -use rustc_target::abi::{Integer, Variants}; +use rustc_target::abi::Integer; use rustc_type_ir::sty::TyKind::*; use super::{ @@ -100,7 +100,8 @@ impl<'mir, 'tcx: 'mir, M: Machine<'mir, 'tcx>> InterpCx<'mir, 'tcx, M> { def_id, substs, ty::ClosureKind::FnOnce, - ); + ) + .ok_or_else(|| err_inval!(TooGeneric))?; let fn_ptr = self.create_fn_alloc_ptr(FnVal::Instance(instance)); self.write_pointer(fn_ptr, dest)?; } @@ -127,12 +128,10 @@ impl<'mir, 'tcx: 'mir, M: Machine<'mir, 'tcx>> InterpCx<'mir, 'tcx, M> { Float(FloatTy::F64) => { return Ok(self.cast_from_float(src.to_scalar()?.to_f64()?, cast_ty).into()); } - // The rest is integer/pointer-"like", including fn ptr casts and casts from enums that - // are represented as integers. + // The rest is integer/pointer-"like", including fn ptr casts _ => assert!( src.layout.ty.is_bool() || src.layout.ty.is_char() - || src.layout.ty.is_enum() || src.layout.ty.is_integral() || src.layout.ty.is_any_ptr(), "Unexpected cast from type {:?}", @@ -142,25 +141,6 @@ impl<'mir, 'tcx: 'mir, M: Machine<'mir, 'tcx>> InterpCx<'mir, 'tcx, M> { // # First handle non-scalar source values. - // Handle cast from a ZST enum (0 or 1 variants). - match src.layout.variants { - Variants::Single { index } => { - if src.layout.abi.is_uninhabited() { - // This is dead code, because an uninhabited enum is UB to - // instantiate. - throw_ub!(Unreachable); - } - if let Some(discr) = src.layout.ty.discriminant_for_variant(*self.tcx, index) { - assert!(src.layout.is_zst()); - let discr_layout = self.layout_of(discr.ty)?; - - let scalar = Scalar::from_uint(discr.val, discr_layout.layout.size()); - return Ok(self.cast_from_int_like(scalar, discr_layout, cast_ty)?.into()); - } - } - Variants::Multiple { .. } => {} - } - // Handle casting any ptr to raw ptr (might be a fat ptr). if src.layout.ty.is_any_ptr() && cast_ty.is_unsafe_ptr() { let dest_layout = self.layout_of(cast_ty)?; @@ -202,7 +182,7 @@ impl<'mir, 'tcx: 'mir, M: Machine<'mir, 'tcx>> InterpCx<'mir, 'tcx, M> { let ptr = self.scalar_to_ptr(scalar)?; match ptr.into_pointer_or_addr() { Ok(ptr) => M::expose_ptr(self, ptr)?, - Err(_) => {} // do nothing, exposing an invalid pointer has no meaning + Err(_) => {} // Do nothing, exposing an invalid pointer (`None` provenance) is a NOP. }; Ok(self.cast_from_int_like(scalar, src.layout, cast_ty)?.into()) } diff --git a/compiler/rustc_const_eval/src/interpret/eval_context.rs b/compiler/rustc_const_eval/src/interpret/eval_context.rs index 66c73624501..031d508d70f 100644 --- a/compiler/rustc_const_eval/src/interpret/eval_context.rs +++ b/compiler/rustc_const_eval/src/interpret/eval_context.rs @@ -808,7 +808,7 @@ impl<'mir, 'tcx: 'mir, M: Machine<'mir, 'tcx>> InterpCx<'mir, 'tcx, M> { self.stack_mut().pop().expect("tried to pop a stack frame, but there were none"); if !unwinding { - let op = self.access_local(&frame, mir::RETURN_PLACE, None)?; + let op = self.local_to_op(&frame, mir::RETURN_PLACE, None)?; self.copy_op_transmute(&op, &frame.return_place)?; trace!("{:?}", self.dump_place(*frame.return_place)); } @@ -981,8 +981,7 @@ impl<'a, 'mir, 'tcx: 'mir, M: Machine<'mir, 'tcx>> std::fmt::Debug LocalValue::Live(Operand::Indirect(mplace)) => { write!( fmt, - " by align({}){} ref {:?}:", - mplace.align.bytes(), + " by {} ref {:?}:", match mplace.meta { MemPlaceMeta::Meta(meta) => format!(" meta({:?})", meta), MemPlaceMeta::Poison | MemPlaceMeta::None => String::new(), @@ -1011,13 +1010,9 @@ impl<'a, 'mir, 'tcx: 'mir, M: Machine<'mir, 'tcx>> std::fmt::Debug write!(fmt, ": {:?}", self.ecx.dump_allocs(allocs.into_iter().flatten().collect())) } Place::Ptr(mplace) => match mplace.ptr.provenance.and_then(Provenance::get_alloc_id) { - Some(alloc_id) => write!( - fmt, - "by align({}) ref {:?}: {:?}", - mplace.align.bytes(), - mplace.ptr, - self.ecx.dump_alloc(alloc_id) - ), + Some(alloc_id) => { + write!(fmt, "by ref {:?}: {:?}", mplace.ptr, self.ecx.dump_alloc(alloc_id)) + } ptr => write!(fmt, " integral by ref: {:?}", ptr), }, } diff --git a/compiler/rustc_const_eval/src/interpret/intern.rs b/compiler/rustc_const_eval/src/interpret/intern.rs index 1fda60c021e..9dfdafcb38e 100644 --- a/compiler/rustc_const_eval/src/interpret/intern.rs +++ b/compiler/rustc_const_eval/src/interpret/intern.rs @@ -168,8 +168,51 @@ impl<'rt, 'mir, 'tcx: 'mir, M: CompileTimeMachine<'mir, 'tcx, const_eval::Memory mplace: &MPlaceTy<'tcx>, fields: impl Iterator<Item = InterpResult<'tcx, Self::V>>, ) -> InterpResult<'tcx> { - // ZSTs cannot contain pointers, so we can skip them. - if mplace.layout.is_zst() { + // We want to walk the aggregate to look for references to intern. While doing that we + // also need to take special care of interior mutability. + // + // As an optimization, however, if the allocation does not contain any references: we don't + // need to do the walk. It can be costly for big arrays for example (e.g. issue #93215). + let is_walk_needed = |mplace: &MPlaceTy<'tcx>| -> InterpResult<'tcx, bool> { + // ZSTs cannot contain pointers, we can avoid the interning walk. + if mplace.layout.is_zst() { + return Ok(false); + } + + // Now, check whether this allocation could contain references. + // + // Note, this check may sometimes not be cheap, so we only do it when the walk we'd like + // to avoid could be expensive: on the potentially larger types, arrays and slices, + // rather than on all aggregates unconditionally. + if matches!(mplace.layout.ty.kind(), ty::Array(..) | ty::Slice(..)) { + let Some((size, align)) = self.ecx.size_and_align_of_mplace(&mplace)? else { + // We do the walk if we can't determine the size of the mplace: we may be + // dealing with extern types here in the future. + return Ok(true); + }; + + // If there are no relocations in this allocation, it does not contain references + // that point to another allocation, and we can avoid the interning walk. + if let Some(alloc) = self.ecx.get_ptr_alloc(mplace.ptr, size, align)? { + if !alloc.has_relocations() { + return Ok(false); + } + } else { + // We're encountering a ZST here, and can avoid the walk as well. + return Ok(false); + } + } + + // In the general case, we do the walk. + Ok(true) + }; + + // If this allocation contains no references to intern, we avoid the potentially costly + // walk. + // + // We can do this before the checks for interior mutability below, because only references + // are relevant in that situation, and we're checking if there are any here. + if !is_walk_needed(mplace)? { return Ok(()); } @@ -195,7 +238,7 @@ impl<'rt, 'mir, 'tcx: 'mir, M: CompileTimeMachine<'mir, 'tcx, const_eval::Memory let tcx = self.ecx.tcx; let ty = mplace.layout.ty; if let ty::Ref(_, referenced_ty, ref_mutability) = *ty.kind() { - let value = self.ecx.read_immediate(&(*mplace).into())?; + let value = self.ecx.read_immediate(&mplace.into())?; let mplace = self.ecx.ref_to_mplace(&value)?; assert_eq!(mplace.layout.ty, referenced_ty); // Handle trait object vtables. diff --git a/compiler/rustc_const_eval/src/interpret/intrinsics.rs b/compiler/rustc_const_eval/src/interpret/intrinsics.rs index e51c51cf45e..6744aace849 100644 --- a/compiler/rustc_const_eval/src/interpret/intrinsics.rs +++ b/compiler/rustc_const_eval/src/interpret/intrinsics.rs @@ -217,7 +217,9 @@ impl<'mir, 'tcx: 'mir, M: Machine<'mir, 'tcx>> InterpCx<'mir, 'tcx, M> { sym::mul_with_overflow => BinOp::Mul, _ => bug!(), }; - self.binop_with_overflow(bin_op, &lhs, &rhs, dest)?; + self.binop_with_overflow( + bin_op, /*force_overflow_checks*/ true, &lhs, &rhs, dest, + )?; } sym::saturating_add | sym::saturating_sub => { let l = self.read_immediate(&args[0])?; diff --git a/compiler/rustc_const_eval/src/interpret/machine.rs b/compiler/rustc_const_eval/src/interpret/machine.rs index c18ac84171d..4661a7c2828 100644 --- a/compiler/rustc_const_eval/src/interpret/machine.rs +++ b/compiler/rustc_const_eval/src/interpret/machine.rs @@ -144,6 +144,9 @@ pub trait Machine<'mir, 'tcx>: Sized { true } + /// Whether CheckedBinOp MIR statements should actually check for overflow. + fn checked_binop_checks_overflow(_ecx: &InterpCx<'mir, 'tcx, Self>) -> bool; + /// Entry point for obtaining the MIR of anything that should get evaluated. /// So not just functions and shims, but also const/static initializers, anonymous /// constants, ... @@ -469,6 +472,11 @@ pub macro compile_time_machine(<$mir: lifetime, $tcx: lifetime>) { } #[inline(always)] + fn checked_binop_checks_overflow(_ecx: &InterpCx<$mir, $tcx, Self>) -> bool { + true + } + + #[inline(always)] fn call_extra_fn( _ecx: &mut InterpCx<$mir, $tcx, Self>, fn_val: !, @@ -513,7 +521,7 @@ pub macro compile_time_machine(<$mir: lifetime, $tcx: lifetime>) { _ecx: &InterpCx<$mir, $tcx, Self>, addr: u64, ) -> Pointer<Option<AllocId>> { - Pointer::new(None, Size::from_bytes(addr)) + Pointer::from_addr(addr) } #[inline(always)] @@ -523,7 +531,7 @@ pub macro compile_time_machine(<$mir: lifetime, $tcx: lifetime>) { ) -> InterpResult<$tcx, Pointer<Option<AllocId>>> { // Allow these casts, but make the pointer not dereferenceable. // (I.e., they behave like transmutation.) - Ok(Pointer::new(None, Size::from_bytes(addr))) + Ok(Pointer::from_addr(addr)) } #[inline(always)] diff --git a/compiler/rustc_const_eval/src/interpret/memory.rs b/compiler/rustc_const_eval/src/interpret/memory.rs index d5e68dbd5b7..509fe576893 100644 --- a/compiler/rustc_const_eval/src/interpret/memory.rs +++ b/compiler/rustc_const_eval/src/interpret/memory.rs @@ -276,7 +276,7 @@ impl<'mir, 'tcx: 'mir, M: Machine<'mir, 'tcx>> InterpCx<'mir, 'tcx, M> { kind: MemoryKind<M::MemoryKind>, ) -> InterpResult<'tcx> { let (alloc_id, offset, tag) = self.ptr_get_alloc_id(ptr)?; - trace!("deallocating: {}", alloc_id); + trace!("deallocating: {alloc_id:?}"); if offset.bytes() != 0 { throw_ub_format!( @@ -289,10 +289,10 @@ impl<'mir, 'tcx: 'mir, M: Machine<'mir, 'tcx>> InterpCx<'mir, 'tcx, M> { // Deallocating global memory -- always an error return Err(match self.tcx.get_global_alloc(alloc_id) { Some(GlobalAlloc::Function(..)) => { - err_ub_format!("deallocating {}, which is a function", alloc_id) + err_ub_format!("deallocating {alloc_id:?}, which is a function") } Some(GlobalAlloc::Static(..) | GlobalAlloc::Memory(..)) => { - err_ub_format!("deallocating {}, which is static memory", alloc_id) + err_ub_format!("deallocating {alloc_id:?}, which is static memory") } None => err_ub!(PointerUseAfterFree(alloc_id)), } @@ -302,21 +302,17 @@ impl<'mir, 'tcx: 'mir, M: Machine<'mir, 'tcx>> InterpCx<'mir, 'tcx, M> { debug!(?alloc); if alloc.mutability == Mutability::Not { - throw_ub_format!("deallocating immutable allocation {}", alloc_id); + throw_ub_format!("deallocating immutable allocation {alloc_id:?}"); } if alloc_kind != kind { throw_ub_format!( - "deallocating {}, which is {} memory, using {} deallocation operation", - alloc_id, - alloc_kind, - kind + "deallocating {alloc_id:?}, which is {alloc_kind} memory, using {kind} deallocation operation" ); } if let Some((size, align)) = old_size_and_align { if size != alloc.size() || align != alloc.align { throw_ub_format!( - "incorrect layout on deallocation: {} has size {} and alignment {}, but gave size {} and alignment {}", - alloc_id, + "incorrect layout on deallocation: {alloc_id:?} has size {} and alignment {}, but gave size {} and alignment {}", alloc.size().bytes(), alloc.align.bytes(), size.bytes(), @@ -815,7 +811,7 @@ impl<'a, 'mir, 'tcx, M: Machine<'mir, 'tcx>> std::fmt::Debug for DumpAllocs<'a, continue; } - write!(fmt, "{}", id)?; + write!(fmt, "{id:?}")?; match self.ecx.memory.alloc_map.get(id) { Some(&(kind, ref alloc)) => { // normal alloc @@ -859,25 +855,21 @@ impl<'a, 'mir, 'tcx, M: Machine<'mir, 'tcx>> std::fmt::Debug for DumpAllocs<'a, /// Reading and writing. impl<'tcx, 'a, Tag: Provenance, Extra> AllocRefMut<'a, 'tcx, Tag, Extra> { + /// `range` is relative to this allocation reference, not the base of the allocation. pub fn write_scalar( &mut self, range: AllocRange, val: ScalarMaybeUninit<Tag>, ) -> InterpResult<'tcx> { let range = self.range.subrange(range); - debug!( - "write_scalar in {} at {:#x}, size {}: {:?}", - self.alloc_id, - range.start.bytes(), - range.size.bytes(), - val - ); + debug!("write_scalar at {:?}{range:?}: {val:?}", self.alloc_id); Ok(self .alloc .write_scalar(&self.tcx, range, val) .map_err(|e| e.to_interp_error(self.alloc_id))?) } + /// `offset` is relative to this allocation reference, not the base of the allocation. pub fn write_ptr_sized( &mut self, offset: Size, @@ -896,6 +888,7 @@ impl<'tcx, 'a, Tag: Provenance, Extra> AllocRefMut<'a, 'tcx, Tag, Extra> { } impl<'tcx, 'a, Tag: Provenance, Extra> AllocRef<'a, 'tcx, Tag, Extra> { + /// `range` is relative to this allocation reference, not the base of the allocation. pub fn read_scalar( &self, range: AllocRange, @@ -906,24 +899,16 @@ impl<'tcx, 'a, Tag: Provenance, Extra> AllocRef<'a, 'tcx, Tag, Extra> { .alloc .read_scalar(&self.tcx, range, read_provenance) .map_err(|e| e.to_interp_error(self.alloc_id))?; - debug!( - "read_scalar in {} at {:#x}, size {}: {:?}", - self.alloc_id, - range.start.bytes(), - range.size.bytes(), - res - ); + debug!("read_scalar at {:?}{range:?}: {res:?}", self.alloc_id); Ok(res) } - pub fn read_integer( - &self, - offset: Size, - size: Size, - ) -> InterpResult<'tcx, ScalarMaybeUninit<Tag>> { - self.read_scalar(alloc_range(offset, size), /*read_provenance*/ false) + /// `range` is relative to this allocation reference, not the base of the allocation. + pub fn read_integer(&self, range: AllocRange) -> InterpResult<'tcx, ScalarMaybeUninit<Tag>> { + self.read_scalar(range, /*read_provenance*/ false) } + /// `offset` is relative to this allocation reference, not the base of the allocation. pub fn read_pointer(&self, offset: Size) -> InterpResult<'tcx, ScalarMaybeUninit<Tag>> { self.read_scalar( alloc_range(offset, self.tcx.data_layout().pointer_size), @@ -931,6 +916,7 @@ impl<'tcx, 'a, Tag: Provenance, Extra> AllocRef<'a, 'tcx, Tag, Extra> { ) } + /// `range` is relative to this allocation reference, not the base of the allocation. pub fn check_bytes( &self, range: AllocRange, @@ -942,6 +928,11 @@ impl<'tcx, 'a, Tag: Provenance, Extra> AllocRef<'a, 'tcx, Tag, Extra> { .check_bytes(&self.tcx, self.range.subrange(range), allow_uninit, allow_ptr) .map_err(|e| e.to_interp_error(self.alloc_id))?) } + + /// Returns whether the allocation has relocations for the entire range of the `AllocRef`. + pub(crate) fn has_relocations(&self) -> bool { + self.alloc.has_relocations(&self.tcx, self.range) + } } impl<'mir, 'tcx: 'mir, M: Machine<'mir, 'tcx>> InterpCx<'mir, 'tcx, M> { diff --git a/compiler/rustc_const_eval/src/interpret/operand.rs b/compiler/rustc_const_eval/src/interpret/operand.rs index 6b05a49575f..145d95a40ea 100644 --- a/compiler/rustc_const_eval/src/interpret/operand.rs +++ b/compiler/rustc_const_eval/src/interpret/operand.rs @@ -10,7 +10,7 @@ use rustc_middle::ty::layout::{LayoutOf, PrimitiveExt, TyAndLayout}; use rustc_middle::ty::print::{FmtPrinter, PrettyPrinter, Printer}; use rustc_middle::ty::{ConstInt, DelaySpanBugEmitted, Ty}; use rustc_middle::{mir, ty}; -use rustc_target::abi::{self, Abi, HasDataLayout, Size, TagEncoding}; +use rustc_target::abi::{self, Abi, Align, HasDataLayout, Size, TagEncoding}; use rustc_target::abi::{VariantIdx, Variants}; use super::{ @@ -177,10 +177,18 @@ pub enum Operand<Tag: Provenance = AllocId> { pub struct OpTy<'tcx, Tag: Provenance = AllocId> { op: Operand<Tag>, // Keep this private; it helps enforce invariants. pub layout: TyAndLayout<'tcx>, + /// rustc does not have a proper way to represent the type of a field of a `repr(packed)` struct: + /// it needs to have a different alignment than the field type would usually have. + /// So we represent this here with a separate field that "overwrites" `layout.align`. + /// This means `layout.align` should never be used for an `OpTy`! + /// `None` means "alignment does not matter since this is a by-value operand" + /// (`Operand::Immediate`); this field is only relevant for `Operand::Indirect`. + /// Also CTFE ignores alignment anyway, so this is for Miri only. + pub align: Option<Align>, } #[cfg(all(target_arch = "x86_64", target_pointer_width = "64"))] -rustc_data_structures::static_assert_size!(OpTy<'_>, 80); +rustc_data_structures::static_assert_size!(OpTy<'_>, 88); impl<'tcx, Tag: Provenance> std::ops::Deref for OpTy<'tcx, Tag> { type Target = Operand<Tag>; @@ -193,21 +201,28 @@ impl<'tcx, Tag: Provenance> std::ops::Deref for OpTy<'tcx, Tag> { impl<'tcx, Tag: Provenance> From<MPlaceTy<'tcx, Tag>> for OpTy<'tcx, Tag> { #[inline(always)] fn from(mplace: MPlaceTy<'tcx, Tag>) -> Self { - OpTy { op: Operand::Indirect(*mplace), layout: mplace.layout } + OpTy { op: Operand::Indirect(*mplace), layout: mplace.layout, align: Some(mplace.align) } } } impl<'tcx, Tag: Provenance> From<&'_ MPlaceTy<'tcx, Tag>> for OpTy<'tcx, Tag> { #[inline(always)] fn from(mplace: &MPlaceTy<'tcx, Tag>) -> Self { - OpTy { op: Operand::Indirect(**mplace), layout: mplace.layout } + OpTy { op: Operand::Indirect(**mplace), layout: mplace.layout, align: Some(mplace.align) } + } +} + +impl<'tcx, Tag: Provenance> From<&'_ mut MPlaceTy<'tcx, Tag>> for OpTy<'tcx, Tag> { + #[inline(always)] + fn from(mplace: &mut MPlaceTy<'tcx, Tag>) -> Self { + OpTy { op: Operand::Indirect(**mplace), layout: mplace.layout, align: Some(mplace.align) } } } impl<'tcx, Tag: Provenance> From<ImmTy<'tcx, Tag>> for OpTy<'tcx, Tag> { #[inline(always)] fn from(val: ImmTy<'tcx, Tag>) -> Self { - OpTy { op: Operand::Immediate(val.imm), layout: val.layout } + OpTy { op: Operand::Immediate(val.imm), layout: val.layout, align: None } } } @@ -291,9 +306,8 @@ impl<'mir, 'tcx: 'mir, M: Machine<'mir, 'tcx>> InterpCx<'mir, 'tcx, M> { s.is_ptr() || (number_may_have_provenance && size == self.pointer_size()) }; if let Some(s) = scalar_layout { - //FIXME(#96185): let size = s.size(self); - //FIXME(#96185): assert_eq!(size, mplace.layout.size, "abi::Scalar size does not match layout size"); - let size = mplace.layout.size; //FIXME(#96185): remove this line + let size = s.size(self); + assert_eq!(size, mplace.layout.size, "abi::Scalar size does not match layout size"); let scalar = alloc.read_scalar(alloc_range(Size::ZERO, size), read_provenance(s, size))?; return Ok(Some(ImmTy { imm: scalar.into(), layout: mplace.layout })); @@ -443,7 +457,7 @@ impl<'mir, 'tcx: 'mir, M: Machine<'mir, 'tcx>> InterpCx<'mir, 'tcx, M> { ), }; - Ok(OpTy { op: Operand::Immediate(field_val), layout: field_layout }) + Ok(OpTy { op: Operand::Immediate(field_val), layout: field_layout, align: None }) } pub fn operand_index( @@ -515,7 +529,7 @@ impl<'mir, 'tcx: 'mir, M: Machine<'mir, 'tcx>> InterpCx<'mir, 'tcx, M> { /// /// This is public because it is used by [priroda](https://github.com/oli-obk/priroda) to get an /// OpTy from a local - pub fn access_local( + pub fn local_to_op( &self, frame: &super::Frame<'mir, 'tcx, M::PointerTag, M::FrameExtra>, local: mir::Local, @@ -528,7 +542,7 @@ impl<'mir, 'tcx: 'mir, M: Machine<'mir, 'tcx>> InterpCx<'mir, 'tcx, M> { } else { M::access_local(&self, frame, local)? }; - Ok(OpTy { op, layout }) + Ok(OpTy { op, layout, align: Some(layout.align.abi) }) } /// Every place can be read from, so we can turn them into an operand. @@ -542,10 +556,10 @@ impl<'mir, 'tcx: 'mir, M: Machine<'mir, 'tcx>> InterpCx<'mir, 'tcx, M> { let op = match **place { Place::Ptr(mplace) => Operand::Indirect(mplace), Place::Local { frame, local } => { - *self.access_local(&self.stack()[frame], local, None)? + *self.local_to_op(&self.stack()[frame], local, None)? } }; - Ok(OpTy { op, layout: place.layout }) + Ok(OpTy { op, layout: place.layout, align: Some(place.align) }) } /// Evaluate a place with the goal of reading from it. This lets us sometimes @@ -559,7 +573,7 @@ impl<'mir, 'tcx: 'mir, M: Machine<'mir, 'tcx>> InterpCx<'mir, 'tcx, M> { // here is not the entire place. let layout = if place.projection.is_empty() { layout } else { None }; - let base_op = self.access_local(self.frame(), place.local, layout)?; + let base_op = self.local_to_op(self.frame(), place.local, layout)?; let op = place .projection @@ -596,11 +610,11 @@ impl<'mir, 'tcx: 'mir, M: Machine<'mir, 'tcx>> InterpCx<'mir, 'tcx, M> { Constant(ref constant) => { let val = self.subst_from_current_frame_and_normalize_erasing_regions(constant.literal)?; + // This can still fail: // * During ConstProp, with `TooGeneric` or since the `required_consts` were not all // checked yet. // * During CTFE, since promoteds in `const`/`static` initializer bodies can fail. - self.mir_const_to_op(&val, layout)? } }; @@ -676,7 +690,7 @@ impl<'mir, 'tcx: 'mir, M: Machine<'mir, 'tcx>> InterpCx<'mir, 'tcx, M> { // We rely on mutability being set correctly in that allocation to prevent writes // where none should happen. let ptr = self.global_base_pointer(Pointer::new(id, offset))?; - Operand::Indirect(MemPlace::from_ptr(ptr.into(), layout.align.abi)) + Operand::Indirect(MemPlace::from_ptr(ptr.into())) } ConstValue::Scalar(x) => Operand::Immediate(tag_scalar(x)?.into()), ConstValue::Slice { data, start, end } => { @@ -693,7 +707,7 @@ impl<'mir, 'tcx: 'mir, M: Machine<'mir, 'tcx>> InterpCx<'mir, 'tcx, M> { )) } }; - Ok(OpTy { op, layout }) + Ok(OpTy { op, layout, align: Some(layout.align.abi) }) } /// Read discriminant, return the runtime value as well as the variant index. diff --git a/compiler/rustc_const_eval/src/interpret/operator.rs b/compiler/rustc_const_eval/src/interpret/operator.rs index 85ee88e9e47..f0c113376ea 100644 --- a/compiler/rustc_const_eval/src/interpret/operator.rs +++ b/compiler/rustc_const_eval/src/interpret/operator.rs @@ -5,15 +5,20 @@ use rustc_middle::mir; use rustc_middle::mir::interpret::{InterpResult, Scalar}; use rustc_middle::ty::layout::{LayoutOf, TyAndLayout}; use rustc_middle::ty::{self, FloatTy, Ty}; +use rustc_target::abi::Abi; use super::{ImmTy, Immediate, InterpCx, Machine, PlaceTy}; impl<'mir, 'tcx: 'mir, M: Machine<'mir, 'tcx>> InterpCx<'mir, 'tcx, M> { /// Applies the binary operation `op` to the two operands and writes a tuple of the result /// and a boolean signifying the potential overflow to the destination. + /// + /// `force_overflow_checks` indicates whether overflow checks should be done even when + /// `tcx.sess.overflow_checks()` is `false`. pub fn binop_with_overflow( &mut self, op: mir::BinOp, + force_overflow_checks: bool, left: &ImmTy<'tcx, M::PointerTag>, right: &ImmTy<'tcx, M::PointerTag>, dest: &PlaceTy<'tcx, M::PointerTag>, @@ -25,8 +30,27 @@ impl<'mir, 'tcx: 'mir, M: Machine<'mir, 'tcx>> InterpCx<'mir, 'tcx, M> { "type mismatch for result of {:?}", op, ); - let val = Immediate::ScalarPair(val.into(), Scalar::from_bool(overflowed).into()); - self.write_immediate(val, dest) + // As per https://github.com/rust-lang/rust/pull/98738, we always return `false` in the 2nd + // component when overflow checking is disabled. + let overflowed = + overflowed && (force_overflow_checks || M::checked_binop_checks_overflow(self)); + // Write the result to `dest`. + if let Abi::ScalarPair(..) = dest.layout.abi { + // We can use the optimized path and avoid `place_field` (which might do + // `force_allocation`). + let pair = Immediate::ScalarPair(val.into(), Scalar::from_bool(overflowed).into()); + self.write_immediate(pair, dest)?; + } else { + assert!(self.tcx.sess.opts.debugging_opts.randomize_layout); + // With randomized layout, `(int, bool)` might cease to be a `ScalarPair`, so we have to + // do a component-wise write here. This code path is slower than the above because + // `place_field` will have to `force_allocate` locals here. + let val_field = self.place_field(&dest, 0)?; + self.write_scalar(val, &val_field)?; + let overflowed_field = self.place_field(&dest, 1)?; + self.write_scalar(Scalar::from_bool(overflowed), &overflowed_field)?; + } + Ok(()) } /// Applies the binary operation `op` to the arguments and writes the result to the diff --git a/compiler/rustc_const_eval/src/interpret/place.rs b/compiler/rustc_const_eval/src/interpret/place.rs index 3dbcba72baf..f4dc18af23c 100644 --- a/compiler/rustc_const_eval/src/interpret/place.rs +++ b/compiler/rustc_const_eval/src/interpret/place.rs @@ -57,7 +57,6 @@ impl<Tag: Provenance> MemPlaceMeta<Tag> { pub struct MemPlace<Tag: Provenance = AllocId> { /// The pointer can be a pure integer, with the `None` tag. pub ptr: Pointer<Option<Tag>>, - pub align: Align, /// Metadata for unsized places. Interpretation is up to the type. /// Must not be present for sized types, but can be missing for unsized types /// (e.g., `extern type`). @@ -65,7 +64,7 @@ pub struct MemPlace<Tag: Provenance = AllocId> { } #[cfg(all(target_arch = "x86_64", target_pointer_width = "64"))] -rustc_data_structures::static_assert_size!(MemPlace, 48); +rustc_data_structures::static_assert_size!(MemPlace, 40); #[derive(Copy, Clone, Hash, PartialEq, Eq, HashStable, Debug)] pub enum Place<Tag: Provenance = AllocId> { @@ -78,12 +77,17 @@ pub enum Place<Tag: Provenance = AllocId> { } #[cfg(all(target_arch = "x86_64", target_pointer_width = "64"))] -rustc_data_structures::static_assert_size!(Place, 56); +rustc_data_structures::static_assert_size!(Place, 48); #[derive(Copy, Clone, Debug)] pub struct PlaceTy<'tcx, Tag: Provenance = AllocId> { place: Place<Tag>, // Keep this private; it helps enforce invariants. pub layout: TyAndLayout<'tcx>, + /// rustc does not have a proper way to represent the type of a field of a `repr(packed)` struct: + /// it needs to have a different alignment than the field type would usually have. + /// So we represent this here with a separate field that "overwrites" `layout.align`. + /// This means `layout.align` should never be used for a `PlaceTy`! + pub align: Align, } #[cfg(all(target_arch = "x86_64", target_pointer_width = "64"))] @@ -102,6 +106,11 @@ impl<'tcx, Tag: Provenance> std::ops::Deref for PlaceTy<'tcx, Tag> { pub struct MPlaceTy<'tcx, Tag: Provenance = AllocId> { mplace: MemPlace<Tag>, pub layout: TyAndLayout<'tcx>, + /// rustc does not have a proper way to represent the type of a field of a `repr(packed)` struct: + /// it needs to have a different alignment than the field type would usually have. + /// So we represent this here with a separate field that "overwrites" `layout.align`. + /// This means `layout.align` should never be used for a `MPlaceTy`! + pub align: Align, } #[cfg(all(target_arch = "x86_64", target_pointer_width = "64"))] @@ -118,14 +127,28 @@ impl<'tcx, Tag: Provenance> std::ops::Deref for MPlaceTy<'tcx, Tag> { impl<'tcx, Tag: Provenance> From<MPlaceTy<'tcx, Tag>> for PlaceTy<'tcx, Tag> { #[inline(always)] fn from(mplace: MPlaceTy<'tcx, Tag>) -> Self { - PlaceTy { place: Place::Ptr(mplace.mplace), layout: mplace.layout } + PlaceTy { place: Place::Ptr(*mplace), layout: mplace.layout, align: mplace.align } + } +} + +impl<'tcx, Tag: Provenance> From<&'_ MPlaceTy<'tcx, Tag>> for PlaceTy<'tcx, Tag> { + #[inline(always)] + fn from(mplace: &MPlaceTy<'tcx, Tag>) -> Self { + PlaceTy { place: Place::Ptr(**mplace), layout: mplace.layout, align: mplace.align } + } +} + +impl<'tcx, Tag: Provenance> From<&'_ mut MPlaceTy<'tcx, Tag>> for PlaceTy<'tcx, Tag> { + #[inline(always)] + fn from(mplace: &mut MPlaceTy<'tcx, Tag>) -> Self { + PlaceTy { place: Place::Ptr(**mplace), layout: mplace.layout, align: mplace.align } } } impl<Tag: Provenance> MemPlace<Tag> { #[inline(always)] - pub fn from_ptr(ptr: Pointer<Option<Tag>>, align: Align) -> Self { - MemPlace { ptr, align, meta: MemPlaceMeta::None } + pub fn from_ptr(ptr: Pointer<Option<Tag>>) -> Self { + MemPlace { ptr, meta: MemPlaceMeta::None } } /// Adjust the provenance of the main pointer (metadata is unaffected). @@ -156,11 +179,7 @@ impl<Tag: Provenance> MemPlace<Tag> { meta: MemPlaceMeta<Tag>, cx: &impl HasDataLayout, ) -> InterpResult<'tcx, Self> { - Ok(MemPlace { - ptr: self.ptr.offset(offset, cx)?, - align: self.align.restrict_for_offset(offset), - meta, - }) + Ok(MemPlace { ptr: self.ptr.offset(offset, cx)?, meta }) } } @@ -169,9 +188,9 @@ impl<'tcx, Tag: Provenance> MPlaceTy<'tcx, Tag> { #[inline] pub fn dangling(layout: TyAndLayout<'tcx>) -> Self { let align = layout.align.abi; - let ptr = Pointer::new(None, Size::from_bytes(align.bytes())); // no provenance, absolute address + let ptr = Pointer::from_addr(align.bytes()); // no provenance, absolute address // `Poison` this to make sure that the pointer value `ptr` is never observable by the program. - MPlaceTy { mplace: MemPlace { ptr, align, meta: MemPlaceMeta::Poison }, layout } + MPlaceTy { mplace: MemPlace { ptr, meta: MemPlaceMeta::Poison }, layout, align } } #[inline] @@ -182,12 +201,16 @@ impl<'tcx, Tag: Provenance> MPlaceTy<'tcx, Tag> { layout: TyAndLayout<'tcx>, cx: &impl HasDataLayout, ) -> InterpResult<'tcx, Self> { - Ok(MPlaceTy { mplace: self.mplace.offset(offset, meta, cx)?, layout }) + Ok(MPlaceTy { + mplace: self.mplace.offset(offset, meta, cx)?, + align: self.align.restrict_for_offset(offset), + layout, + }) } #[inline] pub fn from_aligned_ptr(ptr: Pointer<Option<Tag>>, layout: TyAndLayout<'tcx>) -> Self { - MPlaceTy { mplace: MemPlace::from_ptr(ptr, layout.align.abi), layout } + MPlaceTy { mplace: MemPlace::from_ptr(ptr), layout, align: layout.align.abi } } #[inline] @@ -196,10 +219,10 @@ impl<'tcx, Tag: Provenance> MPlaceTy<'tcx, Tag> { layout: TyAndLayout<'tcx>, meta: MemPlaceMeta<Tag>, ) -> Self { - let mut mplace = MemPlace::from_ptr(ptr, layout.align.abi); + let mut mplace = MemPlace::from_ptr(ptr); mplace.meta = meta; - MPlaceTy { mplace, layout } + MPlaceTy { mplace, layout, align: layout.align.abi } } #[inline] @@ -236,7 +259,9 @@ impl<'tcx, Tag: Provenance> OpTy<'tcx, Tag> { /// read from the resulting mplace, not to get its address back. pub fn try_as_mplace(&self) -> Result<MPlaceTy<'tcx, Tag>, ImmTy<'tcx, Tag>> { match **self { - Operand::Indirect(mplace) => Ok(MPlaceTy { mplace, layout: self.layout }), + Operand::Indirect(mplace) => { + Ok(MPlaceTy { mplace, layout: self.layout, align: self.align.unwrap() }) + } Operand::Immediate(_) if self.layout.is_zst() => Ok(MPlaceTy::dangling(self.layout)), Operand::Immediate(imm) => Err(ImmTy::from_immediate(imm, self.layout)), } @@ -250,20 +275,19 @@ impl<'tcx, Tag: Provenance> OpTy<'tcx, Tag> { } } -impl<Tag: Provenance> Place<Tag> { +impl<'tcx, Tag: Provenance> PlaceTy<'tcx, Tag> { + /// A place is either an mplace or some local. #[inline] - pub fn assert_mem_place(self) -> MemPlace<Tag> { - match self { - Place::Ptr(mplace) => mplace, - _ => bug!("assert_mem_place: expected Place::Ptr, got {:?}", self), + pub fn try_as_mplace(&self) -> Result<MPlaceTy<'tcx, Tag>, (usize, mir::Local)> { + match **self { + Place::Ptr(mplace) => Ok(MPlaceTy { mplace, layout: self.layout, align: self.align }), + Place::Local { frame, local } => Err((frame, local)), } } -} -impl<'tcx, Tag: Provenance> PlaceTy<'tcx, Tag> { #[inline] pub fn assert_mem_place(self) -> MPlaceTy<'tcx, Tag> { - MPlaceTy { mplace: self.place.assert_mem_place(), layout: self.layout } + self.try_as_mplace().unwrap() } } @@ -292,16 +316,10 @@ where Immediate::ScalarPair(ptr, meta) => (ptr, MemPlaceMeta::Meta(meta.check_init()?)), }; - let mplace = MemPlace { - ptr: self.scalar_to_ptr(ptr.check_init()?)?, - // We could use the run-time alignment here. For now, we do not, because - // the point of tracking the alignment here is to make sure that the *static* - // alignment information emitted with the loads is correct. The run-time - // alignment can only be more restrictive. - align: layout.align.abi, - meta, - }; - Ok(MPlaceTy { mplace, layout }) + let mplace = MemPlace { ptr: self.scalar_to_ptr(ptr.check_init()?)?, meta }; + // When deref'ing a pointer, the *static* alignment given by the type is what matters. + let align = layout.align.abi; + Ok(MPlaceTy { mplace, layout, align }) } /// Take an operand, representing a pointer, and dereference it to a place -- that @@ -354,7 +372,7 @@ where let (size, align) = self .size_and_align_of_mplace(&mplace)? .unwrap_or((mplace.layout.size, mplace.layout.align.abi)); - assert!(mplace.mplace.align <= align, "dynamic alignment less strict than static one?"); + assert!(mplace.align <= align, "dynamic alignment less strict than static one?"); let align = M::enforce_alignment(self).then_some(align); self.check_ptr_access_align(mplace.ptr, size, align.unwrap_or(Align::ONE), msg)?; Ok(()) @@ -519,7 +537,7 @@ where Index(local) => { let layout = self.layout_of(self.tcx.types.usize)?; - let n = self.access_local(self.frame(), local, Some(layout))?; + let n = self.local_to_op(self.frame(), local, Some(layout))?; let n = self.read_scalar(&n)?; let n = n.to_machine_usize(self)?; self.mplace_index(base, n)? @@ -594,11 +612,9 @@ where variant: VariantIdx, ) -> InterpResult<'tcx, PlaceTy<'tcx, M::PointerTag>> { // Downcast just changes the layout - Ok(match base.place { - Place::Ptr(mplace) => { - self.mplace_downcast(&MPlaceTy { mplace, layout: base.layout }, variant)?.into() - } - Place::Local { .. } => { + Ok(match base.try_as_mplace() { + Ok(mplace) => self.mplace_downcast(&mplace, variant)?.into(), + Err(..) => { let layout = base.layout.for_variant(self, variant); PlaceTy { layout, ..*base } } @@ -635,6 +651,16 @@ where self.mplace_to_simd(&mplace) } + pub fn local_to_place( + &self, + frame: usize, + local: mir::Local, + ) -> InterpResult<'tcx, PlaceTy<'tcx, M::PointerTag>> { + let layout = self.layout_of_local(&self.stack()[frame], local, None)?; + let place = Place::Local { frame, local }; + Ok(PlaceTy { place, layout, align: layout.align.abi }) + } + /// Computes a place. You should only use this if you intend to write into this /// place; for reading, a more efficient alternative is `eval_place_to_op`. #[instrument(skip(self), level = "debug")] @@ -642,11 +668,7 @@ where &mut self, place: mir::Place<'tcx>, ) -> InterpResult<'tcx, PlaceTy<'tcx, M::PointerTag>> { - let mut place_ty = PlaceTy { - // This works even for dead/uninitialized locals; we check further when writing - place: Place::Local { frame: self.frame_idx(), local: place.local }, - layout: self.layout_of_local(self.frame(), place.local, None)?, - }; + let mut place_ty = self.local_to_place(self.frame_idx(), place.local)?; for elem in place.projection.iter() { place_ty = self.place_projection(&place_ty, &elem)? @@ -654,14 +676,19 @@ where trace!("{:?}", self.dump_place(place_ty.place)); // Sanity-check the type we ended up with. - debug_assert!(mir_assign_valid_types( - *self.tcx, - self.param_env, - self.layout_of(self.subst_from_current_frame_and_normalize_erasing_regions( - place.ty(&self.frame().body.local_decls, *self.tcx).ty - )?)?, - place_ty.layout, - )); + debug_assert!( + mir_assign_valid_types( + *self.tcx, + self.param_env, + self.layout_of(self.subst_from_current_frame_and_normalize_erasing_regions( + place.ty(&self.frame().body.local_decls, *self.tcx).ty + )?)?, + place_ty.layout, + ), + "eval_place of a MIR place with type {:?} produced an interpret place with type {:?}", + place.ty(&self.frame().body.local_decls, *self.tcx).ty, + place_ty.layout.ty, + ); Ok(place_ty) } @@ -732,7 +759,7 @@ where } Place::Ptr(mplace) => mplace, // already referring to memory }; - let dest = MPlaceTy { mplace, layout: dest.layout }; + let dest = MPlaceTy { mplace, layout: dest.layout, align: dest.align }; // This is already in memory, write there. self.write_immediate_to_mplace_no_validate(src, &dest) @@ -766,7 +793,7 @@ where ) }; let size = s.size(&tcx); - //FIXME(#96185): assert_eq!(dest.layout.size, size, "abi::Scalar size does not match layout size"); + assert_eq!(size, dest.layout.size, "abi::Scalar size does not match layout size"); alloc.write_scalar(alloc_range(Size::ZERO, size), scalar) } Immediate::ScalarPair(a_val, b_val) => { @@ -794,9 +821,9 @@ where } pub fn write_uninit(&mut self, dest: &PlaceTy<'tcx, M::PointerTag>) -> InterpResult<'tcx> { - let mplace = match dest.place { - Place::Ptr(mplace) => MPlaceTy { mplace, layout: dest.layout }, - Place::Local { frame, local } => { + let mplace = match dest.try_as_mplace() { + Ok(mplace) => mplace, + Err((frame, local)) => { match M::access_local_mut(self, frame, local)? { Ok(local) => match dest.layout.abi { Abi::Scalar(_) => { @@ -816,7 +843,7 @@ where }, Err(mplace) => { // The local is in memory, go on below. - MPlaceTy { mplace, layout: dest.layout } + MPlaceTy { mplace, layout: dest.layout, align: dest.align } } } } @@ -934,7 +961,7 @@ where let dest = self.force_allocation(dest)?; self.copy_op_no_validate( src, - &PlaceTy::from(MPlaceTy { mplace: *dest, layout: src.layout }), + &PlaceTy::from(MPlaceTy { mplace: *dest, layout: src.layout, align: dest.align }), )?; if M::enforce_validity(self) { @@ -975,12 +1002,16 @@ where .size_and_align_of(&meta, &local_layout)? .expect("Cannot allocate for non-dyn-sized type"); let ptr = self.allocate_ptr(size, align, MemoryKind::Stack)?; - let mplace = MemPlace { ptr: ptr.into(), align, meta }; + let mplace = MemPlace { ptr: ptr.into(), meta }; if let LocalValue::Live(Operand::Immediate(value)) = local_val { // Preserve old value. // We don't have to validate as we can assume the local // was already valid for its type. - let mplace = MPlaceTy { mplace, layout: local_layout }; + let mplace = MPlaceTy { + mplace, + layout: local_layout, + align: local_layout.align.abi, + }; self.write_immediate_to_mplace_no_validate(value, &mplace)?; } // Now we can call `access_mut` again, asserting it goes well, @@ -995,7 +1026,7 @@ where Place::Ptr(mplace) => (mplace, None), }; // Return with the original layout, so that the caller can go on - Ok((MPlaceTy { mplace, layout: place.layout }, size)) + Ok((MPlaceTy { mplace, layout: place.layout, align: place.align }, size)) } #[inline(always)] @@ -1024,15 +1055,14 @@ where ) -> MPlaceTy<'tcx, M::PointerTag> { let ptr = self.allocate_bytes_ptr(str.as_bytes(), Align::ONE, kind, mutbl); let meta = Scalar::from_machine_usize(u64::try_from(str.len()).unwrap(), self); - let mplace = - MemPlace { ptr: ptr.into(), align: Align::ONE, meta: MemPlaceMeta::Meta(meta) }; + let mplace = MemPlace { ptr: ptr.into(), meta: MemPlaceMeta::Meta(meta) }; let ty = self.tcx.mk_ref( self.tcx.lifetimes.re_static, ty::TypeAndMut { ty: self.tcx.types.str_, mutbl }, ); let layout = self.layout_of(ty).unwrap(); - MPlaceTy { mplace, layout } + MPlaceTy { mplace, layout, align: layout.align.abi } } /// Writes the discriminant of the given variant. @@ -1152,7 +1182,11 @@ where assert_eq!(align, layout.align.abi); } - let mplace = MPlaceTy { mplace: MemPlace { meta: MemPlaceMeta::None, ..**mplace }, layout }; + let mplace = MPlaceTy { + mplace: MemPlace { meta: MemPlaceMeta::None, ..**mplace }, + layout, + align: layout.align.abi, + }; Ok((instance, mplace)) } } diff --git a/compiler/rustc_const_eval/src/interpret/step.rs b/compiler/rustc_const_eval/src/interpret/step.rs index 98f69456e49..2ee7ed57ab5 100644 --- a/compiler/rustc_const_eval/src/interpret/step.rs +++ b/compiler/rustc_const_eval/src/interpret/step.rs @@ -185,7 +185,9 @@ impl<'mir, 'tcx: 'mir, M: Machine<'mir, 'tcx>> InterpCx<'mir, 'tcx, M> { let left = self.read_immediate(&self.eval_operand(left, None)?)?; let layout = binop_right_homogeneous(bin_op).then_some(left.layout); let right = self.read_immediate(&self.eval_operand(right, layout)?)?; - self.binop_with_overflow(bin_op, &left, &right, &dest)?; + self.binop_with_overflow( + bin_op, /*force_overflow_checks*/ false, &left, &right, &dest, + )?; } UnaryOp(un_op, ref operand) => { diff --git a/compiler/rustc_const_eval/src/interpret/traits.rs b/compiler/rustc_const_eval/src/interpret/traits.rs index 9c48f3e8337..22c23df7b1a 100644 --- a/compiler/rustc_const_eval/src/interpret/traits.rs +++ b/compiler/rustc_const_eval/src/interpret/traits.rs @@ -1,6 +1,6 @@ use std::convert::TryFrom; -use rustc_middle::mir::interpret::{InterpResult, Pointer, PointerArithmetic}; +use rustc_middle::mir::interpret::{alloc_range, InterpResult, Pointer, PointerArithmetic}; use rustc_middle::ty::{ self, Ty, TyCtxt, COMMON_VTABLE_ENTRIES_ALIGN, COMMON_VTABLE_ENTRIES_DROPINPLACE, COMMON_VTABLE_ENTRIES_SIZE, @@ -102,18 +102,18 @@ impl<'mir, 'tcx: 'mir, M: Machine<'mir, 'tcx>> InterpCx<'mir, 'tcx, M> { )? .expect("cannot be a ZST"); let size = vtable - .read_integer( + .read_integer(alloc_range( pointer_size * u64::try_from(COMMON_VTABLE_ENTRIES_SIZE).unwrap(), pointer_size, - )? + ))? .check_init()?; let size = size.to_machine_usize(self)?; let size = Size::from_bytes(size); let align = vtable - .read_integer( + .read_integer(alloc_range( pointer_size * u64::try_from(COMMON_VTABLE_ENTRIES_ALIGN).unwrap(), pointer_size, - )? + ))? .check_init()?; let align = align.to_machine_usize(self)?; let align = Align::from_bytes(align).map_err(|e| err_ub!(InvalidVtableAlignment(e)))?; diff --git a/compiler/rustc_const_eval/src/interpret/util.rs b/compiler/rustc_const_eval/src/interpret/util.rs index b9866995e9f..2bc521d5bbe 100644 --- a/compiler/rustc_const_eval/src/interpret/util.rs +++ b/compiler/rustc_const_eval/src/interpret/util.rs @@ -1,5 +1,5 @@ use rustc_middle::mir::interpret::InterpResult; -use rustc_middle::ty::{self, Ty, TyCtxt, TypeFoldable, TypeSuperFoldable, TypeVisitor}; +use rustc_middle::ty::{self, Ty, TyCtxt, TypeSuperVisitable, TypeVisitable, TypeVisitor}; use std::convert::TryInto; use std::ops::ControlFlow; @@ -10,7 +10,7 @@ use std::ops::ControlFlow; /// case these parameters are unused. pub(crate) fn ensure_monomorphic_enough<'tcx, T>(tcx: TyCtxt<'tcx>, ty: T) -> InterpResult<'tcx> where - T: TypeFoldable<'tcx>, + T: TypeVisitable<'tcx>, { debug!("ensure_monomorphic_enough: ty={:?}", ty); if !ty.needs_subst() { @@ -44,22 +44,10 @@ where let is_used = unused_params.contains(index).map_or(true, |unused| !unused); // Only recurse when generic parameters in fns, closures and generators // are used and require substitution. - match (is_used, subst.needs_subst()) { - // Just in case there are closures or generators within this subst, - // recurse. - (true, true) => return subst.visit_with(self), - // Confirm that polymorphization replaced the parameter with - // `ty::Param`/`ty::ConstKind::Param`. - (false, true) if cfg!(debug_assertions) => match subst.unpack() { - ty::subst::GenericArgKind::Type(ty) => { - assert!(matches!(ty.kind(), ty::Param(_))) - } - ty::subst::GenericArgKind::Const(ct) => { - assert!(matches!(ct.kind(), ty::ConstKind::Param(_))) - } - ty::subst::GenericArgKind::Lifetime(..) => (), - }, - _ => {} + // Just in case there are closures or generators within this subst, + // recurse. + if is_used && subst.needs_subst() { + return subst.visit_with(self); } } ControlFlow::CONTINUE diff --git a/compiler/rustc_const_eval/src/interpret/validity.rs b/compiler/rustc_const_eval/src/interpret/validity.rs index 905ab6cb578..0bf78446e37 100644 --- a/compiler/rustc_const_eval/src/interpret/validity.rs +++ b/compiler/rustc_const_eval/src/interpret/validity.rs @@ -244,7 +244,7 @@ impl<'rt, 'mir, 'tcx: 'mir, M: Machine<'mir, 'tcx>> ValidityVisitor<'rt, 'mir, ' // for a generator). let var_hir_id = captured_place.get_root_variable(); let node = self.ecx.tcx.hir().get(var_hir_id); - if let hir::Node::Binding(pat) = node { + if let hir::Node::Pat(pat) = node { if let hir::PatKind::Binding(_, _, ident, _) = pat.kind { name = Some(ident.name); } @@ -593,16 +593,6 @@ impl<'rt, 'mir, 'tcx: 'mir, M: Machine<'mir, 'tcx>> ValidityVisitor<'rt, 'mir, ' self.check_safe_pointer(value, "reference")?; Ok(true) } - ty::Adt(def, ..) if def.is_box() => { - let unique = self.ecx.operand_field(value, 0)?; - let nonnull = self.ecx.operand_field(&unique, 0)?; - let ptr = self.ecx.operand_field(&nonnull, 0)?; - self.check_safe_pointer(&ptr, "box")?; - - // Check other fields of Box - self.walk_value(value)?; - Ok(true) - } ty::FnPtr(_sig) => { let value = try_validation!( self.ecx.read_scalar(value).and_then(|v| v.check_init()), @@ -814,6 +804,12 @@ impl<'rt, 'mir, 'tcx: 'mir, M: Machine<'mir, 'tcx>> ValueVisitor<'mir, 'tcx, M> } #[inline] + fn visit_box(&mut self, op: &OpTy<'tcx, M::PointerTag>) -> InterpResult<'tcx> { + self.check_safe_pointer(op, "box")?; + Ok(()) + } + + #[inline] fn visit_value(&mut self, op: &OpTy<'tcx, M::PointerTag>) -> InterpResult<'tcx> { trace!("visit_value: {:?}, {:?}", *op, op.layout); @@ -821,8 +817,6 @@ impl<'rt, 'mir, 'tcx: 'mir, M: Machine<'mir, 'tcx>> ValueVisitor<'mir, 'tcx, M> if self.try_visit_primitive(op)? { return Ok(()); } - // Sanity check: `builtin_deref` does not know any pointers that are not primitive. - assert!(op.layout.ty.builtin_deref(true).is_none()); // Special check preventing `UnsafeCell` in the inner part of constants if let Some(def) = op.layout.ty.ty_adt_def() { diff --git a/compiler/rustc_const_eval/src/interpret/visitor.rs b/compiler/rustc_const_eval/src/interpret/visitor.rs index 679d30227f1..ded4c6a557a 100644 --- a/compiler/rustc_const_eval/src/interpret/visitor.rs +++ b/compiler/rustc_const_eval/src/interpret/visitor.rs @@ -92,7 +92,7 @@ impl<'mir, 'tcx: 'mir, M: Machine<'mir, 'tcx>> Value<'mir, 'tcx, M> &self, _ecx: &InterpCx<'mir, 'tcx, M>, ) -> InterpResult<'tcx, OpTy<'tcx, M::PointerTag>> { - Ok((*self).into()) + Ok(self.into()) } #[inline(always)] @@ -151,6 +151,14 @@ macro_rules! make_value_visitor { { Ok(()) } + /// Visits the given value as the pointer of a `Box`. There is nothing to recurse into. + /// The type of `v` will be a raw pointer, but this is a field of `Box<T>` and the + /// pointee type is the actual `T`. + #[inline(always)] + fn visit_box(&mut self, _v: &Self::V) -> InterpResult<'tcx> + { + Ok(()) + } /// Visits this value as an aggregate, you are getting an iterator yielding /// all the fields (still in an `InterpResult`, you have to do error handling yourself). /// Recurses into the fields. @@ -221,6 +229,47 @@ macro_rules! make_value_visitor { // Slices do not need special handling here: they have `Array` field // placement with length 0, so we enter the `Array` case below which // indirectly uses the metadata to determine the actual length. + + // However, `Box`... let's talk about `Box`. + ty::Adt(def, ..) if def.is_box() => { + // `Box` is a hybrid primitive-library-defined type that one the one hand is + // a dereferenceable pointer, on the other hand has *basically arbitrary + // user-defined layout* since the user controls the 'allocator' field. So it + // cannot be treated like a normal pointer, since it does not fit into an + // `Immediate`. Yeah, it is quite terrible. But many visitors want to do + // something with "all boxed pointers", so we handle this mess for them. + // + // When we hit a `Box`, we do not do the usual `visit_aggregate`; instead, + // we (a) call `visit_box` on the pointer value, and (b) recurse on the + // allocator field. We also assert tons of things to ensure we do not miss + // any other fields. + + // `Box` has two fields: the pointer we care about, and the allocator. + assert_eq!(v.layout().fields.count(), 2, "`Box` must have exactly 2 fields"); + let (unique_ptr, alloc) = + (v.project_field(self.ecx(), 0)?, v.project_field(self.ecx(), 1)?); + // Unfortunately there is some type junk in the way here: `unique_ptr` is a `Unique`... + // (which means another 2 fields, the second of which is a `PhantomData`) + assert_eq!(unique_ptr.layout().fields.count(), 2); + let (nonnull_ptr, phantom) = ( + unique_ptr.project_field(self.ecx(), 0)?, + unique_ptr.project_field(self.ecx(), 1)?, + ); + assert!( + phantom.layout().ty.ty_adt_def().is_some_and(|adt| adt.is_phantom_data()), + "2nd field of `Unique` should be PhantomData but is {:?}", + phantom.layout().ty, + ); + // ... that contains a `NonNull`... (gladly, only a single field here) + assert_eq!(nonnull_ptr.layout().fields.count(), 1); + let raw_ptr = nonnull_ptr.project_field(self.ecx(), 0)?; // the actual raw ptr + // ... whose only field finally is a raw ptr we can dereference. + self.visit_box(&raw_ptr)?; + + // The second `Box` field is the allocator, which we recursively check for validity + // like in regular structs. + self.visit_field(v, 1, &alloc)?; + } _ => {}, }; diff --git a/compiler/rustc_const_eval/src/lib.rs b/compiler/rustc_const_eval/src/lib.rs index 5bf91879066..2d42ae236ad 100644 --- a/compiler/rustc_const_eval/src/lib.rs +++ b/compiler/rustc_const_eval/src/lib.rs @@ -21,6 +21,7 @@ Rust MIR: a lowered representation of Rust. #![feature(trusted_step)] #![feature(try_blocks)] #![feature(yeet_expr)] +#![feature(is_some_with)] #![recursion_limit = "256"] #![allow(rustc::potential_query_instability)] diff --git a/compiler/rustc_const_eval/src/transform/check_consts/check.rs b/compiler/rustc_const_eval/src/transform/check_consts/check.rs index 069fbed36ee..f87de4f6a08 100644 --- a/compiler/rustc_const_eval/src/transform/check_consts/check.rs +++ b/compiler/rustc_const_eval/src/transform/check_consts/check.rs @@ -10,7 +10,7 @@ use rustc_middle::mir::visit::{MutatingUseContext, NonMutatingUseContext, PlaceC use rustc_middle::mir::*; use rustc_middle::ty::subst::{GenericArgKind, InternalSubsts}; use rustc_middle::ty::{self, adjustment::PointerCast, Instance, InstanceDef, Ty, TyCtxt}; -use rustc_middle::ty::{Binder, TraitPredicate, TraitRef, TypeFoldable}; +use rustc_middle::ty::{Binder, TraitPredicate, TraitRef, TypeVisitable}; use rustc_mir_dataflow::{self, Analysis}; use rustc_span::{sym, Span, Symbol}; use rustc_trait_selection::traits::error_reporting::InferCtxtExt; @@ -418,7 +418,7 @@ impl<'tcx> Visitor<'tcx> for Checker<'_, 'tcx> { PlaceContext::MutatingUse(MutatingUseContext::Borrow) } }; - self.visit_local(&reborrowed_place_ref.local, ctx, location); + self.visit_local(reborrowed_place_ref.local, ctx, location); self.visit_projection(reborrowed_place_ref, ctx, location); return; } @@ -431,7 +431,7 @@ impl<'tcx> Visitor<'tcx> for Checker<'_, 'tcx> { } Mutability::Mut => PlaceContext::MutatingUse(MutatingUseContext::AddressOf), }; - self.visit_local(&reborrowed_place_ref.local, ctx, location); + self.visit_local(reborrowed_place_ref.local, ctx, location); self.visit_projection(reborrowed_place_ref, ctx, location); return; } diff --git a/compiler/rustc_const_eval/src/transform/promote_consts.rs b/compiler/rustc_const_eval/src/transform/promote_consts.rs index 3595a488d0c..6298fa7f062 100644 --- a/compiler/rustc_const_eval/src/transform/promote_consts.rs +++ b/compiler/rustc_const_eval/src/transform/promote_consts.rs @@ -17,7 +17,7 @@ use rustc_middle::mir::traversal::ReversePostorderIter; use rustc_middle::mir::visit::{MutVisitor, MutatingUseContext, PlaceContext, Visitor}; use rustc_middle::mir::*; use rustc_middle::ty::subst::InternalSubsts; -use rustc_middle::ty::{self, List, TyCtxt, TypeFoldable}; +use rustc_middle::ty::{self, List, TyCtxt, TypeVisitable}; use rustc_span::Span; use rustc_index::vec::{Idx, IndexVec}; @@ -106,7 +106,7 @@ struct Collector<'a, 'tcx> { } impl<'tcx> Visitor<'tcx> for Collector<'_, 'tcx> { - fn visit_local(&mut self, &index: &Local, context: PlaceContext, location: Location) { + fn visit_local(&mut self, index: Local, context: PlaceContext, location: Location) { debug!("visit_local: index={:?} context={:?} location={:?}", index, context, location); // We're only interested in temporaries and the return place match self.ccx.body.local_kind(index) { diff --git a/compiler/rustc_const_eval/src/transform/validate.rs b/compiler/rustc_const_eval/src/transform/validate.rs index 66d66ea9510..7b9c6329d32 100644 --- a/compiler/rustc_const_eval/src/transform/validate.rs +++ b/compiler/rustc_const_eval/src/transform/validate.rs @@ -7,12 +7,12 @@ use rustc_middle::mir::interpret::Scalar; use rustc_middle::mir::visit::NonUseContext::VarDebugInfo; use rustc_middle::mir::visit::{PlaceContext, Visitor}; use rustc_middle::mir::{ - traversal, AggregateKind, BasicBlock, BinOp, Body, BorrowKind, Local, Location, MirPass, - MirPhase, Operand, Place, PlaceElem, PlaceRef, ProjectionElem, Rvalue, SourceScope, Statement, - StatementKind, Terminator, TerminatorKind, UnOp, START_BLOCK, + traversal, AggregateKind, BasicBlock, BinOp, Body, BorrowKind, CastKind, Local, Location, + MirPass, MirPhase, Operand, Place, PlaceElem, PlaceRef, ProjectionElem, Rvalue, SourceScope, + Statement, StatementKind, Terminator, TerminatorKind, UnOp, START_BLOCK, }; use rustc_middle::ty::fold::BottomUpFolder; -use rustc_middle::ty::{self, InstanceDef, ParamEnv, Ty, TyCtxt, TypeFoldable}; +use rustc_middle::ty::{self, InstanceDef, ParamEnv, Ty, TyCtxt, TypeFoldable, TypeVisitable}; use rustc_mir_dataflow::impls::MaybeStorageLive; use rustc_mir_dataflow::storage::always_live_locals; use rustc_mir_dataflow::{Analysis, ResultsCursor}; @@ -196,8 +196,8 @@ impl<'a, 'tcx> TypeChecker<'a, 'tcx> { } impl<'a, 'tcx> Visitor<'tcx> for TypeChecker<'a, 'tcx> { - fn visit_local(&mut self, local: &Local, context: PlaceContext, location: Location) { - if self.body.local_decls.get(*local).is_none() { + fn visit_local(&mut self, local: Local, context: PlaceContext, location: Location) { + if self.body.local_decls.get(local).is_none() { self.fail( location, format!("local {:?} has no corresponding declaration in `body.local_decls`", local), @@ -208,7 +208,7 @@ impl<'a, 'tcx> Visitor<'tcx> for TypeChecker<'a, 'tcx> { // Uses of locals must occur while the local's storage is allocated. self.storage_liveness.seek_after_primary_effect(location); let locals_with_storage = self.storage_liveness.get(); - if !locals_with_storage.contains(*local) { + if !locals_with_storage.contains(local) { self.fail(location, format!("use of local {:?}, which has no storage here", local)); } } @@ -361,6 +361,7 @@ impl<'a, 'tcx> Visitor<'tcx> for TypeChecker<'a, 'tcx> { ); } } + Rvalue::Ref(..) => {} Rvalue::Len(p) => { let pty = p.ty(&self.body.local_decls, self.tcx).ty; check_kinds!( @@ -503,7 +504,30 @@ impl<'a, 'tcx> Visitor<'tcx> for TypeChecker<'a, 'tcx> { let a = operand.ty(&self.body.local_decls, self.tcx); check_kinds!(a, "Cannot shallow init type {:?}", ty::RawPtr(..)); } - _ => {} + Rvalue::Cast(kind, operand, target_type) => { + match kind { + CastKind::Misc => { + let op_ty = operand.ty(self.body, self.tcx); + if op_ty.is_enum() { + self.fail( + location, + format!( + "enum -> int casts should go through `Rvalue::Discriminant`: {operand:?}:{op_ty} as {target_type}", + ), + ); + } + } + // Nothing to check here + CastKind::PointerFromExposedAddress + | CastKind::PointerExposeAddress + | CastKind::Pointer(_) => {} + } + } + Rvalue::Repeat(_, _) + | Rvalue::ThreadLocalRef(_) + | Rvalue::AddressOf(_, _) + | Rvalue::NullaryOp(_, _) + | Rvalue::Discriminant(_) => {} } self.super_rvalue(rvalue, location); } @@ -823,8 +847,8 @@ impl<'a, 'tcx> Visitor<'tcx> for TypeChecker<'a, 'tcx> { self.super_terminator(terminator, location); } - fn visit_source_scope(&mut self, scope: &SourceScope) { - if self.body.source_scopes.get(*scope).is_none() { + fn visit_source_scope(&mut self, scope: SourceScope) { + if self.body.source_scopes.get(scope).is_none() { self.tcx.sess.diagnostic().delay_span_bug( self.body.span, &format!( diff --git a/compiler/rustc_const_eval/src/util/collect_writes.rs b/compiler/rustc_const_eval/src/util/collect_writes.rs index 9c56fd722bd..8d92bb35938 100644 --- a/compiler/rustc_const_eval/src/util/collect_writes.rs +++ b/compiler/rustc_const_eval/src/util/collect_writes.rs @@ -24,8 +24,8 @@ struct FindLocalAssignmentVisitor { } impl<'tcx> Visitor<'tcx> for FindLocalAssignmentVisitor { - fn visit_local(&mut self, local: &Local, place_context: PlaceContext, location: Location) { - if self.needle != *local { + fn visit_local(&mut self, local: Local, place_context: PlaceContext, location: Location) { + if self.needle != local { return; } diff --git a/compiler/rustc_driver/src/lib.rs b/compiler/rustc_driver/src/lib.rs index 3096af90d47..b71cdad718a 100644 --- a/compiler/rustc_driver/src/lib.rs +++ b/compiler/rustc_driver/src/lib.rs @@ -849,10 +849,10 @@ Available lint options: }; println!("Lint checks provided by rustc:\n"); - println!(" {} {:7.7} {}", padded("name"), "default", "meaning"); - println!(" {} {:7.7} {}", padded("----"), "-------", "-------"); let print_lints = |lints: Vec<&Lint>| { + println!(" {} {:7.7} {}", padded("name"), "default", "meaning"); + println!(" {} {:7.7} {}", padded("----"), "-------", "-------"); for lint in lints { let name = lint.name_lower().replace('_', "-"); println!( @@ -884,11 +884,15 @@ Available lint options: }; println!("Lint groups provided by rustc:\n"); - println!(" {} sub-lints", padded("name")); - println!(" {} ---------", padded("----")); - println!(" {} all lints that are set to issue warnings", padded("warnings")); - let print_lint_groups = |lints: Vec<(&'static str, Vec<LintId>)>| { + let print_lint_groups = |lints: Vec<(&'static str, Vec<LintId>)>, all_warnings| { + println!(" {} sub-lints", padded("name")); + println!(" {} ---------", padded("----")); + + if all_warnings { + println!(" {} all lints that are set to issue warnings", padded("warnings")); + } + for (name, to) in lints { let name = name.to_lowercase().replace('_', "-"); let desc = to @@ -901,7 +905,7 @@ Available lint options: println!("\n"); }; - print_lint_groups(builtin_groups); + print_lint_groups(builtin_groups, true); match (loaded_plugins, plugin.len(), plugin_groups.len()) { (false, 0, _) | (false, _, 0) => { @@ -916,7 +920,7 @@ Available lint options: } if g > 0 { println!("Lint groups provided by plugins loaded by this crate:\n"); - print_lint_groups(plugin_groups); + print_lint_groups(plugin_groups, false); } } } diff --git a/compiler/rustc_error_messages/locales/en-US/lint.ftl b/compiler/rustc_error_messages/locales/en-US/lint.ftl new file mode 100644 index 00000000000..e7e07093c03 --- /dev/null +++ b/compiler/rustc_error_messages/locales/en-US/lint.ftl @@ -0,0 +1,400 @@ +lint-array-into-iter = + this method call resolves to `<&{$target} as IntoIterator>::into_iter` (due to backwards compatibility), but will resolve to <{$target} as IntoIterator>::into_iter in Rust 2021 + .use-iter-suggestion = use `.iter()` instead of `.into_iter()` to avoid ambiguity + .remove-into-iter-suggestion = or remove `.into_iter()` to iterate by value + .use-explicit-into-iter-suggestion = + or use `IntoIterator::into_iter(..)` instead of `.into_iter()` to explicitly iterate by value + +lint-enum-intrinsics-mem-discriminant = + the return value of `mem::discriminant` is unspecified when called with a non-enum type + .note = the argument to `discriminant` should be a reference to an enum, but it was passed a reference to a `{$ty_param}`, which is not an enum. + +lint-enum-intrinsics-mem-variant = + the return value of `mem::variant_count` is unspecified when called with a non-enum type + .note = the type parameter of `variant_count` should be an enum, but it was instantiated with the type `{$ty_param}`, which is not an enum. + +lint-expectation = this lint expectation is unfulfilled + .note = the `unfulfilled_lint_expectations` lint can't be expected and will always produce this message + +lint-hidden-unicode-codepoints = unicode codepoint changing visible direction of text present in {$label} + .label = this {$label} contains {$count -> + [one] an invisible + *[other] invisible + } unicode text flow control {$count -> + [one] codepoint + *[other] codepoints + } + .note = these kind of unicode codepoints change the way text flows on applications that support them, but can cause confusion because they change the order of characters on the screen + .suggestion-remove = if their presence wasn't intentional, you can remove them + .suggestion-escape = if you want to keep them but make them visible in your source code, you can escape them + .no-suggestion-note-escape = if you want to keep them but make them visible in your source code, you can escape them: {$escaped} + +lint-default-hash-types = prefer `{$preferred}` over `{$used}`, it has better performance + .note = a `use rustc_data_structures::fx::{$preferred}` may be necessary + +lint-query-instability = using `{$query}` can result in unstable query results + .note = if you believe this case to be fine, allow this lint and add a comment explaining your rationale + +lint-tykind-kind = usage of `ty::TyKind::<kind>` + .suggestion = try using `ty::<kind>` directly + +lint-tykind = usage of `ty::TyKind` + .help = try using `Ty` instead + +lint-ty-qualified = usage of qualified `ty::{$ty}` + .suggestion = try importing it and using it unqualified + +lint-lintpass-by-hand = implementing `LintPass` by hand + .help = try using `declare_lint_pass!` or `impl_lint_pass!` instead + +lint-non-existant-doc-keyword = found non-existing keyword `{$keyword}` used in `#[doc(keyword = \"...\")]` + .help = only existing keywords are allowed in core/std + +lint-diag-out-of-impl = + diagnostics should only be created in `SessionDiagnostic`/`AddSubdiagnostic` impls + +lint-untranslatable-diag = diagnostics should be created using translatable messages + +lint-cstring-ptr = getting the inner pointer of a temporary `CString` + .as-ptr-label = this pointer will be invalid + .unwrap-label = this `CString` is deallocated at the end of the statement, bind it to a variable to extend its lifetime + .note = pointers do not have a lifetime; when calling `as_ptr` the `CString` will be deallocated at the end of the statement because nothing is referencing it as far as the type system is concerned + .help = for more information, see https://doc.rust-lang.org/reference/destructors.html + +lint-identifier-non-ascii-char = identifier contains non-ASCII characters + +lint-identifier-uncommon-codepoints = identifier contains uncommon Unicode codepoints + +lint-confusable-identifier-pair = identifier pair considered confusable between `{$existing_sym}` and `{$sym}` + .label = this is where the previous identifier occurred + +lint-mixed-script-confusables = + the usage of Script Group `{$set}` in this crate consists solely of mixed script confusables + .includes-note = the usage includes {$includes} + .note = please recheck to make sure their usages are indeed what you want + +lint-non-fmt-panic = panic message is not a string literal + .note = this usage of `{$name}!()` is deprecated; it will be a hard error in Rust 2021 + .more-info-note = for more information, see <https://doc.rust-lang.org/nightly/edition-guide/rust-2021/panic-macro-consistency.html> + .supports-fmt-note = the `{$name}!()` macro supports formatting, so there's no need for the `format!()` macro here + .supports-fmt-suggestion = remove the `format!(..)` macro call + .display-suggestion = add a "{"{"}{"}"}" format string to `Display` the message + .debug-suggestion = + add a "{"{"}:?{"}"}" format string to use the `Debug` implementation of `{$ty}` + .panic-suggestion = {$already_suggested -> + [true] or use + *[false] use + } std::panic::panic_any instead + +lint-non-fmt-panic-unused = + panic message contains {$count -> + [one] an unused + *[other] unused + } formatting {$count -> + [one] placeholder + *[other] placeholders + } + .note = this message is not used as a format string when given without arguments, but will be in Rust 2021 + .add-args-suggestion = add the missing {$count -> + [one] argument + *[other] arguments + } + .add-fmt-suggestion = or add a "{"{"}{"}"}" format string to use the message literally + +lint-non-fmt-panic-braces = + panic message contains {$count -> + [one] a brace + *[other] braces + } + .note = this message is not used as a format string, but will be in Rust 2021 + .suggestion = add a "{"{"}{"}"}" format string to use the message literally + +lint-non-camel-case-type = {$sort} `{$name}` should have an upper camel case name + .suggestion = convert the identifier to upper camel case + .label = should have an UpperCamelCase name + +lint-non-snake-case = {$sort} `{$name}` should have a snake case name + .rename-or-convert-suggestion = rename the identifier or convert it to a snake case raw identifier + .cannot-convert-note = `{$sc}` cannot be used as a raw identifier + .rename-suggestion = rename the identifier + .convert-suggestion = convert the identifier to snake case + .help = convert the identifier to snake case: `{$sc}` + .label = should have a snake_case name + +lint-non-upper_case-global = {$sort} `{$name}` should have an upper case name + .suggestion = convert the identifier to upper case + .label = should have an UPPER_CASE name + +lint-noop-method-call = call to `.{$method}()` on a reference in this situation does nothing + .label = unnecessary method call + .note = the type `{$receiver_ty}` which `{$method}` is being called on is the same as the type returned from `{$method}`, so the method call does not do anything and can be removed + +lint-pass-by-value = passing `{$ty}` by reference + .suggestion = try passing by value + +lint-redundant-semicolons = + unnecessary trailing {$multiple -> + [true] semicolons + *[false] semicolon + } + .suggestion = remove {$multiple -> + [true] these semicolons + *[false] this semicolon + } + +lint-drop-trait-constraints = + bounds on `{$predicate}` are most likely incorrect, consider instead using `{$needs_drop}` to detect whether a type can be trivially dropped + +lint-drop-glue = + types that do not implement `Drop` can still have drop glue, consider instead using `{$needs_drop}` to detect whether a type is trivially dropped + +lint-range-endpoint-out-of-range = range endpoint is out of range for `{$ty}` + .suggestion = use an inclusive range instead + +lint-overflowing-bin-hex = literal out of range for `{$ty}` + .negative-note = the literal `{$lit}` (decimal `{$dec}`) does not fit into the type `{$ty}` + .negative-becomes-note = and the value `-{$lit}` will become `{$actually}{$ty}` + .positive-note = the literal `{$lit}` (decimal `{$dec}`) does not fit into the type `{$ty}` and will become `{$actually}{$ty}` + .suggestion = consider using the type `{$suggestion_ty}` instead + .help = consider using the type `{$suggestion_ty}` instead + +lint-overflowing-int = literal out of range for `{$ty}` + .note = the literal `{$lit}` does not fit into the type `{$ty}` whose range is `{$min}..={$max}` + .help = consider using the type `{$suggestion_ty}` instead + +lint-only-cast-u8-to-char = only `u8` can be cast into `char` + .suggestion = use a `char` literal instead + +lint-overflowing-uint = literal out of range for `{$ty}` + .note = the literal `{$lit}` does not fit into the type `{$ty}` whose range is `{$min}..={$max}` + +lint-overflowing-literal = literal out of range for `{$ty}` + .note = the literal `{$lit}` does not fit into the type `{$ty}` and will be converted to `{$ty}::INFINITY` + +lint-unused-comparisons = comparison is useless due to type limits + +lint-improper-ctypes = `extern` {$desc} uses type `{$ty}`, which is not FFI-safe + .label = not FFI-safe + .note = the type is defined here + +lint-improper-ctypes-opaque = opaque types have no C equivalent + +lint-improper-ctypes-fnptr-reason = this function pointer has Rust-specific calling convention +lint-improper-ctypes-fnptr-help = consider using an `extern fn(...) -> ...` function pointer instead + +lint-improper-ctypes-tuple-reason = tuples have unspecified layout +lint-improper-ctypes-tuple-help = consider using a struct instead + +lint-improper-ctypes-str-reason = string slices have no C equivalent +lint-improper-ctypes-str-help = consider using `*const u8` and a length instead + +lint-improper-ctypes-dyn = trait objects have no C equivalent + +lint-improper-ctypes-slice-reason = slices have no C equivalent +lint-improper-ctypes-slice-help = consider using a raw pointer instead + +lint-improper-ctypes-128bit = 128-bit integers don't currently have a known stable ABI + +lint-improper-ctypes-char-reason = the `char` type has no C equivalent +lint-improper-ctypes-char-help = consider using `u32` or `libc::wchar_t` instead + +lint-improper-ctypes-non-exhaustive = this enum is non-exhaustive +lint-improper-ctypes-non-exhaustive-variant = this enum has non-exhaustive variants + +lint-improper-ctypes-enum-repr-reason = enum has no representation hint +lint-improper-ctypes-enum-repr-help = + consider adding a `#[repr(C)]`, `#[repr(transparent)]`, or integer `#[repr(...)]` attribute to this enum + +lint-improper-ctypes-struct-fieldless-reason = this struct has no fields +lint-improper-ctypes-struct-fieldless-help = consider adding a member to this struct + +lint-improper-ctypes-union-fieldless-reason = this union has no fields +lint-improper-ctypes-union-fieldless-help = consider adding a member to this union + +lint-improper-ctypes-struct-non-exhaustive = this struct is non-exhaustive +lint-improper-ctypes-union-non-exhaustive = this union is non-exhaustive + +lint-improper-ctypes-struct-layout-reason = this struct has unspecified layout +lint-improper-ctypes-struct-layout-help = consider adding a `#[repr(C)]` or `#[repr(transparent)]` attribute to this struct + +lint-improper-ctypes-union-layout-reason = this union has unspecified layout +lint-improper-ctypes-union-layout-help = consider adding a `#[repr(C)]` or `#[repr(transparent)]` attribute to this union + +lint-improper-ctypes-box = box cannot be represented as a single pointer + +lint-improper-ctypes-enum-phantomdata = this enum contains a PhantomData field + +lint-improper-ctypes-struct-zst = this struct contains only zero-sized fields + +lint-improper-ctypes-array-reason = passing raw arrays by value is not FFI-safe +lint-improper-ctypes-array-help = consider passing a pointer to the array + +lint-improper-ctypes-only-phantomdata = composed only of `PhantomData` + +lint-variant-size-differences = + enum variant is more than three times larger ({$largest} bytes) than the next largest + +lint-atomic-ordering-load = atomic loads cannot have `Release` or `AcqRel` ordering + .help = consider using ordering modes `Acquire`, `SeqCst` or `Relaxed` + +lint-atomic-ordering-store = atomic stores cannot have `Acquire` or `AcqRel` ordering + .help = consider using ordering modes `Release`, `SeqCst` or `Relaxed` + +lint-atomic-ordering-fence = memory fences cannot have `Relaxed` ordering + .help = consider using ordering modes `Acquire`, `Release`, `AcqRel` or `SeqCst` + +lint-atomic-ordering-invalid = `{$method}`'s failure ordering may not be `Release` or `AcqRel`, since a failed `{$method}` does not result in a write + .label = invalid failure ordering + .help = consider using `Acquire` or `Relaxed` failure ordering instead + +lint-atomic-ordering-invalid-fail-success = `{$method}`'s success ordering must be at least as strong as its failure ordering + .fail-label = `{$fail_ordering}` failure ordering + .success-label = `{$success_ordering}` success ordering + .suggestion = consider using `{$success_suggestion}` success ordering instead + +lint-unused-op = unused {$op} that must be used + .label = the {$op} produces a value + .suggestion = use `let _ = ...` to ignore the resulting value + +lint-unused-result = unused result of type `{$ty}` + +lint-unused-closure = + unused {$pre}{$count -> + [one] closure + *[other] closures + }{$post} that must be used + .note = closures are lazy and do nothing unless called + +lint-unused-generator = + unused {$pre}{$count -> + [one] generator + *[other] generator + }{$post} that must be used + .note = generators are lazy and do nothing unless resumed + +lint-unused-def = unused {$pre}`{$def}`{$post} that must be used + +lint-path-statement-drop = path statement drops value + .suggestion = use `drop` to clarify the intent + +lint-path-statement-no-effect = path statement with no effect + +lint-unused-delim = unnecessary {$delim} around {$item} + .suggestion = remove these {$delim} + +lint-unused-import-braces = braces around {$node} is unnecessary + +lint-unused-allocation = unnecessary allocation, use `&` instead +lint-unused-allocation-mut = unnecessary allocation, use `&mut` instead + +lint-builtin-while-true = denote infinite loops with `loop {"{"} ... {"}"}` + .suggestion = use `loop` + +lint-builtin-box-pointers = type uses owned (Box type) pointers: {$ty} + +lint-builtin-non-shorthand-field-patterns = the `{$ident}:` in this pattern is redundant + .suggestion = use shorthand field pattern + +lint-builtin-overridden-symbol-name = + the linker's behavior with multiple libraries exporting duplicate symbol names is undefined and Rust cannot provide guarantees when you manually override them + +lint-builtin-overridden-symbol-section = + the program's behavior with overridden link sections on items is unpredictable and Rust cannot provide guarantees when you manually override them + +lint-builtin-allow-internal-unsafe = + `allow_internal_unsafe` allows defining macros using unsafe without triggering the `unsafe_code` lint at their call site + +lint-builtin-unsafe-block = usage of an `unsafe` block + +lint-builtin-unsafe-trait = declaration of an `unsafe` trait + +lint-builtin-unsafe-impl = implementation of an `unsafe` trait + +lint-builtin-no-mangle-fn = declaration of a `no_mangle` function +lint-builtin-export-name-fn = declaration of a function with `export_name` +lint-builtin-link-section-fn = declaration of a function with `link_section` + +lint-builtin-no-mangle-static = declaration of a `no_mangle` static +lint-builtin-export-name-static = declaration of a static with `export_name` +lint-builtin-link-section-static = declaration of a static with `link_section` + +lint-builtin-no-mangle-method = declaration of a `no_mangle` method +lint-builtin-export-name-method = declaration of a method with `export_name` + +lint-builtin-decl-unsafe-fn = declaration of an `unsafe` function +lint-builtin-decl-unsafe-method = declaration of an `unsafe` method +lint-builtin-impl-unsafe-method = implementation of an `unsafe` method + +lint-builtin-missing-doc = missing documentation for {$article} {$desc} + +lint-builtin-missing-copy-impl = type could implement `Copy`; consider adding `impl Copy` + +lint-builtin-missing-debug-impl = + type does not implement `{$debug}`; consider adding `#[derive(Debug)]` or a manual implementation + +lint-builtin-anonymous-params = anonymous parameters are deprecated and will be removed in the next edition + .suggestion = try naming the parameter or explicitly ignoring it + +lint-builtin-deprecated-attr-link = use of deprecated attribute `{$name}`: {$reason}. See {$link} +lint-builtin-deprecated-attr-used = use of deprecated attribute `{$name}`: no longer used. +lint-builtin-deprecated-attr-default-suggestion = remove this attribute + +lint-builtin-unused-doc-comment = unused doc comment + .label = rustdoc does not generate documentation for {$kind} + .plain-help = use `//` for a plain comment + .block-help = use `/* */` for a plain comment + +lint-builtin-no-mangle-generic = functions generic over types or consts must be mangled + .suggestion = remove this attribute + +lint-builtin-const-no-mangle = const items should never be `#[no_mangle]` + .suggestion = try a static value + +lint-builtin-mutable-transmutes = + transmuting &T to &mut T is undefined behavior, even if the reference is unused, consider instead using an UnsafeCell + +lint-builtin-unstable-features = unstable feature + +lint-builtin-unreachable-pub = unreachable `pub` {$what} + .suggestion = consider restricting its visibility + .help = or consider exporting it for use by other crates + +lint-builtin-type-alias-bounds-help = use fully disambiguated paths (i.e., `<T as Trait>::Assoc`) to refer to associated types in type aliases + +lint-builtin-type-alias-where-clause = where clauses are not enforced in type aliases + .suggestion = the clause will not be checked when the type alias is used, and should be removed + +lint-builtin-type-alias-generic-bounds = bounds on generic parameters are not enforced in type aliases + .suggestion = the bound will not be checked when the type alias is used, and should be removed + +lint-builtin-trivial-bounds = {$predicate_kind_name} bound {$predicate} does not depend on any type or lifetime parameters + +lint-builtin-ellipsis-inclusive-range-patterns = `...` range patterns are deprecated + .suggestion = use `..=` for an inclusive range + +lint-builtin-unnameable-test-items = cannot test inner items + +lint-builtin-keyword-idents = `{$kw}` is a keyword in the {$next} edition + .suggestion = you can use a raw identifier to stay compatible + +lint-builtin-explicit-outlives = outlives requirements can be inferred + .suggestion = remove {$count -> + [one] this bound + *[other] these bounds + } + +lint-builtin-incomplete-features = the feature `{$name}` is incomplete and may not be safe to use and/or cause compiler crashes + .note = see issue #{$n} <https://github.com/rust-lang/rust/issues/{$n}> for more information + .help = consider using `min_{$name}` instead, which is more stable and complete + +lint-builtin-clashing-extern-same-name = `{$this_fi}` redeclared with a different signature + .previous-decl-label = `{$orig}` previously declared here + .mismatch-label = this signature doesn't match the previous declaration +lint-builtin-clashing-extern-diff-name = `{$this_fi}` redeclares `{$orig}` with a different signature + .previous-decl-label = `{$orig}` previously declared here + .mismatch-label = this signature doesn't match the previous declaration + +lint-builtin-deref-nullptr = dereferencing a null pointer + .label = this code causes undefined behavior when executed + +lint-builtin-asm-labels = avoid using named labels in inline assembly diff --git a/compiler/rustc_error_messages/src/lib.rs b/compiler/rustc_error_messages/src/lib.rs index d52b94b78df..563d0534d8f 100644 --- a/compiler/rustc_error_messages/src/lib.rs +++ b/compiler/rustc_error_messages/src/lib.rs @@ -31,11 +31,12 @@ pub use unic_langid::{langid, LanguageIdentifier}; // Generates `DEFAULT_LOCALE_RESOURCES` static and `fluent_generated` module. fluent_messages! { + borrowck => "../locales/en-US/borrowck.ftl", + builtin_macros => "../locales/en-US/builtin_macros.ftl", + lint => "../locales/en-US/lint.ftl", 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", - borrowck => "../locales/en-US/borrowck.ftl", } pub use fluent_generated::{self as fluent, DEFAULT_LOCALE_RESOURCES}; diff --git a/compiler/rustc_errors/src/diagnostic.rs b/compiler/rustc_errors/src/diagnostic.rs index b8545139cec..0d1d017d874 100644 --- a/compiler/rustc_errors/src/diagnostic.rs +++ b/compiler/rustc_errors/src/diagnostic.rs @@ -1,14 +1,14 @@ use crate::snippet::Style; use crate::{ - CodeSuggestion, DiagnosticMessage, Level, MultiSpan, SubdiagnosticMessage, Substitution, - SubstitutionPart, SuggestionStyle, + CodeSuggestion, DiagnosticMessage, EmissionGuarantee, Level, LintDiagnosticBuilder, MultiSpan, + SubdiagnosticMessage, Substitution, SubstitutionPart, SuggestionStyle, }; use rustc_data_structures::stable_map::FxHashMap; use rustc_error_messages::FluentValue; use rustc_lint_defs::{Applicability, LintExpectationId}; use rustc_span::edition::LATEST_STABLE_EDITION; use rustc_span::symbol::{Ident, Symbol}; -use rustc_span::{Span, DUMMY_SP}; +use rustc_span::{edition::Edition, Span, DUMMY_SP}; use std::borrow::Cow; use std::fmt; use std::hash::{Hash, Hasher}; @@ -39,12 +39,94 @@ pub trait IntoDiagnosticArg { fn into_diagnostic_arg(self) -> DiagnosticArgValue<'static>; } +impl IntoDiagnosticArg for bool { + fn into_diagnostic_arg(self) -> DiagnosticArgValue<'static> { + if self { + DiagnosticArgValue::Str(Cow::Borrowed("true")) + } else { + DiagnosticArgValue::Str(Cow::Borrowed("false")) + } + } +} + +impl IntoDiagnosticArg for i8 { + fn into_diagnostic_arg(self) -> DiagnosticArgValue<'static> { + DiagnosticArgValue::Str(Cow::Owned(self.to_string())) + } +} + +impl IntoDiagnosticArg for u8 { + fn into_diagnostic_arg(self) -> DiagnosticArgValue<'static> { + DiagnosticArgValue::Str(Cow::Owned(self.to_string())) + } +} + +impl IntoDiagnosticArg for i16 { + fn into_diagnostic_arg(self) -> DiagnosticArgValue<'static> { + DiagnosticArgValue::Str(Cow::Owned(self.to_string())) + } +} + +impl IntoDiagnosticArg for u16 { + fn into_diagnostic_arg(self) -> DiagnosticArgValue<'static> { + DiagnosticArgValue::Str(Cow::Owned(self.to_string())) + } +} + +impl IntoDiagnosticArg for i32 { + fn into_diagnostic_arg(self) -> DiagnosticArgValue<'static> { + DiagnosticArgValue::Str(Cow::Owned(self.to_string())) + } +} + +impl IntoDiagnosticArg for u32 { + fn into_diagnostic_arg(self) -> DiagnosticArgValue<'static> { + DiagnosticArgValue::Str(Cow::Owned(self.to_string())) + } +} + +impl IntoDiagnosticArg for i64 { + fn into_diagnostic_arg(self) -> DiagnosticArgValue<'static> { + DiagnosticArgValue::Str(Cow::Owned(self.to_string())) + } +} + +impl IntoDiagnosticArg for u64 { + fn into_diagnostic_arg(self) -> DiagnosticArgValue<'static> { + DiagnosticArgValue::Str(Cow::Owned(self.to_string())) + } +} + +impl IntoDiagnosticArg for i128 { + fn into_diagnostic_arg(self) -> DiagnosticArgValue<'static> { + DiagnosticArgValue::Str(Cow::Owned(self.to_string())) + } +} + +impl IntoDiagnosticArg for u128 { + fn into_diagnostic_arg(self) -> DiagnosticArgValue<'static> { + DiagnosticArgValue::Str(Cow::Owned(self.to_string())) + } +} + impl IntoDiagnosticArg for String { fn into_diagnostic_arg(self) -> DiagnosticArgValue<'static> { DiagnosticArgValue::Str(Cow::Owned(self)) } } +impl IntoDiagnosticArg for std::num::NonZeroU32 { + fn into_diagnostic_arg(self) -> DiagnosticArgValue<'static> { + DiagnosticArgValue::Str(Cow::Owned(self.to_string())) + } +} + +impl IntoDiagnosticArg for Edition { + fn into_diagnostic_arg(self) -> DiagnosticArgValue<'static> { + DiagnosticArgValue::Str(Cow::Owned(self.to_string())) + } +} + impl IntoDiagnosticArg for Symbol { fn into_diagnostic_arg(self) -> DiagnosticArgValue<'static> { self.to_ident_string().into_diagnostic_arg() @@ -86,6 +168,14 @@ pub trait AddSubdiagnostic { fn add_to_diagnostic(self, diag: &mut Diagnostic); } +/// Trait implemented by lint types. This should not be implemented manually. Instead, use +/// `#[derive(LintDiagnostic)]` -- see [rustc_macros::LintDiagnostic]. +#[rustc_diagnostic_item = "DecorateLint"] +pub trait DecorateLint<'a, G: EmissionGuarantee> { + /// Decorate and emit a lint. + fn decorate_lint(self, diag: LintDiagnosticBuilder<'a, G>); +} + #[must_use] #[derive(Clone, Debug, Encodable, Decodable)] pub struct Diagnostic { @@ -286,7 +376,7 @@ impl Diagnostic { /// /// This span is *not* considered a ["primary span"][`MultiSpan`]; only /// the `Span` supplied when creating the diagnostic is primary. - #[cfg_attr(not(bootstrap), rustc_lint_diagnostics)] + #[rustc_lint_diagnostics] pub fn span_label(&mut self, span: Span, label: impl Into<SubdiagnosticMessage>) -> &mut Self { self.span.push_span_label(span, self.subdiagnostic_message_to_diagnostic_message(label)); self @@ -405,7 +495,7 @@ impl Diagnostic { } /// Add a note attached to this diagnostic. - #[cfg_attr(not(bootstrap), rustc_lint_diagnostics)] + #[rustc_lint_diagnostics] pub fn note(&mut self, msg: impl Into<SubdiagnosticMessage>) -> &mut Self { self.sub(Level::Note, msg, MultiSpan::new(), None); self @@ -428,7 +518,7 @@ impl Diagnostic { /// Prints the span with a note above it. /// This is like [`Diagnostic::note()`], but it gets its own span. - #[cfg_attr(not(bootstrap), rustc_lint_diagnostics)] + #[rustc_lint_diagnostics] pub fn span_note<S: Into<MultiSpan>>( &mut self, sp: S, @@ -450,7 +540,7 @@ impl Diagnostic { } /// Add a warning attached to this diagnostic. - #[cfg_attr(not(bootstrap), rustc_lint_diagnostics)] + #[rustc_lint_diagnostics] pub fn warn(&mut self, msg: impl Into<SubdiagnosticMessage>) -> &mut Self { self.sub(Level::Warning(None), msg, MultiSpan::new(), None); self @@ -458,7 +548,7 @@ impl Diagnostic { /// Prints the span with a warning above it. /// This is like [`Diagnostic::warn()`], but it gets its own span. - #[cfg_attr(not(bootstrap), rustc_lint_diagnostics)] + #[rustc_lint_diagnostics] pub fn span_warn<S: Into<MultiSpan>>( &mut self, sp: S, @@ -469,7 +559,7 @@ impl Diagnostic { } /// Add a help message attached to this diagnostic. - #[cfg_attr(not(bootstrap), rustc_lint_diagnostics)] + #[rustc_lint_diagnostics] pub fn help(&mut self, msg: impl Into<SubdiagnosticMessage>) -> &mut Self { self.sub(Level::Help, msg, MultiSpan::new(), None); self @@ -483,7 +573,7 @@ impl Diagnostic { /// Prints the span with some help above it. /// This is like [`Diagnostic::help()`], but it gets its own span. - #[cfg_attr(not(bootstrap), rustc_lint_diagnostics)] + #[rustc_lint_diagnostics] pub fn span_help<S: Into<MultiSpan>>( &mut self, sp: S, diff --git a/compiler/rustc_errors/src/diagnostic_builder.rs b/compiler/rustc_errors/src/diagnostic_builder.rs index 9e0a99849a3..c3341fd68f4 100644 --- a/compiler/rustc_errors/src/diagnostic_builder.rs +++ b/compiler/rustc_errors/src/diagnostic_builder.rs @@ -529,7 +529,7 @@ impl<'a, G: EmissionGuarantee> DiagnosticBuilder<'a, G> { applicability: Applicability, ) -> &mut Self); - forward!(pub fn set_primary_message(&mut self, msg: impl Into<String>) -> &mut Self); + forward!(pub fn set_primary_message(&mut self, msg: impl Into<DiagnosticMessage>) -> &mut Self); forward!(pub fn set_span(&mut self, sp: impl Into<MultiSpan>) -> &mut Self); forward!(pub fn code(&mut self, s: DiagnosticId) -> &mut Self); forward!(pub fn set_arg( @@ -589,3 +589,26 @@ macro_rules! struct_span_err { macro_rules! error_code { ($code:ident) => {{ $crate::DiagnosticId::Error(stringify!($code).to_owned()) }}; } + +/// Wrapper around a `DiagnosticBuilder` for creating lints. +pub struct LintDiagnosticBuilder<'a, G: EmissionGuarantee>(DiagnosticBuilder<'a, G>); + +impl<'a, G: EmissionGuarantee> LintDiagnosticBuilder<'a, G> { + /// Return the inner `DiagnosticBuilder`, first setting the primary message to `msg`. + pub fn build(mut self, msg: impl Into<DiagnosticMessage>) -> DiagnosticBuilder<'a, G> { + self.0.set_primary_message(msg); + self.0.set_is_lint(); + self.0 + } + + /// Create a `LintDiagnosticBuilder` from some existing `DiagnosticBuilder`. + pub fn new(err: DiagnosticBuilder<'a, G>) -> LintDiagnosticBuilder<'a, G> { + LintDiagnosticBuilder(err) + } +} + +impl<'a> LintDiagnosticBuilder<'a, ErrorGuaranteed> { + pub fn forget_guarantee(self) -> LintDiagnosticBuilder<'a, ()> { + LintDiagnosticBuilder(self.0.forget_guarantee()) + } +} diff --git a/compiler/rustc_errors/src/lib.rs b/compiler/rustc_errors/src/lib.rs index 78b0892b3bc..ffe4ecebb2e 100644 --- a/compiler/rustc_errors/src/lib.rs +++ b/compiler/rustc_errors/src/lib.rs @@ -370,10 +370,10 @@ impl fmt::Display for ExplicitBug { impl error::Error for ExplicitBug {} pub use diagnostic::{ - AddSubdiagnostic, Diagnostic, DiagnosticArg, DiagnosticArgValue, DiagnosticId, + AddSubdiagnostic, DecorateLint, Diagnostic, DiagnosticArg, DiagnosticArgValue, DiagnosticId, DiagnosticStyledString, IntoDiagnosticArg, SubDiagnostic, }; -pub use diagnostic_builder::{DiagnosticBuilder, EmissionGuarantee}; +pub use diagnostic_builder::{DiagnosticBuilder, EmissionGuarantee, LintDiagnosticBuilder}; use std::backtrace::Backtrace; /// A handler deals with errors and other compiler output. @@ -649,7 +649,7 @@ impl Handler { /// Attempting to `.emit()` the builder will only emit if either: /// * `can_emit_warnings` is `true` /// * `is_force_warn` was set in `DiagnosticId::Lint` - #[cfg_attr(not(bootstrap), rustc_lint_diagnostics)] + #[rustc_lint_diagnostics] pub fn struct_span_warn( &self, span: impl Into<MultiSpan>, @@ -678,7 +678,7 @@ impl Handler { } /// Construct a builder at the `Allow` level at the given `span` and with the `msg`. - #[cfg_attr(not(bootstrap), rustc_lint_diagnostics)] + #[rustc_lint_diagnostics] pub fn struct_span_allow( &self, span: impl Into<MultiSpan>, @@ -691,7 +691,7 @@ impl Handler { /// Construct a builder at the `Warning` level at the given `span` and with the `msg`. /// Also include a code. - #[cfg_attr(not(bootstrap), rustc_lint_diagnostics)] + #[rustc_lint_diagnostics] pub fn struct_span_warn_with_code( &self, span: impl Into<MultiSpan>, @@ -708,7 +708,7 @@ impl Handler { /// Attempting to `.emit()` the builder will only emit if either: /// * `can_emit_warnings` is `true` /// * `is_force_warn` was set in `DiagnosticId::Lint` - #[cfg_attr(not(bootstrap), rustc_lint_diagnostics)] + #[rustc_lint_diagnostics] pub fn struct_warn(&self, msg: impl Into<DiagnosticMessage>) -> DiagnosticBuilder<'_, ()> { DiagnosticBuilder::new(self, Level::Warning(None), msg) } @@ -728,13 +728,13 @@ impl Handler { } /// Construct a builder at the `Allow` level with the `msg`. - #[cfg_attr(not(bootstrap), rustc_lint_diagnostics)] + #[rustc_lint_diagnostics] pub fn struct_allow(&self, msg: impl Into<DiagnosticMessage>) -> DiagnosticBuilder<'_, ()> { DiagnosticBuilder::new(self, Level::Allow, msg) } /// Construct a builder at the `Expect` level with the `msg`. - #[cfg_attr(not(bootstrap), rustc_lint_diagnostics)] + #[rustc_lint_diagnostics] pub fn struct_expect( &self, msg: impl Into<DiagnosticMessage>, @@ -744,7 +744,7 @@ impl Handler { } /// Construct a builder at the `Error` level at the given `span` and with the `msg`. - #[cfg_attr(not(bootstrap), rustc_lint_diagnostics)] + #[rustc_lint_diagnostics] pub fn struct_span_err( &self, span: impl Into<MultiSpan>, @@ -756,7 +756,7 @@ impl Handler { } /// Construct a builder at the `Error` level at the given `span`, with the `msg`, and `code`. - #[cfg_attr(not(bootstrap), rustc_lint_diagnostics)] + #[rustc_lint_diagnostics] pub fn struct_span_err_with_code( &self, span: impl Into<MultiSpan>, @@ -770,7 +770,7 @@ impl Handler { /// Construct a builder at the `Error` level with the `msg`. // FIXME: This method should be removed (every error should have an associated error code). - #[cfg_attr(not(bootstrap), rustc_lint_diagnostics)] + #[rustc_lint_diagnostics] pub fn struct_err( &self, msg: impl Into<DiagnosticMessage>, @@ -785,7 +785,7 @@ impl Handler { } /// Construct a builder at the `Error` level with the `msg` and the `code`. - #[cfg_attr(not(bootstrap), rustc_lint_diagnostics)] + #[rustc_lint_diagnostics] pub fn struct_err_with_code( &self, msg: impl Into<DiagnosticMessage>, @@ -797,7 +797,7 @@ impl Handler { } /// Construct a builder at the `Warn` level with the `msg` and the `code`. - #[cfg_attr(not(bootstrap), rustc_lint_diagnostics)] + #[rustc_lint_diagnostics] pub fn struct_warn_with_code( &self, msg: impl Into<DiagnosticMessage>, @@ -809,7 +809,7 @@ impl Handler { } /// Construct a builder at the `Fatal` level at the given `span` and with the `msg`. - #[cfg_attr(not(bootstrap), rustc_lint_diagnostics)] + #[rustc_lint_diagnostics] pub fn struct_span_fatal( &self, span: impl Into<MultiSpan>, @@ -821,7 +821,7 @@ impl Handler { } /// Construct a builder at the `Fatal` level at the given `span`, with the `msg`, and `code`. - #[cfg_attr(not(bootstrap), rustc_lint_diagnostics)] + #[rustc_lint_diagnostics] pub fn struct_span_fatal_with_code( &self, span: impl Into<MultiSpan>, @@ -834,19 +834,19 @@ impl Handler { } /// Construct a builder at the `Error` level with the `msg`. - #[cfg_attr(not(bootstrap), rustc_lint_diagnostics)] + #[rustc_lint_diagnostics] pub fn struct_fatal(&self, msg: impl Into<DiagnosticMessage>) -> DiagnosticBuilder<'_, !> { DiagnosticBuilder::new_fatal(self, msg) } /// Construct a builder at the `Help` level with the `msg`. - #[cfg_attr(not(bootstrap), rustc_lint_diagnostics)] + #[rustc_lint_diagnostics] pub fn struct_help(&self, msg: impl Into<DiagnosticMessage>) -> DiagnosticBuilder<'_, ()> { DiagnosticBuilder::new(self, Level::Help, msg) } /// Construct a builder at the `Note` level with the `msg`. - #[cfg_attr(not(bootstrap), rustc_lint_diagnostics)] + #[rustc_lint_diagnostics] pub fn struct_note_without_error( &self, msg: impl Into<DiagnosticMessage>, @@ -854,13 +854,13 @@ impl Handler { DiagnosticBuilder::new(self, Level::Note, msg) } - #[cfg_attr(not(bootstrap), rustc_lint_diagnostics)] + #[rustc_lint_diagnostics] pub fn span_fatal(&self, span: impl Into<MultiSpan>, msg: impl Into<DiagnosticMessage>) -> ! { self.emit_diag_at_span(Diagnostic::new(Fatal, msg), span); FatalError.raise() } - #[cfg_attr(not(bootstrap), rustc_lint_diagnostics)] + #[rustc_lint_diagnostics] pub fn span_fatal_with_code( &self, span: impl Into<MultiSpan>, @@ -871,7 +871,7 @@ impl Handler { FatalError.raise() } - #[cfg_attr(not(bootstrap), rustc_lint_diagnostics)] + #[rustc_lint_diagnostics] pub fn span_err( &self, span: impl Into<MultiSpan>, @@ -880,7 +880,7 @@ impl Handler { self.emit_diag_at_span(Diagnostic::new(Error { lint: false }, msg), span).unwrap() } - #[cfg_attr(not(bootstrap), rustc_lint_diagnostics)] + #[rustc_lint_diagnostics] pub fn span_err_with_code( &self, span: impl Into<MultiSpan>, @@ -893,12 +893,12 @@ impl Handler { ); } - #[cfg_attr(not(bootstrap), rustc_lint_diagnostics)] + #[rustc_lint_diagnostics] pub fn span_warn(&self, span: impl Into<MultiSpan>, msg: impl Into<DiagnosticMessage>) { self.emit_diag_at_span(Diagnostic::new(Warning(None), msg), span); } - #[cfg_attr(not(bootstrap), rustc_lint_diagnostics)] + #[rustc_lint_diagnostics] pub fn span_warn_with_code( &self, span: impl Into<MultiSpan>, @@ -1447,7 +1447,7 @@ impl HandlerInner { self.flags.treat_err_as_bug.map(|c| c.get()).unwrap_or(0), ) { (1, 1) => panic!("aborting due to `-Z treat-err-as-bug=1`"), - (0, _) | (1, _) => {} + (0 | 1, _) => {} (count, as_bug) => panic!( "aborting after {} errors due to `-Z treat-err-as-bug={}`", count, as_bug, diff --git a/compiler/rustc_expand/src/base.rs b/compiler/rustc_expand/src/base.rs index 1e57d66dd9f..bfe2d773788 100644 --- a/compiler/rustc_expand/src/base.rs +++ b/compiler/rustc_expand/src/base.rs @@ -1077,7 +1077,7 @@ impl<'a> ExtCtxt<'a> { self.current_expansion.id.expansion_cause() } - #[cfg_attr(not(bootstrap), rustc_lint_diagnostics)] + #[rustc_lint_diagnostics] pub fn struct_span_err<S: Into<MultiSpan>>( &self, sp: S, @@ -1102,11 +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)] + #[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)] + #[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/build.rs b/compiler/rustc_expand/src/build.rs index 1694a8865dd..74e9bbeeeaf 100644 --- a/compiler/rustc_expand/src/build.rs +++ b/compiler/rustc_expand/src/build.rs @@ -152,6 +152,19 @@ impl<'a> ExtCtxt<'a> { ast::Stmt { id: ast::DUMMY_NODE_ID, span: expr.span, kind: ast::StmtKind::Expr(expr) } } + pub fn stmt_let_pat(&self, sp: Span, pat: P<ast::Pat>, ex: P<ast::Expr>) -> ast::Stmt { + let local = P(ast::Local { + pat, + ty: None, + id: ast::DUMMY_NODE_ID, + kind: LocalKind::Init(ex), + span: sp, + attrs: AttrVec::new(), + tokens: None, + }); + self.stmt_local(local, sp) + } + pub fn stmt_let(&self, sp: Span, mutbl: bool, ident: Ident, ex: P<ast::Expr>) -> ast::Stmt { self.stmt_let_ty(sp, mutbl, ident, None, ex) } diff --git a/compiler/rustc_hir/src/hir.rs b/compiler/rustc_hir/src/hir.rs index a7fc59255d7..a2ef158ce8d 100644 --- a/compiler/rustc_hir/src/hir.rs +++ b/compiler/rustc_hir/src/hir.rs @@ -3326,7 +3326,6 @@ pub enum Node<'hir> { Ty(&'hir Ty<'hir>), TypeBinding(&'hir TypeBinding<'hir>), TraitRef(&'hir TraitRef<'hir>), - Binding(&'hir Pat<'hir>), Pat(&'hir Pat<'hir>), Arm(&'hir Arm<'hir>), Block(&'hir Block<'hir>), @@ -3378,7 +3377,6 @@ impl<'hir> Node<'hir> { | Node::Block(..) | Node::Ctor(..) | Node::Pat(..) - | Node::Binding(..) | Node::Arm(..) | Node::Local(..) | Node::Crate(..) diff --git a/compiler/rustc_hir_pretty/src/lib.rs b/compiler/rustc_hir_pretty/src/lib.rs index 7bf91df9f76..50acb0270b0 100644 --- a/compiler/rustc_hir_pretty/src/lib.rs +++ b/compiler/rustc_hir_pretty/src/lib.rs @@ -59,7 +59,7 @@ impl PpAnn for &dyn rustc_hir::intravisit::Map<'_> { Nested::ImplItem(id) => state.print_impl_item(self.impl_item(id)), Nested::ForeignItem(id) => state.print_foreign_item(self.foreign_item(id)), Nested::Body(id) => state.print_expr(&self.body(id).value), - Nested::BodyParamPat(id, i) => state.print_pat(&self.body(id).params[i].pat), + Nested::BodyParamPat(id, i) => state.print_pat(self.body(id).params[i].pat), } } } @@ -74,37 +74,37 @@ pub struct State<'a> { impl<'a> State<'a> { pub fn print_node(&mut self, node: Node<'_>) { match node { - Node::Param(a) => self.print_param(&a), - Node::Item(a) => self.print_item(&a), - Node::ForeignItem(a) => self.print_foreign_item(&a), + Node::Param(a) => self.print_param(a), + Node::Item(a) => self.print_item(a), + Node::ForeignItem(a) => self.print_foreign_item(a), Node::TraitItem(a) => self.print_trait_item(a), Node::ImplItem(a) => self.print_impl_item(a), - Node::Variant(a) => self.print_variant(&a), - Node::AnonConst(a) => self.print_anon_const(&a), - Node::Expr(a) => self.print_expr(&a), - Node::Stmt(a) => self.print_stmt(&a), - Node::PathSegment(a) => self.print_path_segment(&a), - Node::Ty(a) => self.print_type(&a), - Node::TypeBinding(a) => self.print_type_binding(&a), - Node::TraitRef(a) => self.print_trait_ref(&a), - Node::Binding(a) | Node::Pat(a) => self.print_pat(&a), - Node::Arm(a) => self.print_arm(&a), + Node::Variant(a) => self.print_variant(a), + Node::AnonConst(a) => self.print_anon_const(a), + Node::Expr(a) => self.print_expr(a), + Node::Stmt(a) => self.print_stmt(a), + Node::PathSegment(a) => self.print_path_segment(a), + Node::Ty(a) => self.print_type(a), + Node::TypeBinding(a) => self.print_type_binding(a), + Node::TraitRef(a) => self.print_trait_ref(a), + Node::Pat(a) => self.print_pat(a), + Node::Arm(a) => self.print_arm(a), Node::Infer(_) => self.word("_"), Node::Block(a) => { // Containing cbox, will be closed by print-block at `}`. self.cbox(INDENT_UNIT); // Head-ibox, will be closed by print-block after `{`. self.ibox(0); - self.print_block(&a) + self.print_block(a); } - Node::Lifetime(a) => self.print_lifetime(&a), + Node::Lifetime(a) => self.print_lifetime(a), Node::GenericParam(_) => panic!("cannot print Node::GenericParam"), Node::Field(_) => panic!("cannot print Node::Field"), // These cases do not carry enough information in the // `hir_map` to reconstruct their full structure for pretty // printing. Node::Ctor(..) => panic!("cannot print isolated Ctor"), - Node::Local(a) => self.print_local_decl(&a), + Node::Local(a) => self.print_local_decl(a), Node::Crate(..) => panic!("cannot print Crate"), } } @@ -266,7 +266,7 @@ impl<'a> State<'a> { } pub fn commasep_exprs(&mut self, b: Breaks, exprs: &[hir::Expr<'_>]) { - self.commasep_cmnt(b, exprs, |s, e| s.print_expr(&e), |e| e.span) + self.commasep_cmnt(b, exprs, |s, e| s.print_expr(e), |e| e.span); } pub fn print_mod(&mut self, _mod: &hir::Mod<'_>, attrs: &[ast::Attribute]) { @@ -287,9 +287,9 @@ impl<'a> State<'a> { self.maybe_print_comment(ty.span.lo()); self.ibox(0); match ty.kind { - hir::TyKind::Slice(ref ty) => { + hir::TyKind::Slice(ty) => { self.word("["); - self.print_type(&ty); + self.print_type(ty); self.word("]"); } hir::TyKind::Ptr(ref mt) => { @@ -304,23 +304,16 @@ impl<'a> State<'a> { hir::TyKind::Never => { self.word("!"); } - hir::TyKind::Tup(ref elts) => { + hir::TyKind::Tup(elts) => { self.popen(); - self.commasep(Inconsistent, &elts, |s, ty| s.print_type(&ty)); + self.commasep(Inconsistent, elts, |s, ty| s.print_type(ty)); if elts.len() == 1 { self.word(","); } self.pclose(); } - hir::TyKind::BareFn(ref f) => { - self.print_ty_fn( - f.abi, - f.unsafety, - &f.decl, - None, - &f.generic_params, - f.param_names, - ); + hir::TyKind::BareFn(f) => { + self.print_ty_fn(f.abi, f.unsafety, f.decl, None, f.generic_params, f.param_names); } hir::TyKind::OpaqueDef(..) => self.word("/*impl Trait*/"), hir::TyKind::Path(ref qpath) => self.print_qpath(qpath, false), @@ -344,9 +337,9 @@ impl<'a> State<'a> { self.print_lifetime(lifetime); } } - hir::TyKind::Array(ref ty, ref length) => { + hir::TyKind::Array(ty, ref length) => { self.word("["); - self.print_type(&ty); + self.print_type(ty); self.word("; "); self.print_array_length(length); self.word("]"); @@ -373,7 +366,7 @@ impl<'a> State<'a> { self.maybe_print_comment(item.span.lo()); self.print_outer_attributes(self.attrs(item.hir_id())); match item.kind { - hir::ForeignItemKind::Fn(ref decl, ref arg_names, ref generics) => { + hir::ForeignItemKind::Fn(decl, arg_names, generics) => { self.head(""); self.print_fn( decl, @@ -392,14 +385,14 @@ impl<'a> State<'a> { self.word(";"); self.end() // end the outer fn box } - hir::ForeignItemKind::Static(ref t, m) => { + hir::ForeignItemKind::Static(t, m) => { self.head("static"); if m == hir::Mutability::Mut { self.word_space("mut"); } self.print_ident(item.ident); self.word_space(":"); - self.print_type(&t); + self.print_type(t); self.word(";"); self.end(); // end the head-ibox self.end() // end the outer cbox @@ -442,7 +435,7 @@ impl<'a> State<'a> { ) { self.word_space("type"); self.print_ident(ident); - self.print_generic_params(&generics.params); + self.print_generic_params(generics.params); if let Some(bounds) = bounds { self.print_bounds(":", bounds); } @@ -463,7 +456,7 @@ impl<'a> State<'a> { ) { self.head("type"); self.print_ident(item.ident); - self.print_generic_params(&generics.params); + self.print_generic_params(generics.params); self.end(); // end the inner ibox self.print_where_clause(generics); @@ -494,7 +487,7 @@ impl<'a> State<'a> { self.end(); // end inner head-block self.end(); // end outer head-block } - hir::ItemKind::Use(ref path, kind) => { + hir::ItemKind::Use(path, kind) => { self.head("use"); self.print_path(path, false); @@ -513,14 +506,14 @@ impl<'a> State<'a> { self.end(); // end inner head-block self.end(); // end outer head-block } - hir::ItemKind::Static(ref ty, m, expr) => { + hir::ItemKind::Static(ty, m, expr) => { self.head("static"); if m == hir::Mutability::Mut { self.word_space("mut"); } self.print_ident(item.ident); self.word_space(":"); - self.print_type(&ty); + self.print_type(ty); self.space(); self.end(); // end the head-ibox @@ -529,11 +522,11 @@ impl<'a> State<'a> { self.word(";"); self.end(); // end the outer cbox } - hir::ItemKind::Const(ref ty, expr) => { + hir::ItemKind::Const(ty, expr) => { self.head("const"); self.print_ident(item.ident); self.word_space(":"); - self.print_type(&ty); + self.print_type(ty); self.space(); self.end(); // end the head-ibox @@ -542,10 +535,10 @@ impl<'a> State<'a> { self.word(";"); self.end(); // end the outer cbox } - hir::ItemKind::Fn(ref sig, ref param_names, body) => { + hir::ItemKind::Fn(ref sig, param_names, body) => { self.head(""); self.print_fn( - &sig.decl, + sig.decl, sig.header, Some(item.ident.name), param_names, @@ -578,22 +571,22 @@ impl<'a> State<'a> { } self.bclose(item.span); } - hir::ItemKind::GlobalAsm(ref asm) => { + hir::ItemKind::GlobalAsm(asm) => { self.head("global_asm!"); self.print_inline_asm(asm); self.end() } - hir::ItemKind::TyAlias(ref ty, ref generics) => { - self.print_item_type(item, &generics, |state| { + hir::ItemKind::TyAlias(ty, generics) => { + self.print_item_type(item, generics, |state| { state.word_space("="); - state.print_type(&ty); + state.print_type(ty); }); } hir::ItemKind::OpaqueTy(ref opaque_ty) => { - self.print_item_type(item, &opaque_ty.generics, |state| { + self.print_item_type(item, opaque_ty.generics, |state| { let mut real_bounds = Vec::with_capacity(opaque_ty.bounds.len()); - for b in opaque_ty.bounds.iter() { - if let GenericBound::Trait(ref ptr, hir::TraitBoundModifier::Maybe) = *b { + for b in opaque_ty.bounds { + if let GenericBound::Trait(ptr, hir::TraitBoundModifier::Maybe) = b { state.space(); state.word_space("for ?"); state.print_trait_ref(&ptr.trait_ref); @@ -604,39 +597,39 @@ impl<'a> State<'a> { state.print_bounds("= impl", real_bounds); }); } - hir::ItemKind::Enum(ref enum_definition, ref params) => { + hir::ItemKind::Enum(ref enum_definition, params) => { self.print_enum_def(enum_definition, params, item.ident.name, item.span); } - hir::ItemKind::Struct(ref struct_def, ref generics) => { + hir::ItemKind::Struct(ref struct_def, generics) => { self.head("struct"); self.print_struct(struct_def, generics, item.ident.name, item.span, true); } - hir::ItemKind::Union(ref struct_def, ref generics) => { + hir::ItemKind::Union(ref struct_def, generics) => { self.head("union"); self.print_struct(struct_def, generics, item.ident.name, item.span, true); } - hir::ItemKind::Impl(hir::Impl { + hir::ItemKind::Impl(&hir::Impl { unsafety, polarity, defaultness, constness, defaultness_span: _, - ref generics, + generics, ref of_trait, - ref self_ty, + self_ty, items, }) => { self.head(""); - self.print_defaultness(*defaultness); - self.print_unsafety(*unsafety); + self.print_defaultness(defaultness); + self.print_unsafety(unsafety); self.word_nbsp("impl"); if !generics.params.is_empty() { - self.print_generic_params(&generics.params); + self.print_generic_params(generics.params); self.space(); } - if *constness == hir::Constness::Const { + if constness == hir::Constness::Const { self.word_nbsp("const"); } @@ -644,33 +637,33 @@ impl<'a> State<'a> { self.word("!"); } - if let Some(ref t) = of_trait { + if let Some(t) = of_trait { self.print_trait_ref(t); self.space(); self.word_space("for"); } - self.print_type(&self_ty); + self.print_type(self_ty); self.print_where_clause(generics); self.space(); self.bopen(); self.print_inner_attributes(attrs); - for impl_item in *items { + for impl_item in items { self.ann.nested(self, Nested::ImplItem(impl_item.id)); } self.bclose(item.span); } - hir::ItemKind::Trait(is_auto, unsafety, ref generics, ref bounds, trait_items) => { + hir::ItemKind::Trait(is_auto, unsafety, generics, bounds, trait_items) => { self.head(""); self.print_is_auto(is_auto); self.print_unsafety(unsafety); self.word_nbsp("trait"); self.print_ident(item.ident); - self.print_generic_params(&generics.params); + self.print_generic_params(generics.params); let mut real_bounds = Vec::with_capacity(bounds.len()); - for b in bounds.iter() { - if let GenericBound::Trait(ref ptr, hir::TraitBoundModifier::Maybe) = *b { + for b in bounds { + if let GenericBound::Trait(ptr, hir::TraitBoundModifier::Maybe) = b { self.space(); self.word_space("for ?"); self.print_trait_ref(&ptr.trait_ref); @@ -687,14 +680,14 @@ impl<'a> State<'a> { } self.bclose(item.span); } - hir::ItemKind::TraitAlias(ref generics, ref bounds) => { + hir::ItemKind::TraitAlias(generics, bounds) => { self.head("trait"); self.print_ident(item.ident); - self.print_generic_params(&generics.params); + self.print_generic_params(generics.params); let mut real_bounds = Vec::with_capacity(bounds.len()); // FIXME(durka) this seems to be some quite outdated syntax - for b in bounds.iter() { - if let GenericBound::Trait(ref ptr, hir::TraitBoundModifier::Maybe) = *b { + for b in bounds { + if let GenericBound::Trait(ptr, hir::TraitBoundModifier::Maybe) = b { self.space(); self.word_space("for ?"); self.print_trait_ref(&ptr.trait_ref); @@ -714,7 +707,7 @@ impl<'a> State<'a> { } pub fn print_trait_ref(&mut self, t: &hir::TraitRef<'_>) { - self.print_path(&t.path, false) + self.print_path(t.path, false); } fn print_formal_generic_params(&mut self, generic_params: &[hir::GenericParam<'_>]) { @@ -726,8 +719,8 @@ impl<'a> State<'a> { } fn print_poly_trait_ref(&mut self, t: &hir::PolyTraitRef<'_>) { - self.print_formal_generic_params(&t.bound_generic_params); - self.print_trait_ref(&t.trait_ref) + self.print_formal_generic_params(t.bound_generic_params); + self.print_trait_ref(&t.trait_ref); } pub fn print_enum_def( @@ -739,10 +732,10 @@ impl<'a> State<'a> { ) { self.head("enum"); self.print_name(name); - self.print_generic_params(&generics.params); + self.print_generic_params(generics.params); self.print_where_clause(generics); self.space(); - self.print_variants(&enum_definition.variants, span) + self.print_variants(enum_definition.variants, span); } pub fn print_variants(&mut self, variants: &[hir::Variant<'_>], span: rustc_span::Span) { @@ -776,7 +769,7 @@ impl<'a> State<'a> { print_finalizer: bool, ) { self.print_name(name); - self.print_generic_params(&generics.params); + self.print_generic_params(generics.params); match struct_def { hir::VariantData::Tuple(..) | hir::VariantData::Unit(..) => { if let hir::VariantData::Tuple(..) = struct_def { @@ -784,7 +777,7 @@ impl<'a> State<'a> { self.commasep(Inconsistent, struct_def.fields(), |s, field| { s.maybe_print_comment(field.span.lo()); s.print_outer_attributes(s.attrs(field.hir_id)); - s.print_type(&field.ty) + s.print_type(field.ty); }); self.pclose(); } @@ -807,7 +800,7 @@ impl<'a> State<'a> { self.print_outer_attributes(self.attrs(field.hir_id)); self.print_ident(field.ident); self.word_nbsp(":"); - self.print_type(&field.ty); + self.print_type(field.ty); self.word(","); } @@ -819,7 +812,7 @@ impl<'a> State<'a> { pub fn print_variant(&mut self, v: &hir::Variant<'_>) { self.head(""); let generics = hir::Generics::empty(); - self.print_struct(&v.data, &generics, v.ident.name, v.span, false); + self.print_struct(&v.data, generics, v.ident.name, v.span, false); if let Some(ref d) = v.disr_expr { self.space(); self.word_space("="); @@ -834,7 +827,7 @@ impl<'a> State<'a> { arg_names: &[Ident], body_id: Option<hir::BodyId>, ) { - self.print_fn(&m.decl, m.header, Some(ident.name), generics, arg_names, body_id) + self.print_fn(m.decl, m.header, Some(ident.name), generics, arg_names, body_id); } pub fn print_trait_item(&mut self, ti: &hir::TraitItem<'_>) { @@ -843,28 +836,23 @@ impl<'a> State<'a> { self.maybe_print_comment(ti.span.lo()); self.print_outer_attributes(self.attrs(ti.hir_id())); match ti.kind { - hir::TraitItemKind::Const(ref ty, default) => { - self.print_associated_const(ti.ident, &ty, default); + hir::TraitItemKind::Const(ty, default) => { + self.print_associated_const(ti.ident, ty, default); } - hir::TraitItemKind::Fn(ref sig, hir::TraitFn::Required(ref arg_names)) => { - self.print_method_sig(ti.ident, sig, &ti.generics, arg_names, None); + hir::TraitItemKind::Fn(ref sig, hir::TraitFn::Required(arg_names)) => { + self.print_method_sig(ti.ident, sig, ti.generics, arg_names, None); self.word(";"); } hir::TraitItemKind::Fn(ref sig, hir::TraitFn::Provided(body)) => { self.head(""); - self.print_method_sig(ti.ident, sig, &ti.generics, &[], Some(body)); + self.print_method_sig(ti.ident, sig, ti.generics, &[], Some(body)); self.nbsp(); self.end(); // need to close a box self.end(); // need to close a box self.ann.nested(self, Nested::Body(body)); } - hir::TraitItemKind::Type(ref bounds, ref default) => { - self.print_associated_type( - ti.ident, - &ti.generics, - Some(bounds), - default.as_ref().map(|ty| &**ty), - ); + hir::TraitItemKind::Type(bounds, default) => { + self.print_associated_type(ti.ident, ti.generics, Some(bounds), default); } } self.ann.post(self, AnnNode::SubItem(ti.hir_id())) @@ -877,19 +865,19 @@ impl<'a> State<'a> { self.print_outer_attributes(self.attrs(ii.hir_id())); match ii.kind { - hir::ImplItemKind::Const(ref ty, expr) => { - self.print_associated_const(ii.ident, &ty, Some(expr)); + hir::ImplItemKind::Const(ty, expr) => { + self.print_associated_const(ii.ident, ty, Some(expr)); } hir::ImplItemKind::Fn(ref sig, body) => { self.head(""); - self.print_method_sig(ii.ident, sig, &ii.generics, &[], Some(body)); + self.print_method_sig(ii.ident, sig, ii.generics, &[], Some(body)); self.nbsp(); self.end(); // need to close a box self.end(); // need to close a box self.ann.nested(self, Nested::Body(body)); } - hir::ImplItemKind::TyAlias(ref ty) => { - self.print_associated_type(ii.ident, &ii.generics, None, Some(ty)); + hir::ImplItemKind::TyAlias(ty) => { + self.print_associated_type(ii.ident, ii.generics, None, Some(ty)); } } self.ann.post(self, AnnNode::SubItem(ii.hir_id())) @@ -904,10 +892,10 @@ impl<'a> State<'a> { decl(self); self.end(); - if let Some(ref init) = init { + if let Some(init) = init { self.nbsp(); self.word_space("="); - self.print_expr(&init); + self.print_expr(init); } self.end() } @@ -915,17 +903,17 @@ impl<'a> State<'a> { pub fn print_stmt(&mut self, st: &hir::Stmt<'_>) { self.maybe_print_comment(st.span.lo()); match st.kind { - hir::StmtKind::Local(ref loc) => { - self.print_local(loc.init, |this| this.print_local_decl(&loc)); + hir::StmtKind::Local(loc) => { + self.print_local(loc.init, |this| this.print_local_decl(loc)); } hir::StmtKind::Item(item) => self.ann.nested(self, Nested::Item(item)), - hir::StmtKind::Expr(ref expr) => { + hir::StmtKind::Expr(expr) => { self.space_if_not_bol(); - self.print_expr(&expr); + self.print_expr(expr); } - hir::StmtKind::Semi(ref expr) => { + hir::StmtKind::Semi(expr) => { self.space_if_not_bol(); - self.print_expr(&expr); + self.print_expr(expr); self.word(";"); } } @@ -966,9 +954,9 @@ impl<'a> State<'a> { for st in blk.stmts { self.print_stmt(st); } - if let Some(ref expr) = blk.expr { + if let Some(expr) = blk.expr { self.space_if_not_bol(); - self.print_expr(&expr); + self.print_expr(expr); self.maybe_print_trailing_comment(expr.span, Some(blk.span.hi())); } self.bclose_maybe_open(blk.span, close_box); @@ -979,21 +967,21 @@ impl<'a> State<'a> { if let Some(els_inner) = els { match els_inner.kind { // Another `else if` block. - hir::ExprKind::If(ref i, ref then, ref e) => { + hir::ExprKind::If(i, then, e) => { self.cbox(INDENT_UNIT - 1); self.ibox(0); self.word(" else if "); - self.print_expr_as_cond(&i); + self.print_expr_as_cond(i); self.space(); - self.print_expr(&then); - self.print_else(e.as_ref().map(|e| &**e)) + self.print_expr(then); + self.print_else(e); } // Final `else` block. - hir::ExprKind::Block(ref b, _) => { + hir::ExprKind::Block(b, _) => { self.cbox(INDENT_UNIT - 1); self.ibox(0); self.word(" else "); - self.print_block(&b) + self.print_block(b); } // Constraints would be great here! _ => { @@ -1048,7 +1036,7 @@ impl<'a> State<'a> { if needs_par { self.popen(); } - if let hir::ExprKind::DropTemps(ref actual_expr) = expr.kind { + if let hir::ExprKind::DropTemps(actual_expr) = expr.kind { self.print_expr(actual_expr); } else { self.print_expr(expr); @@ -1114,7 +1102,7 @@ impl<'a> State<'a> { &mut self, qpath: &hir::QPath<'_>, fields: &[hir::ExprField<'_>], - wth: &Option<&hir::Expr<'_>>, + wth: Option<&hir::Expr<'_>>, ) { self.print_qpath(qpath, true); self.word("{"); @@ -1127,28 +1115,24 @@ impl<'a> State<'a> { s.print_ident(field.ident); s.word_space(":"); } - s.print_expr(&field.expr); + s.print_expr(field.expr); s.end() }, |f| f.span, ); - match *wth { - Some(ref expr) => { - self.ibox(INDENT_UNIT); - if !fields.is_empty() { - self.word(","); - self.space(); - } - self.word(".."); - self.print_expr(&expr); - self.end(); - } - _ => { - if !fields.is_empty() { - self.word(",") - } + if let Some(expr) = wth { + self.ibox(INDENT_UNIT); + if !fields.is_empty() { + self.word(","); + self.space(); } + self.word(".."); + self.print_expr(expr); + self.end(); + } else if !fields.is_empty() { + self.word(","); } + self.word("}"); } @@ -1249,18 +1233,17 @@ impl<'a> State<'a> { Options(ast::InlineAsmOptions), } - let mut args = - vec![AsmArg::Template(ast::InlineAsmTemplatePiece::to_string(&asm.template))]; + let mut args = vec![AsmArg::Template(ast::InlineAsmTemplatePiece::to_string(asm.template))]; args.extend(asm.operands.iter().map(|(o, _)| AsmArg::Operand(o))); if !asm.options.is_empty() { args.push(AsmArg::Options(asm.options)); } self.popen(); - self.commasep(Consistent, &args, |s, arg| match arg { - AsmArg::Template(template) => s.print_string(&template, ast::StrStyle::Cooked), - AsmArg::Operand(op) => match op { - hir::InlineAsmOperand::In { reg, expr } => { + self.commasep(Consistent, &args, |s, arg| match *arg { + AsmArg::Template(ref template) => s.print_string(template, ast::StrStyle::Cooked), + AsmArg::Operand(op) => match *op { + hir::InlineAsmOperand::In { reg, ref expr } => { s.word("in"); s.popen(); s.word(format!("{}", reg)); @@ -1268,8 +1251,8 @@ impl<'a> State<'a> { s.space(); s.print_expr(expr); } - hir::InlineAsmOperand::Out { reg, late, expr } => { - s.word(if *late { "lateout" } else { "out" }); + hir::InlineAsmOperand::Out { reg, late, ref expr } => { + s.word(if late { "lateout" } else { "out" }); s.popen(); s.word(format!("{}", reg)); s.pclose(); @@ -1279,16 +1262,16 @@ impl<'a> State<'a> { None => s.word("_"), } } - hir::InlineAsmOperand::InOut { reg, late, expr } => { - s.word(if *late { "inlateout" } else { "inout" }); + hir::InlineAsmOperand::InOut { reg, late, ref expr } => { + s.word(if late { "inlateout" } else { "inout" }); s.popen(); s.word(format!("{}", reg)); s.pclose(); s.space(); s.print_expr(expr); } - hir::InlineAsmOperand::SplitInOut { reg, late, in_expr, out_expr } => { - s.word(if *late { "inlateout" } else { "inout" }); + hir::InlineAsmOperand::SplitInOut { reg, late, ref in_expr, ref out_expr } => { + s.word(if late { "inlateout" } else { "inout" }); s.popen(); s.word(format!("{}", reg)); s.pclose(); @@ -1301,17 +1284,17 @@ impl<'a> State<'a> { None => s.word("_"), } } - hir::InlineAsmOperand::Const { anon_const } => { + hir::InlineAsmOperand::Const { ref anon_const } => { s.word("const"); s.space(); s.print_anon_const(anon_const); } - hir::InlineAsmOperand::SymFn { anon_const } => { + hir::InlineAsmOperand::SymFn { ref anon_const } => { s.word("sym_fn"); s.space(); s.print_anon_const(anon_const); } - hir::InlineAsmOperand::SymStatic { path, def_id: _ } => { + hir::InlineAsmOperand::SymStatic { ref path, def_id: _ } => { s.word("sym_static"); s.space(); s.print_qpath(path, true); @@ -1363,57 +1346,57 @@ impl<'a> State<'a> { self.ibox(INDENT_UNIT); self.ann.pre(self, AnnNode::Expr(expr)); match expr.kind { - hir::ExprKind::Box(ref expr) => { + hir::ExprKind::Box(expr) => { self.word_space("box"); self.print_expr_maybe_paren(expr, parser::PREC_PREFIX); } - hir::ExprKind::Array(ref exprs) => { + hir::ExprKind::Array(exprs) => { self.print_expr_vec(exprs); } hir::ExprKind::ConstBlock(ref anon_const) => { self.print_expr_anon_const(anon_const); } - hir::ExprKind::Repeat(ref element, ref count) => { - self.print_expr_repeat(&element, count); + hir::ExprKind::Repeat(element, ref count) => { + self.print_expr_repeat(element, count); } - hir::ExprKind::Struct(ref qpath, fields, ref wth) => { + hir::ExprKind::Struct(qpath, fields, wth) => { self.print_expr_struct(qpath, fields, wth); } - hir::ExprKind::Tup(ref exprs) => { + hir::ExprKind::Tup(exprs) => { self.print_expr_tup(exprs); } - hir::ExprKind::Call(ref func, ref args) => { - self.print_expr_call(&func, args); + hir::ExprKind::Call(func, args) => { + self.print_expr_call(func, args); } - hir::ExprKind::MethodCall(ref segment, ref args, _) => { + hir::ExprKind::MethodCall(segment, args, _) => { self.print_expr_method_call(segment, args); } - hir::ExprKind::Binary(op, ref lhs, ref rhs) => { - self.print_expr_binary(op, &lhs, &rhs); + hir::ExprKind::Binary(op, lhs, rhs) => { + self.print_expr_binary(op, lhs, rhs); } - hir::ExprKind::Unary(op, ref expr) => { - self.print_expr_unary(op, &expr); + hir::ExprKind::Unary(op, expr) => { + self.print_expr_unary(op, expr); } - hir::ExprKind::AddrOf(k, m, ref expr) => { - self.print_expr_addr_of(k, m, &expr); + hir::ExprKind::AddrOf(k, m, expr) => { + self.print_expr_addr_of(k, m, expr); } hir::ExprKind::Lit(ref lit) => { - self.print_literal(&lit); + self.print_literal(lit); } - hir::ExprKind::Cast(ref expr, ref ty) => { + hir::ExprKind::Cast(expr, ty) => { let prec = AssocOp::As.precedence() as i8; - self.print_expr_maybe_paren(&expr, prec); + self.print_expr_maybe_paren(expr, prec); self.space(); self.word_space("as"); - self.print_type(&ty); + self.print_type(ty); } - hir::ExprKind::Type(ref expr, ref ty) => { + hir::ExprKind::Type(expr, ty) => { let prec = AssocOp::Colon.precedence() as i8; - self.print_expr_maybe_paren(&expr, prec); + self.print_expr_maybe_paren(expr, prec); self.word_space(":"); - self.print_type(&ty); + self.print_type(ty); } - hir::ExprKind::DropTemps(ref init) => { + hir::ExprKind::DropTemps(init) => { // Print `{`: self.cbox(INDENT_UNIT); self.ibox(0); @@ -1431,25 +1414,25 @@ impl<'a> State<'a> { // Print `}`: self.bclose_maybe_open(expr.span, true); } - hir::ExprKind::Let(hir::Let { pat, ty, init, .. }) => { - self.print_let(pat, *ty, init); + hir::ExprKind::Let(&hir::Let { pat, ty, init, .. }) => { + self.print_let(pat, ty, init); } - hir::ExprKind::If(ref test, ref blk, ref elseopt) => { - self.print_if(&test, &blk, elseopt.as_ref().map(|e| &**e)); + hir::ExprKind::If(test, blk, elseopt) => { + self.print_if(test, blk, elseopt); } - hir::ExprKind::Loop(ref blk, opt_label, _, _) => { + hir::ExprKind::Loop(blk, opt_label, _, _) => { if let Some(label) = opt_label { self.print_ident(label.ident); self.word_space(":"); } self.head("loop"); - self.print_block(&blk); + self.print_block(blk); } - hir::ExprKind::Match(ref expr, arms, _) => { + hir::ExprKind::Match(expr, arms, _) => { self.cbox(INDENT_UNIT); self.ibox(INDENT_UNIT); self.word_nbsp("match"); - self.print_expr_as_cond(&expr); + self.print_expr_as_cond(expr); self.space(); self.bopen(); for arm in arms { @@ -1460,7 +1443,7 @@ impl<'a> State<'a> { hir::ExprKind::Closure { capture_clause, bound_generic_params, - ref fn_decl, + fn_decl, body, fn_decl_span: _, movability: _, @@ -1468,7 +1451,7 @@ impl<'a> State<'a> { self.print_formal_generic_params(bound_generic_params); self.print_capture_clause(capture_clause); - self.print_closure_params(&fn_decl, body); + self.print_closure_params(fn_decl, body); self.space(); // This is a bare expression. @@ -1480,7 +1463,7 @@ impl<'a> State<'a> { // empty box to satisfy the close. self.ibox(0); } - hir::ExprKind::Block(ref blk, opt_label) => { + hir::ExprKind::Block(blk, opt_label) => { if let Some(label) = opt_label { self.print_ident(label.ident); self.word_space(":"); @@ -1489,42 +1472,42 @@ impl<'a> State<'a> { self.cbox(INDENT_UNIT); // head-box, will be closed by print-block after `{` self.ibox(0); - self.print_block(&blk); + self.print_block(blk); } - hir::ExprKind::Assign(ref lhs, ref rhs, _) => { + hir::ExprKind::Assign(lhs, rhs, _) => { let prec = AssocOp::Assign.precedence() as i8; - self.print_expr_maybe_paren(&lhs, prec + 1); + self.print_expr_maybe_paren(lhs, prec + 1); self.space(); self.word_space("="); - self.print_expr_maybe_paren(&rhs, prec); + self.print_expr_maybe_paren(rhs, prec); } - hir::ExprKind::AssignOp(op, ref lhs, ref rhs) => { + hir::ExprKind::AssignOp(op, lhs, rhs) => { let prec = AssocOp::Assign.precedence() as i8; - self.print_expr_maybe_paren(&lhs, prec + 1); + self.print_expr_maybe_paren(lhs, prec + 1); self.space(); self.word(op.node.as_str()); self.word_space("="); - self.print_expr_maybe_paren(&rhs, prec); + self.print_expr_maybe_paren(rhs, prec); } - hir::ExprKind::Field(ref expr, ident) => { + hir::ExprKind::Field(expr, ident) => { self.print_expr_maybe_paren(expr, parser::PREC_POSTFIX); self.word("."); self.print_ident(ident); } - hir::ExprKind::Index(ref expr, ref index) => { - self.print_expr_maybe_paren(&expr, parser::PREC_POSTFIX); + hir::ExprKind::Index(expr, index) => { + self.print_expr_maybe_paren(expr, parser::PREC_POSTFIX); self.word("["); - self.print_expr(&index); + self.print_expr(index); self.word("]"); } hir::ExprKind::Path(ref qpath) => self.print_qpath(qpath, true), - hir::ExprKind::Break(destination, ref opt_expr) => { + hir::ExprKind::Break(destination, opt_expr) => { self.word("break"); if let Some(label) = destination.label { self.space(); self.print_ident(label.ident); } - if let Some(ref expr) = *opt_expr { + if let Some(expr) = opt_expr { self.space(); self.print_expr_maybe_paren(expr, parser::PREC_JUMP); } @@ -1536,20 +1519,20 @@ impl<'a> State<'a> { self.print_ident(label.ident); } } - hir::ExprKind::Ret(ref result) => { + hir::ExprKind::Ret(result) => { self.word("return"); - if let Some(ref expr) = *result { + if let Some(expr) = result { self.word(" "); - self.print_expr_maybe_paren(&expr, parser::PREC_JUMP); + self.print_expr_maybe_paren(expr, parser::PREC_JUMP); } } - hir::ExprKind::InlineAsm(ref asm) => { + hir::ExprKind::InlineAsm(asm) => { self.word("asm!"); self.print_inline_asm(asm); } - hir::ExprKind::Yield(ref expr, _) => { + hir::ExprKind::Yield(expr, _) => { self.word_space("yield"); - self.print_expr_maybe_paren(&expr, parser::PREC_JUMP); + self.print_expr_maybe_paren(expr, parser::PREC_JUMP); } hir::ExprKind::Err => { self.popen(); @@ -1562,10 +1545,10 @@ impl<'a> State<'a> { } pub fn print_local_decl(&mut self, loc: &hir::Local<'_>) { - self.print_pat(&loc.pat); - if let Some(ref ty) = loc.ty { + self.print_pat(loc.pat); + if let Some(ty) = loc.ty { self.word_space(":"); - self.print_type(&ty); + self.print_type(ty); } } @@ -1596,8 +1579,8 @@ impl<'a> State<'a> { pub fn print_qpath(&mut self, qpath: &hir::QPath<'_>, colons_before_params: bool) { match *qpath { - hir::QPath::Resolved(None, ref path) => self.print_path(path, colons_before_params), - hir::QPath::Resolved(Some(ref qself), ref path) => { + hir::QPath::Resolved(None, path) => self.print_path(path, colons_before_params), + hir::QPath::Resolved(Some(qself), path) => { self.word("<"); self.print_type(qself); self.space(); @@ -1627,11 +1610,11 @@ impl<'a> State<'a> { colons_before_params, ) } - hir::QPath::TypeRelative(ref qself, ref item_segment) => { + hir::QPath::TypeRelative(qself, item_segment) => { // If we've got a compound-qualified-path, let's push an additional pair of angle // brackets, so that we pretty-print `<<A::B>::C>` as `<A::B>::C`, instead of just // `A::B::C` (since the latter could be ambiguous to the user) - if let hir::TyKind::Path(hir::QPath::Resolved(None, _)) = &qself.kind { + if let hir::TyKind::Path(hir::QPath::Resolved(None, _)) = qself.kind { self.print_type(qself); } else { self.word("<"); @@ -1663,7 +1646,7 @@ impl<'a> State<'a> { ) { if generic_args.parenthesized { self.word("("); - self.commasep(Inconsistent, generic_args.inputs(), |s, ty| s.print_type(&ty)); + self.commasep(Inconsistent, generic_args.inputs(), |s, ty| s.print_type(ty)); self.word(")"); self.space_if_not_bol(); @@ -1694,7 +1677,7 @@ impl<'a> State<'a> { start_or_comma(self); self.commasep( Inconsistent, - &generic_args.args, + generic_args.args, |s, generic_arg| match generic_arg { GenericArg::Lifetime(lt) if !elide_lifetimes => s.print_lifetime(lt), GenericArg::Lifetime(_) => {} @@ -1712,7 +1695,7 @@ impl<'a> State<'a> { self.word(".."); } - for binding in generic_args.bindings.iter() { + for binding in generic_args.bindings { start_or_comma(self); self.print_type_binding(binding); } @@ -1731,7 +1714,7 @@ impl<'a> State<'a> { hir::TypeBindingKind::Equality { ref term } => { self.word_space("="); match term { - Term::Ty(ref ty) => self.print_type(ty), + Term::Ty(ty) => self.print_type(ty), Term::Const(ref c) => self.print_anon_const(c), } } @@ -1748,7 +1731,7 @@ impl<'a> State<'a> { // is that it doesn't matter match pat.kind { PatKind::Wild => self.word("_"), - PatKind::Binding(binding_mode, _, ident, ref sub) => { + PatKind::Binding(binding_mode, _, ident, sub) => { match binding_mode { hir::BindingAnnotation::Ref => { self.word_nbsp("ref"); @@ -1764,33 +1747,33 @@ impl<'a> State<'a> { } } self.print_ident(ident); - if let Some(ref p) = *sub { + if let Some(p) = sub { self.word("@"); - self.print_pat(&p); + self.print_pat(p); } } - PatKind::TupleStruct(ref qpath, ref elts, ddpos) => { + PatKind::TupleStruct(ref qpath, elts, ddpos) => { self.print_qpath(qpath, true); self.popen(); if let Some(ddpos) = ddpos { - self.commasep(Inconsistent, &elts[..ddpos], |s, p| s.print_pat(&p)); + self.commasep(Inconsistent, &elts[..ddpos], |s, p| s.print_pat(p)); if ddpos != 0 { self.word_space(","); } self.word(".."); if ddpos != elts.len() { self.word(","); - self.commasep(Inconsistent, &elts[ddpos..], |s, p| s.print_pat(&p)); + self.commasep(Inconsistent, &elts[ddpos..], |s, p| s.print_pat(p)); } } else { - self.commasep(Inconsistent, &elts, |s, p| s.print_pat(&p)); + self.commasep(Inconsistent, elts, |s, p| s.print_pat(p)); } self.pclose(); } PatKind::Path(ref qpath) => { self.print_qpath(qpath, true); } - PatKind::Struct(ref qpath, ref fields, etc) => { + PatKind::Struct(ref qpath, fields, etc) => { self.print_qpath(qpath, true); self.nbsp(); self.word("{"); @@ -1800,14 +1783,14 @@ impl<'a> State<'a> { } self.commasep_cmnt( Consistent, - &fields, + fields, |s, f| { s.cbox(INDENT_UNIT); if !f.is_shorthand { s.print_ident(f.ident); s.word_nbsp(":"); } - s.print_pat(&f.pat); + s.print_pat(f.pat); s.end() }, |f| f.pat.span, @@ -1823,58 +1806,58 @@ impl<'a> State<'a> { } self.word("}"); } - PatKind::Or(ref pats) => { - self.strsep("|", true, Inconsistent, &pats, |s, p| s.print_pat(&p)); + PatKind::Or(pats) => { + self.strsep("|", true, Inconsistent, pats, |s, p| s.print_pat(p)); } - PatKind::Tuple(ref elts, ddpos) => { + PatKind::Tuple(elts, ddpos) => { self.popen(); if let Some(ddpos) = ddpos { - self.commasep(Inconsistent, &elts[..ddpos], |s, p| s.print_pat(&p)); + self.commasep(Inconsistent, &elts[..ddpos], |s, p| s.print_pat(p)); if ddpos != 0 { self.word_space(","); } self.word(".."); if ddpos != elts.len() { self.word(","); - self.commasep(Inconsistent, &elts[ddpos..], |s, p| s.print_pat(&p)); + self.commasep(Inconsistent, &elts[ddpos..], |s, p| s.print_pat(p)); } } else { - self.commasep(Inconsistent, &elts[..], |s, p| s.print_pat(&p)); + self.commasep(Inconsistent, elts, |s, p| s.print_pat(p)); if elts.len() == 1 { self.word(","); } } self.pclose(); } - PatKind::Box(ref inner) => { + PatKind::Box(inner) => { let is_range_inner = matches!(inner.kind, PatKind::Range(..)); self.word("box "); if is_range_inner { self.popen(); } - self.print_pat(&inner); + self.print_pat(inner); if is_range_inner { self.pclose(); } } - PatKind::Ref(ref inner, mutbl) => { + PatKind::Ref(inner, mutbl) => { let is_range_inner = matches!(inner.kind, PatKind::Range(..)); self.word("&"); self.word(mutbl.prefix_str()); if is_range_inner { self.popen(); } - self.print_pat(&inner); + self.print_pat(inner); if is_range_inner { self.pclose(); } } - PatKind::Lit(ref e) => self.print_expr(&e), - PatKind::Range(ref begin, ref end, ref end_kind) => { + PatKind::Lit(e) => self.print_expr(e), + PatKind::Range(begin, end, end_kind) => { if let Some(expr) = begin { self.print_expr(expr); } - match *end_kind { + match end_kind { RangeEnd::Included => self.word("..."), RangeEnd::Excluded => self.word(".."), } @@ -1882,24 +1865,24 @@ impl<'a> State<'a> { self.print_expr(expr); } } - PatKind::Slice(ref before, ref slice, ref after) => { + PatKind::Slice(before, slice, after) => { self.word("["); - self.commasep(Inconsistent, &before, |s, p| s.print_pat(&p)); - if let Some(ref p) = *slice { + self.commasep(Inconsistent, before, |s, p| s.print_pat(p)); + if let Some(p) = slice { if !before.is_empty() { self.word_space(","); } if let PatKind::Wild = p.kind { // Print nothing. } else { - self.print_pat(&p); + self.print_pat(p); } self.word(".."); if !after.is_empty() { self.word_space(","); } } - self.commasep(Inconsistent, &after, |s, p| s.print_pat(&p)); + self.commasep(Inconsistent, after, |s, p| s.print_pat(p)); self.word("]"); } } @@ -1908,7 +1891,7 @@ impl<'a> State<'a> { pub fn print_param(&mut self, arg: &hir::Param<'_>) { self.print_outer_attributes(self.attrs(arg.hir_id)); - self.print_pat(&arg.pat); + self.print_pat(arg.pat); } pub fn print_arm(&mut self, arm: &hir::Arm<'_>) { @@ -1920,32 +1903,32 @@ impl<'a> State<'a> { self.cbox(INDENT_UNIT); self.ann.pre(self, AnnNode::Arm(arm)); self.ibox(0); - self.print_outer_attributes(&self.attrs(arm.hir_id)); - self.print_pat(&arm.pat); + self.print_outer_attributes(self.attrs(arm.hir_id)); + self.print_pat(arm.pat); self.space(); if let Some(ref g) = arm.guard { - match g { + match *g { hir::Guard::If(e) => { self.word_space("if"); - self.print_expr(&e); + self.print_expr(e); self.space(); } - hir::Guard::IfLet(hir::Let { pat, ty, init, .. }) => { + hir::Guard::IfLet(&hir::Let { pat, ty, init, .. }) => { self.word_nbsp("if"); - self.print_let(pat, *ty, init); + self.print_let(pat, ty, init); } } } self.word_space("=>"); match arm.body.kind { - hir::ExprKind::Block(ref blk, opt_label) => { + hir::ExprKind::Block(blk, opt_label) => { if let Some(label) = opt_label { self.print_ident(label.ident); self.word_space(":"); } // the block will close the pattern's ibox - self.print_block_unclosed(&blk); + self.print_block_unclosed(blk); // If it is a user-provided unsafe block, print a comma after it if let hir::BlockCheckMode::UnsafeBlock(hir::UnsafeSource::UserProvided) = blk.rules @@ -1955,7 +1938,7 @@ impl<'a> State<'a> { } _ => { self.end(); // close the ibox for the pattern - self.print_expr(&arm.body); + self.print_expr(arm.body); self.word(","); } } @@ -1978,13 +1961,13 @@ impl<'a> State<'a> { self.nbsp(); self.print_name(name); } - self.print_generic_params(&generics.params); + self.print_generic_params(generics.params); self.popen(); let mut i = 0; // Make sure we aren't supplied *both* `arg_names` and `body_id`. assert!(arg_names.is_empty() || body_id.is_none()); - self.commasep(Inconsistent, &decl.inputs, |s, ty| { + self.commasep(Inconsistent, decl.inputs, |s, ty| { s.ibox(INDENT_UNIT); if let Some(arg_name) = arg_names.get(i) { s.word(arg_name.to_string()); @@ -2011,7 +1994,7 @@ impl<'a> State<'a> { fn print_closure_params(&mut self, decl: &hir::FnDecl<'_>, body_id: hir::BodyId) { self.word("|"); let mut i = 0; - self.commasep(Inconsistent, &decl.inputs, |s, ty| { + self.commasep(Inconsistent, decl.inputs, |s, ty| { s.ibox(INDENT_UNIT); s.ann.nested(s, Nested::BodyParamPat(body_id, i)); @@ -2035,8 +2018,8 @@ impl<'a> State<'a> { self.space_if_not_bol(); self.word_space("->"); match decl.output { - hir::FnRetTy::Return(ref ty) => { - self.print_type(&ty); + hir::FnRetTy::Return(ty) => { + self.print_type(ty); self.maybe_print_comment(ty.span.lo()); } hir::FnRetTy::DefaultReturn(..) => unreachable!(), @@ -2107,20 +2090,20 @@ impl<'a> State<'a> { match param.kind { GenericParamKind::Lifetime { .. } => {} - GenericParamKind::Type { ref default, .. } => { + GenericParamKind::Type { default, .. } => { if let Some(default) = default { self.space(); self.word_space("="); - self.print_type(&default) + self.print_type(default); } } - GenericParamKind::Const { ref ty, ref default } => { + GenericParamKind::Const { ty, ref default } => { self.word_space(":"); self.print_type(ty); - if let Some(ref default) = default { + if let Some(default) = default { self.space(); self.word_space("="); - self.print_anon_const(&default) + self.print_anon_const(default); } } } @@ -2143,7 +2126,7 @@ impl<'a> State<'a> { self.word_space(","); } - match predicate { + match *predicate { hir::WherePredicate::BoundPredicate(hir::WhereBoundPredicate { bound_generic_params, bounded_ty, @@ -2151,11 +2134,11 @@ impl<'a> State<'a> { .. }) => { self.print_formal_generic_params(bound_generic_params); - self.print_type(&bounded_ty); - self.print_bounds(":", *bounds); + self.print_type(bounded_ty); + self.print_bounds(":", bounds); } hir::WherePredicate::RegionPredicate(hir::WhereRegionPredicate { - lifetime, + ref lifetime, bounds, .. }) => { @@ -2200,7 +2183,7 @@ impl<'a> State<'a> { pub fn print_mt(&mut self, mt: &hir::MutTy<'_>, print_const: bool) { self.print_mutability(mt.mutbl, print_const); - self.print_type(&mt.ty) + self.print_type(mt.ty); } pub fn print_fn_output(&mut self, decl: &hir::FnDecl<'_>) { @@ -2213,11 +2196,11 @@ impl<'a> State<'a> { self.word_space("->"); match decl.output { hir::FnRetTy::DefaultReturn(..) => unreachable!(), - hir::FnRetTy::Return(ref ty) => self.print_type(&ty), + hir::FnRetTy::Return(ty) => self.print_type(ty), } self.end(); - if let hir::FnRetTy::Return(ref output) = decl.output { + if let hir::FnRetTy::Return(output) = decl.output { self.maybe_print_comment(output.span.lo()); } } @@ -2243,7 +2226,7 @@ impl<'a> State<'a> { asyncness: hir::IsAsync::NotAsync, }, name, - &generics, + generics, arg_names, None, ); @@ -2312,7 +2295,7 @@ fn stmt_ends_with_semi(stmt: &hir::StmtKind<'_>) -> bool { match *stmt { hir::StmtKind::Local(_) => true, hir::StmtKind::Item(_) => false, - hir::StmtKind::Expr(ref e) => expr_requires_semi_to_be_stmt(&e), + hir::StmtKind::Expr(e) => expr_requires_semi_to_be_stmt(e), hir::StmtKind::Semi(..) => false, } } @@ -2351,22 +2334,22 @@ fn contains_exterior_struct_lit(value: &hir::Expr<'_>) -> bool { match value.kind { hir::ExprKind::Struct(..) => true, - hir::ExprKind::Assign(ref lhs, ref rhs, _) - | hir::ExprKind::AssignOp(_, ref lhs, ref rhs) - | hir::ExprKind::Binary(_, ref lhs, ref rhs) => { + hir::ExprKind::Assign(lhs, rhs, _) + | hir::ExprKind::AssignOp(_, lhs, rhs) + | hir::ExprKind::Binary(_, lhs, rhs) => { // `X { y: 1 } + X { y: 2 }` - contains_exterior_struct_lit(&lhs) || contains_exterior_struct_lit(&rhs) + contains_exterior_struct_lit(lhs) || contains_exterior_struct_lit(rhs) } - hir::ExprKind::Unary(_, ref x) - | hir::ExprKind::Cast(ref x, _) - | hir::ExprKind::Type(ref x, _) - | hir::ExprKind::Field(ref x, _) - | hir::ExprKind::Index(ref x, _) => { + hir::ExprKind::Unary(_, x) + | hir::ExprKind::Cast(x, _) + | hir::ExprKind::Type(x, _) + | hir::ExprKind::Field(x, _) + | hir::ExprKind::Index(x, _) => { // `&X { y: 1 }, X { y: 1 }.y` - contains_exterior_struct_lit(&x) + contains_exterior_struct_lit(x) } - hir::ExprKind::MethodCall(.., ref exprs, _) => { + hir::ExprKind::MethodCall(.., exprs, _) => { // `X { y: 1 }.bar(...)` contains_exterior_struct_lit(&exprs[0]) } diff --git a/compiler/rustc_infer/src/infer/canonical/query_response.rs b/compiler/rustc_infer/src/infer/canonical/query_response.rs index 8938ed78a94..7120d5ad934 100644 --- a/compiler/rustc_infer/src/infer/canonical/query_response.rs +++ b/compiler/rustc_infer/src/infer/canonical/query_response.rs @@ -128,7 +128,7 @@ impl<'cx, 'tcx> InferCtxt<'cx, 'tcx> { let region_constraints = self.with_region_constraints(|region_constraints| { make_query_region_constraints( tcx, - region_obligations.iter().map(|(_, r_o)| (r_o.sup_type, r_o.sub_region)), + region_obligations.iter().map(|r_o| (r_o.sup_type, r_o.sub_region)), region_constraints, ) }); diff --git a/compiler/rustc_infer/src/infer/combine.rs b/compiler/rustc_infer/src/infer/combine.rs index 67dcb6e708b..8bf1de34a9b 100644 --- a/compiler/rustc_infer/src/infer/combine.rs +++ b/compiler/rustc_infer/src/infer/combine.rs @@ -37,7 +37,7 @@ use rustc_middle::traits::ObligationCause; use rustc_middle::ty::error::{ExpectedFound, TypeError}; use rustc_middle::ty::relate::{self, Relate, RelateResult, TypeRelation}; use rustc_middle::ty::subst::SubstsRef; -use rustc_middle::ty::{self, InferConst, ToPredicate, Ty, TyCtxt, TypeFoldable}; +use rustc_middle::ty::{self, InferConst, ToPredicate, Ty, TyCtxt, TypeVisitable}; use rustc_middle::ty::{IntType, UintType}; use rustc_span::{Span, DUMMY_SP}; diff --git a/compiler/rustc_infer/src/infer/error_reporting/mod.rs b/compiler/rustc_infer/src/infer/error_reporting/mod.rs index e319f17b0e6..665669be2dd 100644 --- a/compiler/rustc_infer/src/infer/error_reporting/mod.rs +++ b/compiler/rustc_infer/src/infer/error_reporting/mod.rs @@ -68,7 +68,7 @@ use rustc_middle::dep_graph::DepContext; use rustc_middle::ty::print::with_no_trimmed_paths; use rustc_middle::ty::{ self, error::TypeError, Binder, List, Region, Subst, Ty, TyCtxt, TypeFoldable, - TypeSuperFoldable, + TypeSuperVisitable, TypeVisitable, }; use rustc_span::{sym, symbol::kw, BytePos, DesugaringKind, Pos, Span}; use rustc_target::spec::abi; @@ -1540,7 +1540,7 @@ impl<'a, 'tcx> InferCtxt<'a, 'tcx> { } } - impl<'tcx> ty::fold::TypeVisitor<'tcx> for OpaqueTypesVisitor<'tcx> { + impl<'tcx> ty::visit::TypeVisitor<'tcx> for OpaqueTypesVisitor<'tcx> { fn visit_ty(&mut self, t: Ty<'tcx>) -> ControlFlow<Self::BreakTy> { if let Some((kind, def_id)) = TyCategory::from_ty(self.tcx, t) { let span = self.tcx.def_span(def_id); diff --git a/compiler/rustc_infer/src/infer/error_reporting/need_type_info.rs b/compiler/rustc_infer/src/infer/error_reporting/need_type_info.rs index 20b9ed9cd73..4d29fc46946 100644 --- a/compiler/rustc_infer/src/infer/error_reporting/need_type_info.rs +++ b/compiler/rustc_infer/src/infer/error_reporting/need_type_info.rs @@ -313,11 +313,10 @@ impl<'a, 'tcx> InferCtxt<'a, 'tcx> { pub fn emit_inference_failure_err( &self, body_id: Option<hir::BodyId>, - span: Span, + failure_span: Span, arg: GenericArg<'tcx>, - // FIXME(#94483): Either use this or remove it. - _impl_candidates: Vec<ty::TraitRef<'tcx>>, error_code: TypeAnnotationNeeded, + should_label_span: bool, ) -> DiagnosticBuilder<'tcx, ErrorGuaranteed> { let arg = self.resolve_vars_if_possible(arg); let arg_data = self.extract_inference_diagnostics_data(arg, None); @@ -326,7 +325,7 @@ impl<'a, 'tcx> InferCtxt<'a, 'tcx> { // If we don't have any typeck results we're outside // of a body, so we won't be able to get better info // here. - return self.bad_inference_failure_err(span, arg_data, error_code); + return self.bad_inference_failure_err(failure_span, arg_data, error_code); }; let typeck_results = typeck_results.borrow(); let typeck_results = &typeck_results; @@ -334,12 +333,11 @@ impl<'a, 'tcx> InferCtxt<'a, 'tcx> { let mut local_visitor = FindInferSourceVisitor::new(&self, typeck_results, arg); if let Some(body_id) = body_id { let expr = self.tcx.hir().expect_expr(body_id.hir_id); - debug!(?expr); local_visitor.visit_expr(expr); } let Some(InferSource { span, kind }) = local_visitor.infer_source else { - return self.bad_inference_failure_err(span, arg_data, error_code) + return self.bad_inference_failure_err(failure_span, arg_data, error_code) }; let error_code = error_code.into(); @@ -348,6 +346,11 @@ impl<'a, 'tcx> InferCtxt<'a, 'tcx> { &format!("type annotations needed{}", kind.ty_msg(self)), error_code, ); + + if should_label_span && !failure_span.overlaps(span) { + err.span_label(failure_span, "type must be known at this point"); + } + match kind { InferSourceKind::LetBinding { insert_span, pattern_name, ty } => { let suggestion_msg = if let Some(name) = pattern_name { @@ -529,6 +532,23 @@ enum InferSourceKind<'tcx> { }, } +impl<'tcx> InferSource<'tcx> { + fn from_expansion(&self) -> bool { + let source_from_expansion = match self.kind { + InferSourceKind::LetBinding { insert_span, .. } + | InferSourceKind::ClosureArg { insert_span, .. } + | InferSourceKind::GenericArg { insert_span, .. } => insert_span.from_expansion(), + InferSourceKind::FullyQualifiedMethodCall { receiver, .. } => { + receiver.span.from_expansion() + } + InferSourceKind::ClosureReturn { data, should_wrap_expr, .. } => { + data.span().from_expansion() || should_wrap_expr.map_or(false, Span::from_expansion) + } + }; + source_from_expansion || self.span.from_expansion() + } +} + impl<'tcx> InferSourceKind<'tcx> { fn ty_msg(&self, infcx: &InferCtxt<'_, 'tcx>) -> String { match *self { @@ -550,6 +570,7 @@ impl<'tcx> InferSourceKind<'tcx> { } } +#[derive(Debug)] struct InsertableGenericArgs<'tcx> { insert_span: Span, substs: SubstsRef<'tcx>, @@ -598,43 +619,65 @@ impl<'a, 'tcx> FindInferSourceVisitor<'a, 'tcx> { /// Sources with a small cost are prefer and should result /// in a clearer and idiomatic suggestion. fn source_cost(&self, source: &InferSource<'tcx>) -> usize { - let tcx = self.infcx.tcx; - - fn arg_cost<'tcx>(arg: GenericArg<'tcx>) -> usize { - match arg.unpack() { - GenericArgKind::Lifetime(_) => 0, // erased - GenericArgKind::Type(ty) => ty_cost(ty), - GenericArgKind::Const(_) => 3, // some non-zero value - } + #[derive(Clone, Copy)] + struct CostCtxt<'tcx> { + tcx: TyCtxt<'tcx>, } - fn ty_cost<'tcx>(ty: Ty<'tcx>) -> usize { - match ty.kind() { - ty::Closure(..) => 100, - ty::FnDef(..) => 20, - ty::FnPtr(..) => 10, - ty::Infer(..) => 0, - _ => 1, + impl<'tcx> CostCtxt<'tcx> { + fn arg_cost(self, arg: GenericArg<'tcx>) -> usize { + match arg.unpack() { + GenericArgKind::Lifetime(_) => 0, // erased + GenericArgKind::Type(ty) => self.ty_cost(ty), + GenericArgKind::Const(_) => 3, // some non-zero value + } + } + fn ty_cost(self, ty: Ty<'tcx>) -> usize { + match *ty.kind() { + ty::Closure(..) => 1000, + ty::FnDef(..) => 150, + ty::FnPtr(..) => 30, + ty::Adt(def, substs) => { + 5 + self + .tcx + .generics_of(def.did()) + .own_substs_no_defaults(self.tcx, substs) + .iter() + .map(|&arg| self.arg_cost(arg)) + .sum::<usize>() + } + ty::Tuple(args) => 5 + args.iter().map(|arg| self.ty_cost(arg)).sum::<usize>(), + ty::Ref(_, ty, _) => 2 + self.ty_cost(ty), + ty::Infer(..) => 0, + _ => 1, + } } } // The sources are listed in order of preference here. - match source.kind { - InferSourceKind::LetBinding { ty, .. } => ty_cost(ty), - InferSourceKind::ClosureArg { ty, .. } => 5 + ty_cost(ty), + let tcx = self.infcx.tcx; + let ctx = CostCtxt { tcx }; + let base_cost = match source.kind { + InferSourceKind::LetBinding { ty, .. } => ctx.ty_cost(ty), + InferSourceKind::ClosureArg { ty, .. } => ctx.ty_cost(ty), InferSourceKind::GenericArg { def_id, generic_args, .. } => { let variant_cost = match tcx.def_kind(def_id) { - DefKind::Variant | DefKind::Ctor(CtorOf::Variant, _) => 15, // `None::<u32>` and friends are ugly. - _ => 12, + // `None::<u32>` and friends are ugly. + DefKind::Variant | DefKind::Ctor(CtorOf::Variant, _) => 15, + _ => 10, }; - variant_cost + generic_args.iter().map(|&arg| arg_cost(arg)).sum::<usize>() + variant_cost + generic_args.iter().map(|&arg| ctx.arg_cost(arg)).sum::<usize>() } InferSourceKind::FullyQualifiedMethodCall { substs, .. } => { - 20 + substs.iter().map(|arg| arg_cost(arg)).sum::<usize>() + 20 + substs.iter().map(|arg| ctx.arg_cost(arg)).sum::<usize>() } InferSourceKind::ClosureReturn { ty, should_wrap_expr, .. } => { - 30 + ty_cost(ty) + if should_wrap_expr.is_some() { 10 } else { 0 } + 30 + ctx.ty_cost(ty) + if should_wrap_expr.is_some() { 10 } else { 0 } } - } + }; + + let suggestion_may_apply = if source.from_expansion() { 10000 } else { 0 }; + + base_cost + suggestion_may_apply } /// Uses `fn source_cost` to determine whether this inference source is preferable to @@ -642,6 +685,7 @@ impl<'a, 'tcx> FindInferSourceVisitor<'a, 'tcx> { #[instrument(level = "debug", skip(self))] fn update_infer_source(&mut self, new_source: InferSource<'tcx>) { let cost = self.source_cost(&new_source) + self.attempt; + debug!(?cost); self.attempt += 1; if cost < self.infer_source_cost { self.infer_source_cost = cost; @@ -649,6 +693,11 @@ impl<'a, 'tcx> FindInferSourceVisitor<'a, 'tcx> { } } + fn node_substs_opt(&self, hir_id: HirId) -> Option<SubstsRef<'tcx>> { + let substs = self.typeck_results.node_substs_opt(hir_id); + self.infcx.resolve_vars_if_possible(substs) + } + fn opt_node_type(&self, hir_id: HirId) -> Option<Ty<'tcx>> { let ty = self.typeck_results.node_type_opt(hir_id); self.infcx.resolve_vars_if_possible(ty) @@ -731,14 +780,24 @@ impl<'a, 'tcx> FindInferSourceVisitor<'a, 'tcx> { let tcx = self.infcx.tcx; match expr.kind { hir::ExprKind::Path(ref path) => { - if let Some(substs) = self.typeck_results.node_substs_opt(expr.hir_id) { + if let Some(substs) = self.node_substs_opt(expr.hir_id) { return self.path_inferred_subst_iter(expr.hir_id, substs, path); } } - hir::ExprKind::Struct(path, _, _) => { + // FIXME(#98711): Ideally we would also deal with type relative + // paths here, even if that is quite rare. + // + // See the `need_type_info/expr-struct-type-relative-gat.rs` test + // for an example where that would be needed. + // + // However, the `type_dependent_def_id` for `Self::Output` in an + // impl is currently the `DefId` of `Output` in the trait definition + // which makes this somewhat difficult and prevents us from just + // using `self.path_inferred_subst_iter` here. + hir::ExprKind::Struct(&hir::QPath::Resolved(_self_ty, path), _, _) => { if let Some(ty) = self.opt_node_type(expr.hir_id) { if let ty::Adt(_, substs) = ty.kind() { - return self.path_inferred_subst_iter(expr.hir_id, substs, path); + return Box::new(self.resolved_path_inferred_subst_iter(path, substs)); } } } @@ -749,7 +808,7 @@ impl<'a, 'tcx> FindInferSourceVisitor<'a, 'tcx> { if generics.has_impl_trait() { None? } - let substs = self.typeck_results.node_substs_opt(expr.hir_id)?; + let substs = self.node_substs_opt(expr.hir_id)?; let span = tcx.hir().span(segment.hir_id?); let insert_span = segment.ident.span.shrink_to_hi().with_hi(span.hi()); InsertableGenericArgs { @@ -945,6 +1004,7 @@ impl<'a, 'tcx> Visitor<'tcx> for FindInferSourceVisitor<'a, 'tcx> { intravisit::walk_body(self, body); } + #[instrument(level = "debug", skip(self))] fn visit_expr(&mut self, expr: &'tcx Expr<'tcx>) { let tcx = self.infcx.tcx; match expr.kind { @@ -959,12 +1019,14 @@ impl<'a, 'tcx> Visitor<'tcx> for FindInferSourceVisitor<'a, 'tcx> { _ => intravisit::walk_expr(self, expr), } - for InsertableGenericArgs { insert_span, substs, generics_def_id, def_id } in - self.expr_inferred_subst_iter(expr) - { + for args in self.expr_inferred_subst_iter(expr) { + debug!(?args); + let InsertableGenericArgs { insert_span, substs, generics_def_id, def_id } = args; let generics = tcx.generics_of(generics_def_id); - if let Some(argument_index) = - generics.own_substs(substs).iter().position(|&arg| self.generic_arg_is_target(arg)) + if let Some(argument_index) = generics + .own_substs(substs) + .iter() + .position(|&arg| self.generic_arg_contains_target(arg)) { let substs = self.infcx.resolve_vars_if_possible(substs); let generic_args = &generics.own_substs_no_defaults(tcx, substs) @@ -1020,7 +1082,7 @@ impl<'a, 'tcx> Visitor<'tcx> for FindInferSourceVisitor<'a, 'tcx> { .any(|generics| generics.has_impl_trait()) }; if let ExprKind::MethodCall(path, args, span) = expr.kind - && let Some(substs) = self.typeck_results.node_substs_opt(expr.hir_id) + && let Some(substs) = self.node_substs_opt(expr.hir_id) && substs.iter().any(|arg| self.generic_arg_contains_target(arg)) && let Some(def_id) = self.typeck_results.type_dependent_def_id(expr.hir_id) && self.infcx.tcx.trait_of_item(def_id).is_some() diff --git a/compiler/rustc_infer/src/infer/error_reporting/nice_region_error/static_impl_trait.rs b/compiler/rustc_infer/src/infer/error_reporting/nice_region_error/static_impl_trait.rs index 09430a135a3..02928c4aa57 100644 --- a/compiler/rustc_infer/src/infer/error_reporting/nice_region_error/static_impl_trait.rs +++ b/compiler/rustc_infer/src/infer/error_reporting/nice_region_error/static_impl_trait.rs @@ -10,7 +10,7 @@ use rustc_hir::def_id::DefId; use rustc_hir::intravisit::{walk_ty, Visitor}; use rustc_hir::{self as hir, GenericBound, Item, ItemKind, Lifetime, LifetimeName, Node, TyKind}; use rustc_middle::ty::{ - self, AssocItemContainer, StaticLifetimeVisitor, Ty, TyCtxt, TypeSuperFoldable, TypeVisitor, + self, AssocItemContainer, StaticLifetimeVisitor, Ty, TyCtxt, TypeSuperVisitable, TypeVisitor, }; use rustc_span::symbol::Ident; use rustc_span::Span; diff --git a/compiler/rustc_infer/src/infer/error_reporting/nice_region_error/trait_impl_difference.rs b/compiler/rustc_infer/src/infer/error_reporting/nice_region_error/trait_impl_difference.rs index f6b49e41d4c..91bf9695dfc 100644 --- a/compiler/rustc_infer/src/infer/error_reporting/nice_region_error/trait_impl_difference.rs +++ b/compiler/rustc_infer/src/infer/error_reporting/nice_region_error/trait_impl_difference.rs @@ -11,7 +11,7 @@ use rustc_hir::def_id::{DefId, LocalDefId}; use rustc_hir::intravisit::Visitor; use rustc_middle::hir::nested_filter; use rustc_middle::ty::print::RegionHighlightMode; -use rustc_middle::ty::{self, Ty, TyCtxt, TypeSuperFoldable, TypeVisitor}; +use rustc_middle::ty::{self, Ty, TyCtxt, TypeSuperVisitable, TypeVisitor}; use rustc_span::{Span, Symbol}; use std::ops::ControlFlow; @@ -88,7 +88,7 @@ impl<'a, 'tcx> NiceRegionError<'a, 'tcx> { } } - impl<'tcx> ty::fold::TypeVisitor<'tcx> for HighlightBuilder<'tcx> { + impl<'tcx> ty::visit::TypeVisitor<'tcx> for HighlightBuilder<'tcx> { fn visit_region(&mut self, r: ty::Region<'tcx>) -> ControlFlow<Self::BreakTy> { if !r.has_name() && self.counter <= 3 { self.highlight.highlighting_region(r, self.counter); 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 42d52446ab6..b356da0be55 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 @@ -5,7 +5,7 @@ use crate::infer::error_reporting::nice_region_error::NiceRegionError; use crate::infer::TyCtxt; use rustc_hir as hir; use rustc_hir::def_id::LocalDefId; -use rustc_middle::ty::{self, Binder, DefIdTree, Region, Ty, TypeFoldable}; +use rustc_middle::ty::{self, Binder, DefIdTree, Region, Ty, TypeVisitable}; use rustc_span::Span; /// Information about the anonymous region we are searching for. @@ -142,7 +142,7 @@ impl<'a, 'tcx> NiceRegionError<'a, 'tcx> { fn includes_region( &self, - ty: Binder<'tcx, impl TypeFoldable<'tcx>>, + ty: Binder<'tcx, impl TypeVisitable<'tcx>>, region: ty::BoundRegionKind, ) -> bool { let late_bound_regions = self.tcx().collect_referenced_late_bound_regions(&ty); diff --git a/compiler/rustc_infer/src/infer/free_regions.rs b/compiler/rustc_infer/src/infer/free_regions.rs index 082eb1bf111..fad949a3bc6 100644 --- a/compiler/rustc_infer/src/infer/free_regions.rs +++ b/compiler/rustc_infer/src/infer/free_regions.rs @@ -4,7 +4,6 @@ //! and use that to decide when one free region outlives another, and so forth. use rustc_data_structures::transitive_relation::TransitiveRelation; -use rustc_hir::def_id::DefId; use rustc_middle::ty::{self, Lift, Region, TyCtxt}; /// Combines a `FreeRegionMap` and a `TyCtxt`. @@ -14,16 +13,13 @@ use rustc_middle::ty::{self, Lift, Region, TyCtxt}; pub(crate) struct RegionRelations<'a, 'tcx> { pub tcx: TyCtxt<'tcx>, - /// The context used for debug messages - pub context: DefId, - /// Free-region relationships. pub free_regions: &'a FreeRegionMap<'tcx>, } impl<'a, 'tcx> RegionRelations<'a, 'tcx> { - pub fn new(tcx: TyCtxt<'tcx>, context: DefId, free_regions: &'a FreeRegionMap<'tcx>) -> Self { - Self { tcx, context, free_regions } + pub fn new(tcx: TyCtxt<'tcx>, free_regions: &'a FreeRegionMap<'tcx>) -> Self { + Self { tcx, free_regions } } pub fn lub_free_regions(&self, r_a: Region<'tcx>, r_b: Region<'tcx>) -> Region<'tcx> { diff --git a/compiler/rustc_infer/src/infer/freshen.rs b/compiler/rustc_infer/src/infer/freshen.rs index 024f7409947..84004d2b21f 100644 --- a/compiler/rustc_infer/src/infer/freshen.rs +++ b/compiler/rustc_infer/src/infer/freshen.rs @@ -34,7 +34,7 @@ use super::InferCtxt; use rustc_data_structures::fx::FxHashMap; use rustc_middle::infer::unify_key::ToType; use rustc_middle::ty::fold::TypeFolder; -use rustc_middle::ty::{self, Ty, TyCtxt, TypeFoldable, TypeSuperFoldable}; +use rustc_middle::ty::{self, Ty, TyCtxt, TypeFoldable, TypeSuperFoldable, TypeVisitable}; use std::collections::hash_map::Entry; pub struct TypeFreshener<'a, 'tcx> { 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 68c709a2e24..87fa22b3835 100644 --- a/compiler/rustc_infer/src/infer/lexical_region_resolve/mod.rs +++ b/compiler/rustc_infer/src/infer/lexical_region_resolve/mod.rs @@ -120,13 +120,9 @@ impl<'cx, 'tcx> LexicalResolver<'cx, 'tcx> { ) -> LexicalRegionResolutions<'tcx> { let mut var_data = self.construct_var_data(self.tcx()); - // Dorky hack to cause `dump_constraints` to only get called - // if debug mode is enabled: - debug!( - "----() End constraint listing (context={:?}) {:?}---", - self.region_rels.context, - self.dump_constraints(self.region_rels) - ); + if cfg!(debug_assertions) { + self.dump_constraints(); + } let graph = self.construct_graph(); self.expand_givens(&graph); @@ -156,8 +152,8 @@ impl<'cx, 'tcx> LexicalResolver<'cx, 'tcx> { } } - fn dump_constraints(&self, free_regions: &RegionRelations<'_, 'tcx>) { - debug!("----() Start constraint listing (context={:?}) ()----", free_regions.context); + #[instrument(level = "debug", skip(self))] + fn dump_constraints(&self) { for (idx, (constraint, _)) in self.data.constraints.iter().enumerate() { debug!("Constraint {} => {:?}", idx, constraint); } diff --git a/compiler/rustc_infer/src/infer/mod.rs b/compiler/rustc_infer/src/infer/mod.rs index 6f88b83a473..991fd23ab43 100644 --- a/compiler/rustc_infer/src/infer/mod.rs +++ b/compiler/rustc_infer/src/infer/mod.rs @@ -15,7 +15,6 @@ use rustc_data_structures::sync::Lrc; use rustc_data_structures::undo_log::Rollback; use rustc_data_structures::unify as ut; use rustc_errors::{DiagnosticBuilder, ErrorGuaranteed}; -use rustc_hir as hir; use rustc_hir::def_id::{DefId, LocalDefId}; use rustc_middle::infer::canonical::{Canonical, CanonicalVarValues}; use rustc_middle::infer::unify_key::{ConstVarValue, ConstVariableValue}; @@ -26,6 +25,7 @@ use rustc_middle::ty::error::{ExpectedFound, TypeError}; use rustc_middle::ty::fold::{TypeFoldable, TypeFolder, TypeSuperFoldable}; use rustc_middle::ty::relate::RelateResult; use rustc_middle::ty::subst::{GenericArg, GenericArgKind, InternalSubsts, SubstsRef}; +use rustc_middle::ty::visit::TypeVisitable; pub use rustc_middle::ty::IntVarValue; use rustc_middle::ty::{self, GenericParamDefKind, InferConst, Ty, TyCtxt}; use rustc_middle::ty::{ConstVid, FloatVid, IntVid, TyVid}; @@ -147,7 +147,7 @@ pub struct InferCtxtInner<'tcx> { /// for each body-id in this map, which will process the /// obligations within. This is expected to be done 'late enough' /// that all type inference variables have been bound and so forth. - region_obligations: Vec<(hir::HirId, RegionObligation<'tcx>)>, + region_obligations: Vec<RegionObligation<'tcx>>, undo_log: InferCtxtUndoLogs<'tcx>, @@ -171,7 +171,7 @@ impl<'tcx> InferCtxtInner<'tcx> { } #[inline] - pub fn region_obligations(&self) -> &[(hir::HirId, RegionObligation<'tcx>)] { + pub fn region_obligations(&self) -> &[RegionObligation<'tcx>] { &self.region_obligations } @@ -319,7 +319,7 @@ pub struct InferCtxt<'a, 'tcx> { } /// See the `error_reporting` module for more details. -#[derive(Clone, Copy, Debug, PartialEq, Eq, TypeFoldable)] +#[derive(Clone, Copy, Debug, PartialEq, Eq, TypeFoldable, TypeVisitable)] pub enum ValuePairs<'tcx> { Regions(ExpectedFound<ty::Region<'tcx>>), Terms(ExpectedFound<ty::Term<'tcx>>), @@ -1267,7 +1267,6 @@ impl<'a, 'tcx> InferCtxt<'a, 'tcx> { /// `resolve_vars_if_possible` as well as `fully_resolve`. pub fn resolve_regions( &self, - region_context: DefId, outlives_env: &OutlivesEnvironment<'tcx>, ) -> Vec<RegionResolutionError<'tcx>> { let (var_infos, data) = { @@ -1286,8 +1285,7 @@ impl<'a, 'tcx> InferCtxt<'a, 'tcx> { .into_infos_and_data() }; - let region_rels = - &RegionRelations::new(self.tcx, region_context, outlives_env.free_region_map()); + let region_rels = &RegionRelations::new(self.tcx, outlives_env.free_region_map()); let (lexical_region_resolutions, errors) = lexical_region_resolve::resolve(outlives_env.param_env, region_rels, var_infos, data); @@ -1302,12 +1300,8 @@ impl<'a, 'tcx> InferCtxt<'a, 'tcx> { /// result. After this, no more unification operations should be /// done -- or the compiler will panic -- but it is legal to use /// `resolve_vars_if_possible` as well as `fully_resolve`. - pub fn resolve_regions_and_report_errors( - &self, - region_context: DefId, - outlives_env: &OutlivesEnvironment<'tcx>, - ) { - let errors = self.resolve_regions(region_context, outlives_env); + pub fn resolve_regions_and_report_errors(&self, outlives_env: &OutlivesEnvironment<'tcx>) { + let errors = self.resolve_regions(outlives_env); if !self.is_tainted_by_errors() { // As a heuristic, just skip reporting region errors @@ -1445,7 +1439,7 @@ impl<'a, 'tcx> InferCtxt<'a, 'tcx> { /// `resolve_vars_if_possible()`. pub fn unresolved_type_vars<T>(&self, value: &T) -> Option<(Ty<'tcx>, Option<Span>)> where - T: TypeFoldable<'tcx>, + T: TypeVisitable<'tcx>, { value.visit_with(&mut resolve::UnresolvedTypeFinder::new(self)).break_value() } diff --git a/compiler/rustc_infer/src/infer/nll_relate/mod.rs b/compiler/rustc_infer/src/infer/nll_relate/mod.rs index 846e7f7b921..bab4f3e9e36 100644 --- a/compiler/rustc_infer/src/infer/nll_relate/mod.rs +++ b/compiler/rustc_infer/src/infer/nll_relate/mod.rs @@ -27,8 +27,8 @@ use crate::infer::{ConstVarValue, ConstVariableValue}; use crate::infer::{TypeVariableOrigin, TypeVariableOriginKind}; use rustc_data_structures::fx::FxHashMap; use rustc_middle::ty::error::TypeError; -use rustc_middle::ty::fold::{TypeFoldable, TypeSuperFoldable, TypeVisitor}; use rustc_middle::ty::relate::{self, Relate, RelateResult, TypeRelation}; +use rustc_middle::ty::visit::{TypeSuperVisitable, TypeVisitable, TypeVisitor}; use rustc_middle::ty::{self, InferConst, Ty, TyCtxt}; use rustc_span::Span; use std::fmt::Debug; @@ -810,7 +810,7 @@ struct ScopeInstantiator<'me, 'tcx> { } impl<'me, 'tcx> TypeVisitor<'tcx> for ScopeInstantiator<'me, 'tcx> { - fn visit_binder<T: TypeFoldable<'tcx>>( + fn visit_binder<T: TypeVisitable<'tcx>>( &mut self, t: &ty::Binder<'tcx, T>, ) -> ControlFlow<Self::BreakTy> { diff --git a/compiler/rustc_infer/src/infer/opaque_types.rs b/compiler/rustc_infer/src/infer/opaque_types.rs index cc36d6a0a4f..26d689f29ee 100644 --- a/compiler/rustc_infer/src/infer/opaque_types.rs +++ b/compiler/rustc_infer/src/infer/opaque_types.rs @@ -9,7 +9,8 @@ use rustc_middle::traits::ObligationCause; use rustc_middle::ty::fold::BottomUpFolder; use rustc_middle::ty::subst::{GenericArgKind, Subst}; use rustc_middle::ty::{ - self, OpaqueHiddenType, OpaqueTypeKey, Ty, TyCtxt, TypeFoldable, TypeSuperFoldable, TypeVisitor, + self, OpaqueHiddenType, OpaqueTypeKey, Ty, TyCtxt, TypeFoldable, TypeSuperVisitable, + TypeVisitable, TypeVisitor, }; use rustc_span::Span; @@ -461,7 +462,7 @@ impl<'tcx, OP> TypeVisitor<'tcx> for ConstrainOpaqueTypeRegionVisitor<OP> where OP: FnMut(ty::Region<'tcx>), { - fn visit_binder<T: TypeFoldable<'tcx>>( + fn visit_binder<T: TypeVisitable<'tcx>>( &mut self, t: &ty::Binder<'tcx, T>, ) -> ControlFlow<Self::BreakTy> { diff --git a/compiler/rustc_infer/src/infer/outlives/components.rs b/compiler/rustc_infer/src/infer/outlives/components.rs index 5ea096f5cc2..7234660dbcd 100644 --- a/compiler/rustc_infer/src/infer/outlives/components.rs +++ b/compiler/rustc_infer/src/infer/outlives/components.rs @@ -4,7 +4,7 @@ use rustc_data_structures::sso::SsoHashSet; use rustc_middle::ty::subst::{GenericArg, GenericArgKind}; -use rustc_middle::ty::{self, Ty, TyCtxt, TypeFoldable}; +use rustc_middle::ty::{self, Ty, TyCtxt, TypeVisitable}; use smallvec::{smallvec, SmallVec}; #[derive(Debug)] diff --git a/compiler/rustc_infer/src/infer/outlives/env.rs b/compiler/rustc_infer/src/infer/outlives/env.rs index 9ddda7b92eb..b897de7315a 100644 --- a/compiler/rustc_infer/src/infer/outlives/env.rs +++ b/compiler/rustc_infer/src/infer/outlives/env.rs @@ -1,8 +1,6 @@ use crate::infer::free_regions::FreeRegionMap; use crate::infer::{GenericKind, InferCtxt}; use crate::traits::query::OutlivesBound; -use rustc_data_structures::fx::FxHashMap; -use rustc_hir as hir; use rustc_middle::ty::{self, ReEarlyBound, ReFree, ReVar, Region}; use super::explicit_outlives_bounds; @@ -31,9 +29,7 @@ pub struct OutlivesEnvironment<'tcx> { pub param_env: ty::ParamEnv<'tcx>, free_region_map: FreeRegionMap<'tcx>, - // Contains, for each body B that we are checking (that is, the fn - // item, but also any nested closures), the set of implied region - // bounds that are in scope in that particular body. + // Contains the implied region bounds in scope for our current body. // // Example: // @@ -43,24 +39,15 @@ pub struct OutlivesEnvironment<'tcx> { // } // body B0 // ``` // - // Here, for body B0, the list would be `[T: 'a]`, because we + // Here, when checking the body B0, the list would be `[T: 'a]`, because we // infer that `T` must outlive `'a` from the implied bounds on the // fn declaration. // - // For the body B1, the list would be `[T: 'a, T: 'b]`, because we + // For the body B1 however, the list would be `[T: 'a, T: 'b]`, because we // also can see that -- within the closure body! -- `T` must // outlive `'b`. This is not necessarily true outside the closure // body, since the closure may never be called. - // - // We collect this map as we descend the tree. We then use the - // results when proving outlives obligations like `T: 'x` later - // (e.g., if `T: 'x` must be proven within the body B1, then we - // know it is true if either `'a: 'x` or `'b: 'x`). - region_bound_pairs_map: FxHashMap<hir::HirId, RegionBoundPairs<'tcx>>, - - // Used to compute `region_bound_pairs_map`: contains the set of - // in-scope region-bound pairs thus far. - region_bound_pairs_accum: RegionBoundPairs<'tcx>, + region_bound_pairs: RegionBoundPairs<'tcx>, } /// "Region-bound pairs" tracks outlives relations that are known to @@ -73,8 +60,7 @@ impl<'a, 'tcx> OutlivesEnvironment<'tcx> { let mut env = OutlivesEnvironment { param_env, free_region_map: Default::default(), - region_bound_pairs_map: Default::default(), - region_bound_pairs_accum: vec![], + region_bound_pairs: Default::default(), }; env.add_outlives_bounds(None, explicit_outlives_bounds(param_env)); @@ -87,62 +73,9 @@ impl<'a, 'tcx> OutlivesEnvironment<'tcx> { &self.free_region_map } - /// Borrows current value of the `region_bound_pairs`. - pub fn region_bound_pairs_map(&self) -> &FxHashMap<hir::HirId, RegionBoundPairs<'tcx>> { - &self.region_bound_pairs_map - } - - /// This is a hack to support the old-school regionck, which - /// processes region constraints from the main function and the - /// closure together. In that context, when we enter a closure, we - /// want to be able to "save" the state of the surrounding a - /// function. We can then add implied bounds and the like from the - /// closure arguments into the environment -- these should only - /// apply in the closure body, so once we exit, we invoke - /// `pop_snapshot_post_typeck_child` to remove them. - /// - /// Example: - /// - /// ```ignore (pseudo-rust) - /// fn foo<T>() { - /// callback(for<'a> |x: &'a T| { - /// // ^^^^^^^ not legal syntax, but probably should be - /// // within this closure body, `T: 'a` holds - /// }) - /// } - /// ``` - /// - /// This "containment" of closure's effects only works so well. In - /// particular, we (intentionally) leak relationships between free - /// regions that are created by the closure's bounds. The case - /// where this is useful is when you have (e.g.) a closure with a - /// signature like `for<'a, 'b> fn(x: &'a &'b u32)` -- in this - /// case, we want to keep the relationship `'b: 'a` in the - /// free-region-map, so that later if we have to take `LUB('b, - /// 'a)` we can get the result `'b`. - /// - /// I have opted to keep **all modifications** to the - /// free-region-map, however, and not just those that concern free - /// variables bound in the closure. The latter seems more correct, - /// but it is not the existing behavior, and I could not find a - /// case where the existing behavior went wrong. In any case, it - /// seems like it'd be readily fixed if we wanted. There are - /// similar leaks around givens that seem equally suspicious, to - /// be honest. --nmatsakis - pub fn push_snapshot_pre_typeck_child(&self) -> usize { - self.region_bound_pairs_accum.len() - } - - /// See `push_snapshot_pre_typeck_child`. - pub fn pop_snapshot_post_typeck_child(&mut self, len: usize) { - self.region_bound_pairs_accum.truncate(len); - } - - /// Save the current set of region-bound pairs under the given `body_id`. - pub fn save_implied_bounds(&mut self, body_id: hir::HirId) { - let old = - self.region_bound_pairs_map.insert(body_id, self.region_bound_pairs_accum.clone()); - assert!(old.is_none()); + /// Borrows current `region_bound_pairs`. + pub fn region_bound_pairs(&self) -> &RegionBoundPairs<'tcx> { + &self.region_bound_pairs } /// Processes outlives bounds that are known to hold, whether from implied or other sources. @@ -164,11 +97,10 @@ impl<'a, 'tcx> OutlivesEnvironment<'tcx> { debug!("add_outlives_bounds: outlives_bound={:?}", outlives_bound); match outlives_bound { OutlivesBound::RegionSubParam(r_a, param_b) => { - self.region_bound_pairs_accum.push((r_a, GenericKind::Param(param_b))); + self.region_bound_pairs.push((r_a, GenericKind::Param(param_b))); } OutlivesBound::RegionSubProjection(r_a, projection_b) => { - self.region_bound_pairs_accum - .push((r_a, GenericKind::Projection(projection_b))); + self.region_bound_pairs.push((r_a, GenericKind::Projection(projection_b))); } OutlivesBound::RegionSubRegion(r_a, r_b) => { if let (ReEarlyBound(_) | ReFree(_), ReVar(vid_b)) = (r_a.kind(), r_b.kind()) { diff --git a/compiler/rustc_infer/src/infer/outlives/obligations.rs b/compiler/rustc_infer/src/infer/outlives/obligations.rs index 1c1906f3375..59cf39abe64 100644 --- a/compiler/rustc_infer/src/infer/outlives/obligations.rs +++ b/compiler/rustc_infer/src/infer/outlives/obligations.rs @@ -60,18 +60,16 @@ //! imply that `'b: 'a`. use crate::infer::outlives::components::{push_outlives_components, Component}; +use crate::infer::outlives::env::OutlivesEnvironment; use crate::infer::outlives::env::RegionBoundPairs; use crate::infer::outlives::verify::VerifyBoundCx; use crate::infer::{ self, GenericKind, InferCtxt, RegionObligation, SubregionOrigin, UndoLog, VerifyBound, }; use crate::traits::{ObligationCause, ObligationCauseCode}; -use rustc_middle::ty::subst::GenericArgKind; -use rustc_middle::ty::{self, Region, Ty, TyCtxt, TypeFoldable}; - -use rustc_data_structures::fx::FxHashMap; use rustc_data_structures::undo_log::UndoLogs; -use rustc_hir as hir; +use rustc_middle::ty::subst::GenericArgKind; +use rustc_middle::ty::{self, Region, Ty, TyCtxt, TypeVisitable}; use smallvec::smallvec; impl<'cx, 'tcx> InferCtxt<'cx, 'tcx> { @@ -80,16 +78,11 @@ impl<'cx, 'tcx> InferCtxt<'cx, 'tcx> { /// and later processed by regionck, when full type information is /// available (see `region_obligations` field for more /// information). - pub fn register_region_obligation( - &self, - body_id: hir::HirId, - obligation: RegionObligation<'tcx>, - ) { - debug!("register_region_obligation(body_id={:?}, obligation={:?})", body_id, obligation); - + #[instrument(level = "debug", skip(self))] + pub fn register_region_obligation(&self, obligation: RegionObligation<'tcx>) { let mut inner = self.inner.borrow_mut(); inner.undo_log.push(UndoLog::PushRegionObligation); - inner.region_obligations.push((body_id, obligation)); + inner.region_obligations.push(obligation); } pub fn register_region_obligation_with_cause( @@ -109,14 +102,11 @@ impl<'cx, 'tcx> InferCtxt<'cx, 'tcx> { ) }); - self.register_region_obligation( - cause.body_id, - RegionObligation { sup_type, sub_region, origin }, - ); + self.register_region_obligation(RegionObligation { sup_type, sub_region, origin }); } /// Trait queries just want to pass back type obligations "as is" - pub fn take_registered_region_obligations(&self) -> Vec<(hir::HirId, RegionObligation<'tcx>)> { + pub fn take_registered_region_obligations(&self) -> Vec<RegionObligation<'tcx>> { std::mem::take(&mut self.inner.borrow_mut().region_obligations) } @@ -144,10 +134,10 @@ impl<'cx, 'tcx> InferCtxt<'cx, 'tcx> { /// - `param_env` is the parameter environment for the enclosing function. /// - `body_id` is the body-id whose region obligations are being /// processed. - #[instrument(level = "debug", skip(self, region_bound_pairs_map))] + #[instrument(level = "debug", skip(self, region_bound_pairs))] pub fn process_registered_region_obligations( &self, - region_bound_pairs_map: &FxHashMap<hir::HirId, RegionBoundPairs<'tcx>>, + region_bound_pairs: &RegionBoundPairs<'tcx>, param_env: ty::ParamEnv<'tcx>, ) { assert!( @@ -157,7 +147,7 @@ impl<'cx, 'tcx> InferCtxt<'cx, 'tcx> { let my_region_obligations = self.take_registered_region_obligations(); - for (body_id, RegionObligation { sup_type, sub_region, origin }) in my_region_obligations { + for RegionObligation { sup_type, sub_region, origin } in my_region_obligations { debug!( "process_registered_region_obligations: sup_type={:?} sub_region={:?} origin={:?}", sup_type, sub_region, origin @@ -165,18 +155,23 @@ 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, None, param_env); - outlives.type_must_outlive(origin, sup_type, sub_region); - } else { - self.tcx.sess.delay_span_bug( - origin.span(), - &format!("no region-bound-pairs for {:?}", body_id), - ); - } + let outlives = + &mut TypeOutlives::new(self, self.tcx, ®ion_bound_pairs, None, param_env); + outlives.type_must_outlive(origin, sup_type, sub_region); } } + + pub fn check_region_obligations_and_report_errors( + &self, + outlives_env: &OutlivesEnvironment<'tcx>, + ) { + self.process_registered_region_obligations( + outlives_env.region_bound_pairs(), + outlives_env.param_env, + ); + + self.resolve_regions_and_report_errors(outlives_env) + } } /// The `TypeOutlives` struct has the job of "lowering" a `T: 'a` diff --git a/compiler/rustc_infer/src/infer/outlives/test_type_match.rs b/compiler/rustc_infer/src/infer/outlives/test_type_match.rs index 9f71ebae99e..772e297b7b4 100644 --- a/compiler/rustc_infer/src/infer/outlives/test_type_match.rs +++ b/compiler/rustc_infer/src/infer/outlives/test_type_match.rs @@ -1,7 +1,7 @@ use std::collections::hash_map::Entry; use rustc_data_structures::fx::FxHashMap; -use rustc_middle::ty::TypeFoldable; +use rustc_middle::ty::TypeVisitable; use rustc_middle::ty::{ self, error::TypeError, diff --git a/compiler/rustc_infer/src/infer/region_constraints/mod.rs b/compiler/rustc_infer/src/infer/region_constraints/mod.rs index 19f83e3377a..c5747ecf702 100644 --- a/compiler/rustc_infer/src/infer/region_constraints/mod.rs +++ b/compiler/rustc_infer/src/infer/region_constraints/mod.rs @@ -165,7 +165,7 @@ pub struct Verify<'tcx> { pub bound: VerifyBound<'tcx>, } -#[derive(Copy, Clone, PartialEq, Eq, Hash, TypeFoldable)] +#[derive(Copy, Clone, PartialEq, Eq, Hash, TypeFoldable, TypeVisitable)] pub enum GenericKind<'tcx> { Param(ty::ParamTy), Projection(ty::ProjectionTy<'tcx>), @@ -272,7 +272,7 @@ pub enum VerifyBound<'tcx> { /// } /// } /// ``` -#[derive(Debug, Copy, Clone, TypeFoldable)] +#[derive(Debug, Copy, Clone, TypeFoldable, TypeVisitable)] pub struct VerifyIfEq<'tcx> { /// Type which must match the generic `G` pub ty: Ty<'tcx>, diff --git a/compiler/rustc_infer/src/infer/resolve.rs b/compiler/rustc_infer/src/infer/resolve.rs index 1f3cb401314..a6145687429 100644 --- a/compiler/rustc_infer/src/infer/resolve.rs +++ b/compiler/rustc_infer/src/infer/resolve.rs @@ -1,8 +1,9 @@ use super::type_variable::{TypeVariableOrigin, TypeVariableOriginKind}; use super::{FixupError, FixupResult, InferCtxt, Span}; use rustc_middle::mir; -use rustc_middle::ty::fold::{FallibleTypeFolder, TypeFolder, TypeSuperFoldable, TypeVisitor}; -use rustc_middle::ty::{self, Const, InferConst, Ty, TyCtxt, TypeFoldable}; +use rustc_middle::ty::fold::{FallibleTypeFolder, TypeFolder, TypeSuperFoldable}; +use rustc_middle::ty::visit::{TypeSuperVisitable, TypeVisitor}; +use rustc_middle::ty::{self, Const, InferConst, Ty, TyCtxt, TypeFoldable, TypeVisitable}; use std::ops::ControlFlow; diff --git a/compiler/rustc_infer/src/infer/sub.rs b/compiler/rustc_infer/src/infer/sub.rs index d0c6d8d16eb..b27571275b7 100644 --- a/compiler/rustc_infer/src/infer/sub.rs +++ b/compiler/rustc_infer/src/infer/sub.rs @@ -4,8 +4,8 @@ use super::SubregionOrigin; use crate::infer::combine::ConstEquateRelation; use crate::infer::{TypeVariableOrigin, TypeVariableOriginKind}; use crate::traits::Obligation; -use rustc_middle::ty::fold::TypeFoldable; use rustc_middle::ty::relate::{Cause, Relate, RelateResult, TypeRelation}; +use rustc_middle::ty::visit::TypeVisitable; use rustc_middle::ty::TyVar; use rustc_middle::ty::{self, ToPredicate, Ty, TyCtxt}; use std::mem; diff --git a/compiler/rustc_infer/src/traits/project.rs b/compiler/rustc_infer/src/traits/project.rs index b84ed3dc689..932e597509f 100644 --- a/compiler/rustc_infer/src/traits/project.rs +++ b/compiler/rustc_infer/src/traits/project.rs @@ -20,7 +20,7 @@ pub struct MismatchedProjectionTypes<'tcx> { pub err: ty::error::TypeError<'tcx>, } -#[derive(Clone, TypeFoldable)] +#[derive(Clone, TypeFoldable, TypeVisitable)] pub struct Normalized<'tcx, T> { pub value: T, pub obligations: Vec<PredicateObligation<'tcx>>, diff --git a/compiler/rustc_infer/src/traits/structural_impls.rs b/compiler/rustc_infer/src/traits/structural_impls.rs index 82ee4bb29e8..573d2d1e330 100644 --- a/compiler/rustc_infer/src/traits/structural_impls.rs +++ b/compiler/rustc_infer/src/traits/structural_impls.rs @@ -1,7 +1,8 @@ use crate::traits; use crate::traits::project::Normalized; use rustc_middle::ty; -use rustc_middle::ty::fold::{FallibleTypeFolder, TypeFoldable, TypeVisitor}; +use rustc_middle::ty::fold::{FallibleTypeFolder, TypeFoldable}; +use rustc_middle::ty::visit::{TypeVisitable, TypeVisitor}; use std::fmt; use std::ops::ControlFlow; @@ -68,7 +69,9 @@ impl<'tcx, O: TypeFoldable<'tcx>> TypeFoldable<'tcx> for traits::Obligation<'tcx param_env: self.param_env.try_fold_with(folder)?, }) } +} +impl<'tcx, O: TypeVisitable<'tcx>> TypeVisitable<'tcx> for traits::Obligation<'tcx, O> { fn visit_with<V: TypeVisitor<'tcx>>(&self, visitor: &mut V) -> ControlFlow<V::BreakTy> { self.predicate.visit_with(visitor)?; self.param_env.visit_with(visitor) diff --git a/compiler/rustc_interface/src/passes.rs b/compiler/rustc_interface/src/passes.rs index 502afa493fe..5b263aded9c 100644 --- a/compiler/rustc_interface/src/passes.rs +++ b/compiler/rustc_interface/src/passes.rs @@ -972,6 +972,7 @@ fn analysis(tcx: TyCtxt<'_>, (): ()) -> Result<()> { if !tcx.sess.opts.debugging_opts.thir_unsafeck { rustc_mir_transform::check_unsafety::check_unsafety(tcx, def_id); } + tcx.ensure().has_ffi_unwind_calls(def_id); if tcx.hir().body_const_context(def_id).is_some() { tcx.ensure() diff --git a/compiler/rustc_interface/src/util.rs b/compiler/rustc_interface/src/util.rs index fb9258eb4a9..8796ad5a33c 100644 --- a/compiler/rustc_interface/src/util.rs +++ b/compiler/rustc_interface/src/util.rs @@ -10,7 +10,7 @@ use rustc_errors::registry::Registry; use rustc_middle::ty::tls; use rustc_parse::validate_attr; #[cfg(parallel_compiler)] -use rustc_query_impl::QueryCtxt; +use rustc_query_impl::{QueryContext, QueryCtxt}; use rustc_session as session; use rustc_session::config::CheckCfg; use rustc_session::config::{self, CrateType}; @@ -166,20 +166,12 @@ pub fn run_in_thread_pool_with_globals<F: FnOnce() -> R + Send, R: Send>( unsafe fn handle_deadlock() { let registry = rustc_rayon_core::Registry::current(); - let context = tls::get_tlv(); - assert!(context != 0); - rustc_data_structures::sync::assert_sync::<tls::ImplicitCtxt<'_, '_>>(); - let icx: &tls::ImplicitCtxt<'_, '_> = &*(context as *const tls::ImplicitCtxt<'_, '_>); - - let session_globals = rustc_span::with_session_globals(|sg| sg as *const _); - let session_globals = &*session_globals; - thread::spawn(move || { - tls::enter_context(icx, |_| { - rustc_span::set_session_globals_then(session_globals, || { - tls::with(|tcx| QueryCtxt::from_tcx(tcx).deadlock(®istry)) - }) - }); + let query_map = tls::with(|tcx| { + QueryCtxt::from_tcx(tcx) + .try_collect_active_jobs() + .expect("active jobs shouldn't be locked in deadlock handler") }); + thread::spawn(move || rustc_query_impl::deadlock(query_map, ®istry)); } #[cfg(parallel_compiler)] diff --git a/compiler/rustc_lint/Cargo.toml b/compiler/rustc_lint/Cargo.toml index fab60b6f609..7c0f2c440d5 100644 --- a/compiler/rustc_lint/Cargo.toml +++ b/compiler/rustc_lint/Cargo.toml @@ -22,3 +22,4 @@ rustc_trait_selection = { path = "../rustc_trait_selection" } rustc_parse_format = { path = "../rustc_parse_format" } rustc_infer = { path = "../rustc_infer" } rustc_type_ir = { path = "../rustc_type_ir" } +rustc_macros = { path = "../rustc_macros" } diff --git a/compiler/rustc_lint/src/array_into_iter.rs b/compiler/rustc_lint/src/array_into_iter.rs index b33ab40eb39..121fefdc620 100644 --- a/compiler/rustc_lint/src/array_into_iter.rs +++ b/compiler/rustc_lint/src/array_into_iter.rs @@ -1,5 +1,5 @@ use crate::{LateContext, LateLintPass, LintContext}; -use rustc_errors::Applicability; +use rustc_errors::{fluent, Applicability}; use rustc_hir as hir; use rustc_middle::ty; use rustc_middle::ty::adjustment::{Adjust, Adjustment}; @@ -120,31 +120,30 @@ impl<'tcx> LateLintPass<'tcx> for ArrayIntoIter { _ => bug!("array type coerced to something other than array or slice"), }; cx.struct_span_lint(ARRAY_INTO_ITER, call.ident.span, |lint| { - let mut diag = lint.build(&format!( - "this method call resolves to `<&{} as IntoIterator>::into_iter` \ - (due to backwards compatibility), \ - but will resolve to <{} as IntoIterator>::into_iter in Rust 2021", - target, target, - )); + let mut diag = lint.build(fluent::lint::array_into_iter); + diag.set_arg("target", target); diag.span_suggestion( call.ident.span, - "use `.iter()` instead of `.into_iter()` to avoid ambiguity", + fluent::lint::use_iter_suggestion, "iter", Applicability::MachineApplicable, ); if self.for_expr_span == expr.span { diag.span_suggestion( receiver_arg.span.shrink_to_hi().to(expr.span.shrink_to_hi()), - "or remove `.into_iter()` to iterate by value", + fluent::lint::remove_into_iter_suggestion, "", Applicability::MaybeIncorrect, ); } else if receiver_ty.is_array() { diag.multipart_suggestion( - "or use `IntoIterator::into_iter(..)` instead of `.into_iter()` to explicitly iterate by value", + fluent::lint::use_explicit_into_iter_suggestion, vec![ (expr.span.shrink_to_lo(), "IntoIterator::into_iter(".into()), - (receiver_arg.span.shrink_to_hi().to(expr.span.shrink_to_hi()), ")".into()), + ( + receiver_arg.span.shrink_to_hi().to(expr.span.shrink_to_hi()), + ")".into(), + ), ], Applicability::MaybeIncorrect, ); diff --git a/compiler/rustc_lint/src/builtin.rs b/compiler/rustc_lint/src/builtin.rs index 8266f1566c4..363978926a7 100644 --- a/compiler/rustc_lint/src/builtin.rs +++ b/compiler/rustc_lint/src/builtin.rs @@ -31,14 +31,17 @@ use rustc_ast::{self as ast, *}; use rustc_ast_pretty::pprust::{self, expr_to_string}; use rustc_data_structures::fx::{FxHashMap, FxHashSet}; use rustc_data_structures::stack::ensure_sufficient_stack; -use rustc_errors::{Applicability, Diagnostic, DiagnosticStyledString, MultiSpan}; +use rustc_errors::{ + fluent, Applicability, Diagnostic, DiagnosticMessage, DiagnosticStyledString, + LintDiagnosticBuilder, MultiSpan, +}; use rustc_feature::{deprecated_attributes, AttributeGate, BuiltinAttribute, GateIssue, Stability}; use rustc_hir as hir; use rustc_hir::def::{DefKind, Res}; use rustc_hir::def_id::{DefId, LocalDefId, LocalDefIdSet, CRATE_DEF_ID}; use rustc_hir::{ForeignItemKind, GenericParamKind, HirId, PatKind, PredicateOrigin}; use rustc_index::vec::Idx; -use rustc_middle::lint::{in_external_macro, LintDiagnosticBuilder}; +use rustc_middle::lint::in_external_macro; use rustc_middle::ty::layout::{LayoutError, LayoutOf}; use rustc_middle::ty::print::with_no_trimmed_paths; use rustc_middle::ty::subst::GenericArgKind; @@ -99,13 +102,12 @@ impl EarlyLintPass for WhileTrue { if let ast::ExprKind::Lit(ref lit) = pierce_parens(cond).kind { if let ast::LitKind::Bool(true) = lit.kind { if !lit.span.from_expansion() { - let msg = "denote infinite loops with `loop { ... }`"; let condition_span = e.span.with_hi(cond.span.hi()); cx.struct_span_lint(WHILE_TRUE, condition_span, |lint| { - lint.build(msg) + lint.build(fluent::lint::builtin_while_true) .span_suggestion_short( condition_span, - "use `loop`", + fluent::lint::suggestion, format!( "{}loop", label.map_or_else(String::new, |label| format!( @@ -156,7 +158,7 @@ impl BoxPointers { if let GenericArgKind::Type(leaf_ty) = leaf.unpack() { if leaf_ty.is_box() { cx.struct_span_lint(BOX_POINTERS, span, |lint| { - lint.build(&format!("type uses owned (Box type) pointers: {}", ty)).emit(); + lint.build(fluent::lint::builtin_box_pointers).set_arg("ty", ty).emit(); }); } } @@ -257,26 +259,26 @@ impl<'tcx> LateLintPass<'tcx> for NonShorthandFieldPatterns { == Some(cx.tcx.field_index(fieldpat.hir_id, cx.typeck_results())) { cx.struct_span_lint(NON_SHORTHAND_FIELD_PATTERNS, fieldpat.span, |lint| { - let mut err = lint - .build(&format!("the `{}:` in this pattern is redundant", ident)); let binding = match binding_annot { hir::BindingAnnotation::Unannotated => None, hir::BindingAnnotation::Mutable => Some("mut"), hir::BindingAnnotation::Ref => Some("ref"), hir::BindingAnnotation::RefMut => Some("ref mut"), }; - let ident = if let Some(binding) = binding { + let suggested_ident = if let Some(binding) = binding { format!("{} {}", binding, ident) } else { ident.to_string() }; - err.span_suggestion( - fieldpat.span, - "use shorthand field pattern", - ident, - Applicability::MachineApplicable, - ); - err.emit(); + lint.build(fluent::lint::builtin_non_shorthand_field_patterns) + .set_arg("ident", ident.clone()) + .span_suggestion( + fieldpat.span, + fluent::lint::suggestion, + suggested_ident, + Applicability::MachineApplicable, + ) + .emit(); }); } } @@ -327,26 +329,25 @@ impl UnsafeCode { cx.struct_span_lint(UNSAFE_CODE, span, decorate); } - fn report_overridden_symbol_name(&self, cx: &EarlyContext<'_>, span: Span, msg: &str) { + fn report_overridden_symbol_name( + &self, + cx: &EarlyContext<'_>, + span: Span, + msg: DiagnosticMessage, + ) { self.report_unsafe(cx, span, |lint| { - lint.build(msg) - .note( - "the linker's behavior with multiple libraries exporting duplicate symbol \ - names is undefined and Rust cannot provide guarantees when you manually \ - override them", - ) - .emit(); + lint.build(msg).note(fluent::lint::builtin_overridden_symbol_name).emit(); }) } - fn report_overridden_symbol_section(&self, cx: &EarlyContext<'_>, span: Span, msg: &str) { + fn report_overridden_symbol_section( + &self, + cx: &EarlyContext<'_>, + span: Span, + msg: DiagnosticMessage, + ) { self.report_unsafe(cx, span, |lint| { - lint.build(msg) - .note( - "the program's behavior with overridden link sections on items is unpredictable \ - and Rust cannot provide guarantees when you manually override them", - ) - .emit(); + lint.build(msg).note(fluent::lint::builtin_overridden_symbol_section).emit(); }) } } @@ -355,12 +356,7 @@ impl EarlyLintPass for UnsafeCode { fn check_attribute(&mut self, cx: &EarlyContext<'_>, attr: &ast::Attribute) { if attr.has_name(sym::allow_internal_unsafe) { self.report_unsafe(cx, attr.span, |lint| { - lint.build( - "`allow_internal_unsafe` allows defining \ - macros using unsafe without triggering \ - the `unsafe_code` lint at their call site", - ) - .emit(); + lint.build(fluent::lint::builtin_allow_internal_unsafe).emit(); }); } } @@ -370,7 +366,7 @@ impl EarlyLintPass for UnsafeCode { // Don't warn about generated blocks; that'll just pollute the output. if blk.rules == ast::BlockCheckMode::Unsafe(ast::UserProvided) { self.report_unsafe(cx, blk.span, |lint| { - lint.build("usage of an `unsafe` block").emit(); + lint.build(fluent::lint::builtin_unsafe_block).emit(); }); } } @@ -380,12 +376,12 @@ impl EarlyLintPass for UnsafeCode { match it.kind { ast::ItemKind::Trait(box ast::Trait { unsafety: ast::Unsafe::Yes(_), .. }) => self .report_unsafe(cx, it.span, |lint| { - lint.build("declaration of an `unsafe` trait").emit(); + lint.build(fluent::lint::builtin_unsafe_trait).emit(); }), ast::ItemKind::Impl(box ast::Impl { unsafety: ast::Unsafe::Yes(_), .. }) => self .report_unsafe(cx, it.span, |lint| { - lint.build("implementation of an `unsafe` trait").emit(); + lint.build(fluent::lint::builtin_unsafe_impl).emit(); }), ast::ItemKind::Fn(..) => { @@ -393,7 +389,7 @@ impl EarlyLintPass for UnsafeCode { self.report_overridden_symbol_name( cx, attr.span, - "declaration of a `no_mangle` function", + fluent::lint::builtin_no_mangle_fn, ); } @@ -401,7 +397,7 @@ impl EarlyLintPass for UnsafeCode { self.report_overridden_symbol_name( cx, attr.span, - "declaration of a function with `export_name`", + fluent::lint::builtin_export_name_fn, ); } @@ -409,7 +405,7 @@ impl EarlyLintPass for UnsafeCode { self.report_overridden_symbol_section( cx, attr.span, - "declaration of a function with `link_section`", + fluent::lint::builtin_link_section_fn, ); } } @@ -419,7 +415,7 @@ impl EarlyLintPass for UnsafeCode { self.report_overridden_symbol_name( cx, attr.span, - "declaration of a `no_mangle` static", + fluent::lint::builtin_no_mangle_static, ); } @@ -427,7 +423,7 @@ impl EarlyLintPass for UnsafeCode { self.report_overridden_symbol_name( cx, attr.span, - "declaration of a static with `export_name`", + fluent::lint::builtin_export_name_static, ); } @@ -435,7 +431,7 @@ impl EarlyLintPass for UnsafeCode { self.report_overridden_symbol_section( cx, attr.span, - "declaration of a static with `link_section`", + fluent::lint::builtin_link_section_static, ); } } @@ -450,14 +446,14 @@ impl EarlyLintPass for UnsafeCode { self.report_overridden_symbol_name( cx, attr.span, - "declaration of a `no_mangle` method", + fluent::lint::builtin_no_mangle_method, ); } if let Some(attr) = cx.sess().find_by_name(&it.attrs, sym::export_name) { self.report_overridden_symbol_name( cx, attr.span, - "declaration of a method with `export_name`", + fluent::lint::builtin_export_name_method, ); } } @@ -475,9 +471,9 @@ impl EarlyLintPass for UnsafeCode { { let msg = match ctxt { FnCtxt::Foreign => return, - FnCtxt::Free => "declaration of an `unsafe` function", - FnCtxt::Assoc(_) if body.is_none() => "declaration of an `unsafe` method", - FnCtxt::Assoc(_) => "implementation of an `unsafe` method", + FnCtxt::Free => fluent::lint::builtin_decl_unsafe_fn, + FnCtxt::Assoc(_) if body.is_none() => fluent::lint::builtin_decl_unsafe_method, + FnCtxt::Assoc(_) => fluent::lint::builtin_impl_unsafe_method, }; self.report_unsafe(cx, span, |lint| { lint.build(msg).emit(); @@ -587,7 +583,10 @@ impl MissingDoc { MISSING_DOCS, cx.tcx.sess.source_map().guess_head_span(sp), |lint| { - lint.build(&format!("missing documentation for {} {}", article, desc)).emit(); + lint.build(fluent::lint::builtin_missing_doc) + .set_arg("article", article) + .set_arg("desc", desc) + .emit(); }, ); } @@ -783,11 +782,7 @@ impl<'tcx> LateLintPass<'tcx> for MissingCopyImplementations { .is_ok() { cx.struct_span_lint(MISSING_COPY_IMPLEMENTATIONS, item.span, |lint| { - lint.build( - "type could implement `Copy`; consider adding `impl \ - Copy`", - ) - .emit(); + lint.build(fluent::lint::builtin_missing_copy_impl).emit(); }) } } @@ -863,12 +858,9 @@ impl<'tcx> LateLintPass<'tcx> for MissingDebugImplementations { if !self.impling_types.as_ref().unwrap().contains(&item.def_id) { cx.struct_span_lint(MISSING_DEBUG_IMPLEMENTATIONS, item.span, |lint| { - lint.build(&format!( - "type does not implement `{}`; consider adding `#[derive(Debug)]` \ - or a manual implementation", - cx.tcx.def_path_str(debug) - )) - .emit(); + lint.build(fluent::lint::builtin_missing_debug_impl) + .set_arg("debug", cx.tcx.def_path_str(debug)) + .emit(); }); } } @@ -946,18 +938,14 @@ impl EarlyLintPass for AnonymousParameters { ("<type>", Applicability::HasPlaceholders) }; - lint.build( - "anonymous parameters are deprecated and will be \ - removed in the next edition", - ) - .span_suggestion( - arg.pat.span, - "try naming the parameter or explicitly \ - ignoring it", - format!("_: {}", ty_snip), - appl, - ) - .emit(); + lint.build(fluent::lint::builtin_anonymous_params) + .span_suggestion( + arg.pat.span, + fluent::lint::suggestion, + format!("_: {}", ty_snip), + appl, + ) + .emit(); }) } } @@ -982,24 +970,6 @@ impl DeprecatedAttr { } } -fn lint_deprecated_attr( - cx: &EarlyContext<'_>, - attr: &ast::Attribute, - msg: &str, - suggestion: Option<&str>, -) { - cx.struct_span_lint(DEPRECATED, attr.span, |lint| { - lint.build(msg) - .span_suggestion_short( - attr.span, - suggestion.unwrap_or("remove this attribute"), - "", - Applicability::MachineApplicable, - ) - .emit(); - }) -} - impl EarlyLintPass for DeprecatedAttr { fn check_attribute(&mut self, cx: &EarlyContext<'_>, attr: &ast::Attribute) { for BuiltinAttribute { name, gate, .. } in &self.depr_attrs { @@ -1011,17 +981,38 @@ impl EarlyLintPass for DeprecatedAttr { _, ) = gate { - let msg = - format!("use of deprecated attribute `{}`: {}. See {}", name, reason, link); - lint_deprecated_attr(cx, attr, &msg, suggestion); + cx.struct_span_lint(DEPRECATED, attr.span, |lint| { + // FIXME(davidtwco) translatable deprecated attr + lint.build(fluent::lint::builtin_deprecated_attr_link) + .set_arg("name", name) + .set_arg("reason", reason) + .set_arg("link", link) + .span_suggestion_short( + attr.span, + suggestion.map(|s| s.into()).unwrap_or( + fluent::lint::builtin_deprecated_attr_default_suggestion, + ), + "", + Applicability::MachineApplicable, + ) + .emit(); + }); } return; } } if attr.has_name(sym::no_start) || attr.has_name(sym::crate_id) { - let path_str = pprust::path_to_string(&attr.get_normal_item().path); - let msg = format!("use of deprecated attribute `{}`: no longer used.", path_str); - lint_deprecated_attr(cx, attr, &msg, None); + cx.struct_span_lint(DEPRECATED, attr.span, |lint| { + lint.build(fluent::lint::builtin_deprecated_attr_used) + .set_arg("name", pprust::path_to_string(&attr.get_normal_item().path)) + .span_suggestion_short( + attr.span, + fluent::lint::builtin_deprecated_attr_default_suggestion, + "", + Applicability::MachineApplicable, + ) + .emit(); + }); } } } @@ -1049,17 +1040,15 @@ fn warn_if_doc(cx: &EarlyContext<'_>, node_span: Span, node_kind: &str, attrs: & if is_doc_comment || attr.has_name(sym::doc) { cx.struct_span_lint(UNUSED_DOC_COMMENTS, span, |lint| { - let mut err = lint.build("unused doc comment"); - err.span_label( - node_span, - format!("rustdoc does not generate documentation for {}", node_kind), - ); + let mut err = lint.build(fluent::lint::builtin_unused_doc_comment); + err.set_arg("kind", node_kind); + err.span_label(node_span, fluent::lint::label); match attr.kind { AttrKind::DocComment(CommentKind::Line, _) | AttrKind::Normal(..) => { - err.help("use `//` for a plain comment"); + err.help(fluent::lint::plain_help); } AttrKind::DocComment(CommentKind::Block, _) => { - err.help("use `/* */` for a plain comment"); + err.help(fluent::lint::block_help); } } err.emit(); @@ -1098,12 +1087,12 @@ impl EarlyLintPass for UnusedDocComment { } fn check_block(&mut self, cx: &EarlyContext<'_>, block: &ast::Block) { - warn_if_doc(cx, block.span, "block", &block.attrs()); + warn_if_doc(cx, block.span, "blocks", &block.attrs()); } fn check_item(&mut self, cx: &EarlyContext<'_>, item: &ast::Item) { if let ast::ItemKind::ForeignMod(_) = item.kind { - warn_if_doc(cx, item.span, "extern block", &item.attrs); + warn_if_doc(cx, item.span, "extern blocks", &item.attrs); } } } @@ -1178,10 +1167,10 @@ impl<'tcx> LateLintPass<'tcx> for InvalidNoMangleItems { GenericParamKind::Lifetime { .. } => {} GenericParamKind::Type { .. } | GenericParamKind::Const { .. } => { cx.struct_span_lint(NO_MANGLE_GENERIC_ITEMS, span, |lint| { - lint.build("functions generic over types or consts must be mangled") + lint.build(fluent::lint::builtin_no_mangle_generic) .span_suggestion_short( no_mangle_attr.span, - "remove this attribute", + fluent::lint::suggestion, "", // Use of `#[no_mangle]` suggests FFI intent; correct // fix may be to monomorphize source by hand @@ -1205,8 +1194,7 @@ impl<'tcx> LateLintPass<'tcx> for InvalidNoMangleItems { // Const items do not refer to a particular location in memory, and therefore // don't have anything to attach a symbol to cx.struct_span_lint(NO_MANGLE_CONST_ITEMS, it.span, |lint| { - let msg = "const items should never be `#[no_mangle]`"; - let mut err = lint.build(msg); + let mut err = lint.build(fluent::lint::builtin_const_no_mangle); // account for "pub const" (#45562) let start = cx @@ -1220,7 +1208,7 @@ impl<'tcx> LateLintPass<'tcx> for InvalidNoMangleItems { let const_span = it.span.with_hi(BytePos(it.span.lo().0 + start + 5)); err.span_suggestion( const_span, - "try a static value", + fluent::lint::suggestion, "pub static", Applicability::MachineApplicable, ); @@ -1285,10 +1273,8 @@ impl<'tcx> LateLintPass<'tcx> for MutableTransmutes { get_transmute_from_to(cx, expr).map(|(ty1, ty2)| (ty1.kind(), ty2.kind())) { if to_mt == hir::Mutability::Mut && from_mt == hir::Mutability::Not { - let msg = "transmuting &T to &mut T is undefined behavior, \ - even if the reference is unused, consider instead using an UnsafeCell"; cx.struct_span_lint(MUTABLE_TRANSMUTES, expr.span, |lint| { - lint.build(msg).emit(); + lint.build(fluent::lint::builtin_mutable_transmutes).emit(); }); } } @@ -1338,7 +1324,7 @@ impl<'tcx> LateLintPass<'tcx> for UnstableFeatures { if let Some(items) = attr.meta_item_list() { for item in items { cx.struct_span_lint(UNSTABLE_FEATURES, item.span(), |lint| { - lint.build("unstable feature").emit(); + lint.build(fluent::lint::builtin_unstable_features).emit(); }); } } @@ -1400,16 +1386,17 @@ impl UnreachablePub { } let def_span = cx.tcx.sess.source_map().guess_head_span(span); cx.struct_span_lint(UNREACHABLE_PUB, def_span, |lint| { - let mut err = lint.build(&format!("unreachable `pub` {}", what)); + let mut err = lint.build(fluent::lint::builtin_unreachable_pub); + err.set_arg("what", what); err.span_suggestion( vis_span, - "consider restricting its visibility", + fluent::lint::suggestion, "pub(crate)", applicability, ); if exportable { - err.help("or consider exporting it for use by other crates"); + err.help(fluent::lint::help); } err.emit(); }); @@ -1513,11 +1500,7 @@ impl TypeAliasBounds { impl Visitor<'_> for WalkAssocTypes<'_> { fn visit_qpath(&mut self, qpath: &hir::QPath<'_>, id: hir::HirId, span: Span) { if TypeAliasBounds::is_type_variable_assoc(qpath) { - self.err.span_help( - span, - "use fully disambiguated paths (i.e., `<T as Trait>::Assoc`) to refer to \ - associated types in type aliases", - ); + self.err.span_help(span, fluent::lint::builtin_type_alias_bounds_help); } intravisit::walk_qpath(self, qpath, id, span) } @@ -1561,11 +1544,11 @@ impl<'tcx> LateLintPass<'tcx> for TypeAliasBounds { let mut suggested_changing_assoc_types = false; if !where_spans.is_empty() { cx.lint(TYPE_ALIAS_BOUNDS, |lint| { - let mut err = lint.build("where clauses are not enforced in type aliases"); + let mut err = lint.build(fluent::lint::builtin_type_alias_where_clause); err.set_span(where_spans); err.span_suggestion( type_alias_generics.where_clause_span, - "the clause will not be checked when the type alias is used, and should be removed", + fluent::lint::suggestion, "", Applicability::MachineApplicable, ); @@ -1579,11 +1562,10 @@ impl<'tcx> LateLintPass<'tcx> for TypeAliasBounds { if !inline_spans.is_empty() { cx.lint(TYPE_ALIAS_BOUNDS, |lint| { - let mut err = - lint.build("bounds on generic parameters are not enforced in type aliases"); + let mut err = lint.build(fluent::lint::builtin_type_alias_generic_bounds); err.set_span(inline_spans); err.multipart_suggestion( - "the bound will not be checked when the type alias is used, and should be removed", + fluent::lint::suggestion, inline_sugg, Applicability::MachineApplicable, ); @@ -1664,7 +1646,7 @@ declare_lint_pass!( impl<'tcx> LateLintPass<'tcx> for TrivialConstraints { fn check_item(&mut self, cx: &LateContext<'tcx>, item: &'tcx hir::Item<'tcx>) { - use rustc_middle::ty::fold::TypeFoldable; + use rustc_middle::ty::visit::TypeVisitable; use rustc_middle::ty::PredicateKind::*; if cx.tcx.features().trivial_bounds { @@ -1690,12 +1672,10 @@ impl<'tcx> LateLintPass<'tcx> for TrivialConstraints { }; if predicate.is_global() { cx.struct_span_lint(TRIVIAL_BOUNDS, span, |lint| { - lint.build(&format!( - "{} bound {} does not depend on any type \ - or lifetime parameters", - predicate_kind_name, predicate - )) - .emit(); + lint.build(fluent::lint::builtin_trivial_bounds) + .set_arg("predicate_kind_name", predicate_kind_name) + .set_arg("predicate", predicate) + .emit(); }); } } @@ -1796,8 +1776,8 @@ impl EarlyLintPass for EllipsisInclusiveRangePatterns { }; if let Some((start, end, join)) = endpoints { - let msg = "`...` range patterns are deprecated"; - let suggestion = "use `..=` for an inclusive range"; + let msg = fluent::lint::builtin_ellipsis_inclusive_range_patterns; + let suggestion = fluent::lint::suggestion; if parenthesise { self.node_id = Some(pat.id); let end = expr_to_string(&end); @@ -1806,8 +1786,11 @@ impl EarlyLintPass for EllipsisInclusiveRangePatterns { None => format!("&(..={})", end), }; if join.edition() >= Edition::Edition2021 { - let mut err = - rustc_errors::struct_span_err!(cx.sess(), pat.span, E0783, "{}", msg,); + let mut err = cx.sess().struct_span_err_with_code( + pat.span, + msg, + rustc_errors::error_code!(E0783), + ); err.span_suggestion( pat.span, suggestion, @@ -1830,8 +1813,11 @@ impl EarlyLintPass for EllipsisInclusiveRangePatterns { } else { let replace = "..="; if join.edition() >= Edition::Edition2021 { - let mut err = - rustc_errors::struct_span_err!(cx.sess(), pat.span, E0783, "{}", msg,); + let mut err = cx.sess().struct_span_err_with_code( + pat.span, + msg, + rustc_errors::error_code!(E0783), + ); err.span_suggestion_short( join, suggestion, @@ -1930,7 +1916,7 @@ impl<'tcx> LateLintPass<'tcx> for UnnameableTestItems { let attrs = cx.tcx.hir().attrs(it.hir_id()); if let Some(attr) = cx.sess().find_by_name(attrs, sym::rustc_test_marker) { cx.struct_span_lint(UNNAMEABLE_TEST_ITEMS, attr.span, |lint| { - lint.build("cannot test inner items").emit(); + lint.build(fluent::lint::builtin_unnameable_test_items).emit(); }); } } @@ -2048,10 +2034,12 @@ impl KeywordIdents { } cx.struct_span_lint(KEYWORD_IDENTS, ident.span, |lint| { - lint.build(&format!("`{}` is a keyword in the {} edition", ident, next_edition)) + lint.build(fluent::lint::builtin_keyword_idents) + .set_arg("kw", ident.clone()) + .set_arg("next", next_edition) .span_suggestion( ident.span, - "you can use a raw identifier to stay compatible", + fluent::lint::suggestion, format!("r#{}", ident), Applicability::MachineApplicable, ) @@ -2301,13 +2289,10 @@ impl<'tcx> LateLintPass<'tcx> for ExplicitOutlivesRequirements { if !lint_spans.is_empty() { cx.struct_span_lint(EXPLICIT_OUTLIVES_REQUIREMENTS, lint_spans.clone(), |lint| { - lint.build("outlives requirements can be inferred") + lint.build(fluent::lint::builtin_explicit_outlives) + .set_arg("count", bound_count) .multipart_suggestion( - if bound_count == 1 { - "remove this bound" - } else { - "remove these bounds" - }, + fluent::lint::suggestion, lint_spans .into_iter() .map(|span| (span, String::new())) @@ -2363,23 +2348,14 @@ impl EarlyLintPass for IncompleteFeatures { .filter(|(&name, _)| features.incomplete(name)) .for_each(|(&name, &span)| { cx.struct_span_lint(INCOMPLETE_FEATURES, span, |lint| { - let mut builder = lint.build(&format!( - "the feature `{}` is incomplete and may not be safe to use \ - and/or cause compiler crashes", - name, - )); + let mut builder = lint.build(fluent::lint::builtin_incomplete_features); + builder.set_arg("name", name); if let Some(n) = rustc_feature::find_feature_issue(name, GateIssue::Language) { - builder.note(&format!( - "see issue #{} <https://github.com/rust-lang/rust/issues/{}> \ - for more information", - n, n, - )); + builder.set_arg("n", n); + builder.note(fluent::lint::note); } if HAS_MIN_FEATURES.contains(&name) { - builder.help(&format!( - "consider using `min_{}` instead, which is more stable and complete", - name, - )); + builder.help(fluent::lint::help); } builder.emit(); }) @@ -2620,6 +2596,7 @@ impl<'tcx> LateLintPass<'tcx> for InvalidValue { if let Some((msg, span)) = with_no_trimmed_paths!(ty_find_init_error(cx, conjured_ty, init)) { + // FIXME(davidtwco): make translatable cx.struct_span_lint(INVALID_VALUE, expr.span, |lint| { let mut err = lint.build(&format!( "the type `{}` does not permit {}", @@ -2996,23 +2973,19 @@ impl<'tcx> LateLintPass<'tcx> for ClashingExternDeclarations { let mut found_str = DiagnosticStyledString::new(); found_str.push(this_decl_ty.fn_sig(tcx).to_string(), true); - lint.build(&format!( - "`{}` redeclare{} with a different signature", - this_fi.ident.name, - if orig.get_name() == this_fi.ident.name { - "d".to_string() - } else { - format!("s `{}`", orig.get_name()) - } - )) + lint.build(if orig.get_name() == this_fi.ident.name { + fluent::lint::builtin_clashing_extern_same_name + } else { + fluent::lint::builtin_clashing_extern_diff_name + }) + .set_arg("this_fi", this_fi.ident.name) + .set_arg("orig", orig.get_name()) .span_label( get_relevant_span(orig_fi), - &format!("`{}` previously declared here", orig.get_name()), - ) - .span_label( - get_relevant_span(this_fi), - "this signature doesn't match the previous declaration", + fluent::lint::previous_decl_label, ) + .span_label(get_relevant_span(this_fi), fluent::lint::mismatch_label) + // FIXME(davidtwco): translatable expected/found .note_expected_found(&"", expected_str, &"", found_str) .emit(); }, @@ -3096,8 +3069,8 @@ impl<'tcx> LateLintPass<'tcx> for DerefNullPtr { if let rustc_hir::ExprKind::Unary(rustc_hir::UnOp::Deref, expr_deref) = expr.kind { if is_null_ptr(cx, expr_deref) { cx.struct_span_lint(DEREF_NULLPTR, expr.span, |lint| { - let mut err = lint.build("dereferencing a null pointer"); - err.span_label(expr.span, "this code causes undefined behavior when executed"); + let mut err = lint.build(fluent::lint::builtin_deref_nullptr); + err.span_label(expr.span, fluent::lint::label); err.emit(); }); } @@ -3210,9 +3183,7 @@ impl<'tcx> LateLintPass<'tcx> for NamedAsmLabels { NAMED_ASM_LABELS, Some(target_spans), |diag| { - let mut err = - diag.build("avoid using named labels in inline assembly"); - err.emit(); + diag.build(fluent::lint::builtin_asm_labels).emit(); }, BuiltinLintDiagnostics::NamedAsmLabel( "only local labels of the form `<number>:` should be used in inline asm" diff --git a/compiler/rustc_lint/src/context.rs b/compiler/rustc_lint/src/context.rs index eeb66f2d738..83328093e9f 100644 --- a/compiler/rustc_lint/src/context.rs +++ b/compiler/rustc_lint/src/context.rs @@ -22,12 +22,13 @@ use rustc_ast::util::unicode::TEXT_FLOW_CONTROL_CHARS; use rustc_data_structures::fx::FxHashMap; use rustc_data_structures::sync; use rustc_errors::{add_elided_lifetime_in_path_suggestion, struct_span_err}; -use rustc_errors::{Applicability, MultiSpan, SuggestionStyle}; +use rustc_errors::{ + Applicability, DecorateLint, LintDiagnosticBuilder, MultiSpan, SuggestionStyle, +}; use rustc_hir as hir; use rustc_hir::def::Res; use rustc_hir::def_id::{CrateNum, DefId}; use rustc_hir::definitions::{DefPathData, DisambiguatedDefPathData}; -use rustc_middle::lint::LintDiagnosticBuilder; use rustc_middle::middle::privacy::AccessLevels; use rustc_middle::middle::stability; use rustc_middle::ty::layout::{LayoutError, LayoutOfHelpers, TyAndLayout}; @@ -871,6 +872,17 @@ pub trait LintContext: Sized { decorate: impl for<'a> FnOnce(LintDiagnosticBuilder<'a, ()>), ); + /// Emit a lint at `span` from a lint struct (some type that implements `DecorateLint`, + /// typically generated by `#[derive(LintDiagnostic)]`). + fn emit_spanned_lint<S: Into<MultiSpan>>( + &self, + lint: &'static Lint, + span: S, + decorator: impl for<'a> DecorateLint<'a, ()>, + ) { + self.lookup(lint, Some(span), |diag| decorator.decorate_lint(diag)); + } + fn struct_span_lint<S: Into<MultiSpan>>( &self, lint: &'static Lint, @@ -879,6 +891,13 @@ pub trait LintContext: Sized { ) { self.lookup(lint, Some(span), decorate); } + + /// Emit a lint from a lint struct (some type that implements `DecorateLint`, typically + /// generated by `#[derive(LintDiagnostic)]`). + fn emit_lint(&self, lint: &'static Lint, decorator: impl for<'a> DecorateLint<'a, ()>) { + self.lookup(lint, None as Option<Span>, |diag| decorator.decorate_lint(diag)); + } + /// Emit a lint at the appropriate level, with no associated span. fn lint( &self, diff --git a/compiler/rustc_lint/src/enum_intrinsics_non_enums.rs b/compiler/rustc_lint/src/enum_intrinsics_non_enums.rs index c5e15a88fdf..f41ee640499 100644 --- a/compiler/rustc_lint/src/enum_intrinsics_non_enums.rs +++ b/compiler/rustc_lint/src/enum_intrinsics_non_enums.rs @@ -1,6 +1,7 @@ use crate::{context::LintContext, LateContext, LateLintPass}; +use rustc_errors::fluent; use rustc_hir as hir; -use rustc_middle::ty::{fold::TypeFoldable, Ty}; +use rustc_middle::ty::{visit::TypeVisitable, Ty}; use rustc_span::{symbol::sym, Span}; declare_lint! { @@ -51,19 +52,9 @@ fn enforce_mem_discriminant( if is_non_enum(ty_param) { cx.struct_span_lint(ENUM_INTRINSICS_NON_ENUMS, expr_span, |builder| { builder - .build( - "the return value of `mem::discriminant` is \ - unspecified when called with a non-enum type", - ) - .span_note( - args_span, - &format!( - "the argument to `discriminant` should be a \ - reference to an enum, but it was passed \ - a reference to a `{}`, which is not an enum.", - ty_param, - ), - ) + .build(fluent::lint::enum_intrinsics_mem_discriminant) + .set_arg("ty_param", ty_param) + .span_note(args_span, fluent::lint::note) .emit(); }); } @@ -74,16 +65,9 @@ fn enforce_mem_variant_count(cx: &LateContext<'_>, func_expr: &hir::Expr<'_>, sp if is_non_enum(ty_param) { cx.struct_span_lint(ENUM_INTRINSICS_NON_ENUMS, span, |builder| { builder - .build( - "the return value of `mem::variant_count` is \ - unspecified when called with a non-enum type", - ) - .note(&format!( - "the type parameter of `variant_count` should \ - be an enum, but it was instantiated with \ - the type `{}`, which is not an enum.", - ty_param, - )) + .build(fluent::lint::enum_intrinsics_mem_variant) + .set_arg("ty_param", ty_param) + .note(fluent::lint::note) .emit(); }); } diff --git a/compiler/rustc_lint/src/expect.rs b/compiler/rustc_lint/src/expect.rs index 95e3125045d..699e8154318 100644 --- a/compiler/rustc_lint/src/expect.rs +++ b/compiler/rustc_lint/src/expect.rs @@ -1,4 +1,5 @@ use crate::builtin; +use rustc_errors::fluent; use rustc_hir::HirId; use rustc_middle::ty::query::Providers; use rustc_middle::{lint::LintExpectation, ty::TyCtxt}; @@ -43,13 +44,13 @@ fn emit_unfulfilled_expectation_lint( hir_id, expectation.emission_span, |diag| { - let mut diag = diag.build("this lint expectation is unfulfilled"); + let mut diag = diag.build(fluent::lint::expectation); if let Some(rationale) = expectation.reason { diag.note(rationale.as_str()); } if expectation.is_unfulfilled_lint_expectations { - diag.note("the `unfulfilled_lint_expectations` lint can't be expected and will always produce this message"); + diag.note(fluent::lint::note); } diag.emit(); diff --git a/compiler/rustc_lint/src/hidden_unicode_codepoints.rs b/compiler/rustc_lint/src/hidden_unicode_codepoints.rs index fc99d759a03..fe2712525ee 100644 --- a/compiler/rustc_lint/src/hidden_unicode_codepoints.rs +++ b/compiler/rustc_lint/src/hidden_unicode_codepoints.rs @@ -1,7 +1,7 @@ use crate::{EarlyContext, EarlyLintPass, LintContext}; use ast::util::unicode::{contains_text_flow_control_chars, TEXT_FLOW_CONTROL_CHARS}; use rustc_ast as ast; -use rustc_errors::{Applicability, SuggestionStyle}; +use rustc_errors::{fluent, Applicability, SuggestionStyle}; use rustc_span::{BytePos, Span, Symbol}; declare_lint! { @@ -61,41 +61,25 @@ impl HiddenUnicodeCodepoints { .collect(); cx.struct_span_lint(TEXT_DIRECTION_CODEPOINT_IN_LITERAL, span, |lint| { - let mut err = lint.build(&format!( - "unicode codepoint changing visible direction of text present in {}", - label - )); - let (an, s) = match spans.len() { - 1 => ("an ", ""), - _ => ("", "s"), - }; - err.span_label( - span, - &format!( - "this {} contains {}invisible unicode text flow control codepoint{}", - label, an, s, - ), - ); + let mut err = lint.build(fluent::lint::hidden_unicode_codepoints); + err.set_arg("label", label); + err.set_arg("count", spans.len()); + err.span_label(span, fluent::lint::label); + err.note(fluent::lint::note); if point_at_inner_spans { for (c, span) in &spans { err.span_label(*span, format!("{:?}", c)); } } - err.note( - "these kind of unicode codepoints change the way text flows on applications that \ - support them, but can cause confusion because they change the order of \ - characters on the screen", - ); if point_at_inner_spans && !spans.is_empty() { err.multipart_suggestion_with_style( - "if their presence wasn't intentional, you can remove them", + fluent::lint::suggestion_remove, spans.iter().map(|(_, span)| (*span, "".to_string())).collect(), Applicability::MachineApplicable, SuggestionStyle::HideCodeAlways, ); err.multipart_suggestion( - "if you want to keep them but make them visible in your source code, you can \ - escape them", + fluent::lint::suggestion_escape, spans .into_iter() .map(|(c, span)| { @@ -109,16 +93,16 @@ impl HiddenUnicodeCodepoints { // FIXME: in other suggestions we've reversed the inner spans of doc comments. We // should do the same here to provide the same good suggestions as we do for // literals above. - err.note("if their presence wasn't intentional, you can remove them"); - err.note(&format!( - "if you want to keep them but make them visible in your source code, you can \ - escape them: {}", + err.set_arg( + "escaped", spans .into_iter() - .map(|(c, _)| { format!("{:?}", c) }) + .map(|(c, _)| format!("{:?}", c)) .collect::<Vec<String>>() .join(", "), - )); + ); + err.note(fluent::lint::suggestion_remove); + err.note(fluent::lint::no_suggestion_note_escape); } err.emit(); }); diff --git a/compiler/rustc_lint/src/internal.rs b/compiler/rustc_lint/src/internal.rs index 56c8635a189..738f475983e 100644 --- a/compiler/rustc_lint/src/internal.rs +++ b/compiler/rustc_lint/src/internal.rs @@ -3,7 +3,7 @@ use crate::{EarlyContext, EarlyLintPass, LateContext, LateLintPass, LintContext}; use rustc_ast as ast; -use rustc_errors::Applicability; +use rustc_errors::{fluent, Applicability}; use rustc_hir::def::Res; use rustc_hir::{def_id::DefId, Expr, ExprKind, GenericArg, PatKind, Path, PathSegment, QPath}; use rustc_hir::{HirId, Impl, Item, ItemKind, Node, Pat, Ty, TyKind}; @@ -36,13 +36,10 @@ impl LateLintPass<'_> for DefaultHashTypes { _ => return, }; cx.struct_span_lint(DEFAULT_HASH_TYPES, path.span, |lint| { - let msg = format!( - "prefer `{}` over `{}`, it has better performance", - replace, - cx.tcx.item_name(def_id) - ); - lint.build(&msg) - .note(&format!("a `use rustc_data_structures::fx::{}` may be necessary", replace)) + lint.build(fluent::lint::default_hash_types) + .set_arg("preferred", replace) + .set_arg("used", cx.tcx.item_name(def_id)) + .note(fluent::lint::note) .emit(); }); } @@ -99,12 +96,9 @@ impl LateLintPass<'_> for QueryStability { let def_id = instance.def_id(); if cx.tcx.has_attr(def_id, sym::rustc_lint_query_instability) { cx.struct_span_lint(POTENTIAL_QUERY_INSTABILITY, span, |lint| { - let msg = format!( - "using `{}` can result in unstable query results", - cx.tcx.item_name(def_id) - ); - lint.build(&msg) - .note("if you believe this case to be fine, allow this lint and add a comment explaining your rationale") + lint.build(fluent::lint::query_instability) + .set_arg("query", cx.tcx.item_name(def_id)) + .note(fluent::lint::note) .emit(); }) } @@ -146,10 +140,10 @@ impl<'tcx> LateLintPass<'tcx> for TyTyKind { segment.args.map_or(segment.ident.span, |a| a.span_ext).hi() ); cx.struct_span_lint(USAGE_OF_TY_TYKIND, path.span, |lint| { - lint.build("usage of `ty::TyKind::<kind>`") + lint.build(fluent::lint::tykind_kind) .span_suggestion( span, - "try using `ty::<kind>` directly", + fluent::lint::suggestion, "ty", Applicability::MaybeIncorrect, // ty maybe needs an import ) @@ -175,10 +169,10 @@ impl<'tcx> LateLintPass<'tcx> for TyTyKind { if let QPath::TypeRelative(qpath_ty, ..) = qpath && qpath_ty.hir_id == ty.hir_id { - lint.build("usage of `ty::TyKind::<kind>`") + lint.build(fluent::lint::tykind_kind) .span_suggestion( path.span, - "try using `ty::<kind>` directly", + fluent::lint::suggestion, "ty", Applicability::MaybeIncorrect, // ty maybe needs an import ) @@ -193,10 +187,10 @@ impl<'tcx> LateLintPass<'tcx> for TyTyKind { if let QPath::TypeRelative(qpath_ty, ..) = qpath && qpath_ty.hir_id == ty.hir_id { - lint.build("usage of `ty::TyKind::<kind>`") + lint.build(fluent::lint::tykind_kind) .span_suggestion( path.span, - "try using `ty::<kind>` directly", + fluent::lint::suggestion, "ty", Applicability::MaybeIncorrect, // ty maybe needs an import ) @@ -213,10 +207,10 @@ impl<'tcx> LateLintPass<'tcx> for TyTyKind { if let QPath::TypeRelative(qpath_ty, ..) = qpath && qpath_ty.hir_id == ty.hir_id { - lint.build("usage of `ty::TyKind::<kind>`") + lint.build(fluent::lint::tykind_kind) .span_suggestion( path.span, - "try using `ty::<kind>` directly", + fluent::lint::suggestion, "ty", Applicability::MaybeIncorrect, // ty maybe needs an import ) @@ -226,15 +220,16 @@ impl<'tcx> LateLintPass<'tcx> for TyTyKind { } _ => {} } - lint.build("usage of `ty::TyKind`").help("try using `Ty` instead").emit(); + lint.build(fluent::lint::tykind).help(fluent::lint::help).emit(); }) } else if !ty.span.from_expansion() && let Some(t) = is_ty_or_ty_ctxt(cx, &path) { if path.segments.len() > 1 { cx.struct_span_lint(USAGE_OF_QUALIFIED_TY, path.span, |lint| { - lint.build(&format!("usage of qualified `ty::{}`", t)) + lint.build(fluent::lint::ty_qualified) + .set_arg("ty", t.clone()) .span_suggestion( path.span, - "try importing it and using it unqualified", + fluent::lint::suggestion, t, // The import probably needs to be changed Applicability::MaybeIncorrect, @@ -330,8 +325,8 @@ impl EarlyLintPass for LintPassImpl { LINT_PASS_IMPL_WITHOUT_MACRO, lint_pass.path.span, |lint| { - lint.build("implementing `LintPass` by hand") - .help("try using `declare_lint_pass!` or `impl_lint_pass!` instead") + lint.build(fluent::lint::lintpass_by_hand) + .help(fluent::lint::help) .emit(); }, ) @@ -371,13 +366,10 @@ impl<'tcx> LateLintPass<'tcx> for ExistingDocKeyword { return; } cx.struct_span_lint(EXISTING_DOC_KEYWORD, attr.span, |lint| { - lint.build(&format!( - "Found non-existing keyword `{}` used in \ - `#[doc(keyword = \"...\")]`", - v, - )) - .help("only existing keywords are allowed in core/std") - .emit(); + lint.build(fluent::lint::non_existant_doc_keyword) + .set_arg("keyword", v) + .help(fluent::lint::help) + .emit(); }); } } @@ -422,7 +414,7 @@ impl LateLintPass<'_> for Diagnostics { let Impl { of_trait: Some(of_trait), .. } = impl_ && let Some(def_id) = of_trait.trait_def_id() && let Some(name) = cx.tcx.get_diagnostic_name(def_id) && - matches!(name, sym::SessionDiagnostic | sym::AddSubdiagnostic) + matches!(name, sym::SessionDiagnostic | sym::AddSubdiagnostic | sym::DecorateLint) { found_impl = true; break; @@ -431,8 +423,7 @@ impl LateLintPass<'_> for Diagnostics { debug!(?found_impl); if !found_impl { cx.struct_span_lint(DIAGNOSTIC_OUTSIDE_OF_IMPL, span, |lint| { - lint.build("diagnostics should only be created in `SessionDiagnostic`/`AddSubdiagnostic` impls") - .emit(); + lint.build(fluent::lint::diag_out_of_impl).emit(); }) } @@ -450,7 +441,7 @@ impl LateLintPass<'_> for Diagnostics { debug!(?found_diagnostic_message); if !found_diagnostic_message { cx.struct_span_lint(UNTRANSLATABLE_DIAGNOSTIC, span, |lint| { - lint.build("diagnostics should be created using translatable messages").emit(); + lint.build(fluent::lint::untranslatable_diag).emit(); }) } } diff --git a/compiler/rustc_lint/src/levels.rs b/compiler/rustc_lint/src/levels.rs index 4773feded12..00e96f20d1a 100644 --- a/compiler/rustc_lint/src/levels.rs +++ b/compiler/rustc_lint/src/levels.rs @@ -3,13 +3,13 @@ use crate::late::unerased_lint_store; use rustc_ast as ast; use rustc_ast_pretty::pprust; use rustc_data_structures::fx::FxHashMap; -use rustc_errors::{struct_span_err, Applicability, Diagnostic, MultiSpan}; +use rustc_errors::{struct_span_err, Applicability, Diagnostic, LintDiagnosticBuilder, MultiSpan}; use rustc_hir as hir; use rustc_hir::{intravisit, HirId}; use rustc_middle::hir::nested_filter; use rustc_middle::lint::{ - struct_lint_level, LevelAndSource, LintDiagnosticBuilder, LintExpectation, LintLevelMap, - LintLevelSets, LintLevelSource, LintSet, LintStackIndex, COMMAND_LINE, + struct_lint_level, LevelAndSource, LintExpectation, LintLevelMap, LintLevelSets, + LintLevelSource, LintSet, LintStackIndex, COMMAND_LINE, }; use rustc_middle::ty::query::Providers; use rustc_middle::ty::{RegisteredTools, TyCtxt}; @@ -521,7 +521,7 @@ impl<'s> LintLevelsBuilder<'s> { src, Some(sp.into()), |lint| { - let mut err = lint.build(&msg); + let mut err = lint.build(msg); if let Some(new_name) = &renamed { err.span_suggestion( sp, @@ -548,7 +548,7 @@ impl<'s> LintLevelsBuilder<'s> { } else { name.to_string() }; - let mut db = lint.build(&format!("unknown lint: `{}`", name)); + let mut db = lint.build(format!("unknown lint: `{}`", name)); if let Some(suggestion) = suggestion { db.span_suggestion( sp, diff --git a/compiler/rustc_lint/src/methods.rs b/compiler/rustc_lint/src/methods.rs index b6a45676a30..ff5a01749c1 100644 --- a/compiler/rustc_lint/src/methods.rs +++ b/compiler/rustc_lint/src/methods.rs @@ -1,6 +1,7 @@ use crate::LateContext; use crate::LateLintPass; use crate::LintContext; +use rustc_errors::fluent; use rustc_hir::{Expr, ExprKind, PathSegment}; use rustc_middle::ty; use rustc_span::{symbol::sym, ExpnKind, Span}; @@ -88,16 +89,12 @@ fn lint_cstring_as_ptr( if let ty::Adt(adt, _) = substs.type_at(0).kind() { if cx.tcx.is_diagnostic_item(sym::cstring_type, adt.did()) { cx.struct_span_lint(TEMPORARY_CSTRING_AS_PTR, as_ptr_span, |diag| { - let mut diag = diag - .build("getting the inner pointer of a temporary `CString`"); - diag.span_label(as_ptr_span, "this pointer will be invalid"); - diag.span_label( - unwrap.span, - "this `CString` is deallocated at the end of the statement, bind it to a variable to extend its lifetime", - ); - diag.note("pointers do not have a lifetime; when calling `as_ptr` the `CString` will be deallocated at the end of the statement because nothing is referencing it as far as the type system is concerned"); - diag.help("for more information, see https://doc.rust-lang.org/reference/destructors.html"); - diag.emit(); + diag.build(fluent::lint::cstring_ptr) + .span_label(as_ptr_span, fluent::lint::as_ptr_label) + .span_label(unwrap.span, fluent::lint::unwrap_label) + .note(fluent::lint::note) + .help(fluent::lint::help) + .emit(); }); } } diff --git a/compiler/rustc_lint/src/non_ascii_idents.rs b/compiler/rustc_lint/src/non_ascii_idents.rs index 6182d2b10ed..764003e61a6 100644 --- a/compiler/rustc_lint/src/non_ascii_idents.rs +++ b/compiler/rustc_lint/src/non_ascii_idents.rs @@ -1,6 +1,7 @@ use crate::{EarlyContext, EarlyLintPass, LintContext}; use rustc_ast as ast; use rustc_data_structures::fx::FxHashMap; +use rustc_errors::fluent; use rustc_span::symbol::Symbol; declare_lint! { @@ -180,13 +181,13 @@ impl EarlyLintPass for NonAsciiIdents { } has_non_ascii_idents = true; cx.struct_span_lint(NON_ASCII_IDENTS, sp, |lint| { - lint.build("identifier contains non-ASCII characters").emit(); + lint.build(fluent::lint::identifier_non_ascii_char).emit(); }); if check_uncommon_codepoints && !symbol_str.chars().all(GeneralSecurityProfile::identifier_allowed) { cx.struct_span_lint(UNCOMMON_CODEPOINTS, sp, |lint| { - lint.build("identifier contains uncommon Unicode codepoints").emit(); + lint.build(fluent::lint::identifier_uncommon_codepoints).emit(); }) } } @@ -216,15 +217,11 @@ impl EarlyLintPass for NonAsciiIdents { .and_modify(|(existing_symbol, existing_span, existing_is_ascii)| { if !*existing_is_ascii || !is_ascii { cx.struct_span_lint(CONFUSABLE_IDENTS, sp, |lint| { - lint.build(&format!( - "identifier pair considered confusable between `{}` and `{}`", - existing_symbol, symbol - )) - .span_label( - *existing_span, - "this is where the previous identifier occurred", - ) - .emit(); + lint.build(fluent::lint::confusable_identifier_pair) + .set_arg("existing_sym", *existing_symbol) + .set_arg("sym", symbol) + .span_label(*existing_span, fluent::lint::label) + .emit(); }); } if *existing_is_ascii && !is_ascii { @@ -326,18 +323,20 @@ impl EarlyLintPass for NonAsciiIdents { for ((sp, ch_list), script_set) in lint_reports { cx.struct_span_lint(MIXED_SCRIPT_CONFUSABLES, sp, |lint| { - let message = format!( - "the usage of Script Group `{}` in this crate consists solely of mixed script confusables", - script_set); - let mut note = "the usage includes ".to_string(); + let mut includes = String::new(); for (idx, ch) in ch_list.into_iter().enumerate() { if idx != 0 { - note += ", "; + includes += ", "; } let char_info = format!("'{}' (U+{:04X})", ch, ch as u32); - note += &char_info; + includes += &char_info; } - lint.build(&message).note(¬e).note("please recheck to make sure their usages are indeed what you want").emit(); + lint.build(fluent::lint::mixed_script_confusables) + .set_arg("set", script_set.to_string()) + .set_arg("includes", includes) + .note(fluent::lint::includes_note) + .note(fluent::lint::note) + .emit(); }); } } diff --git a/compiler/rustc_lint/src/non_fmt_panic.rs b/compiler/rustc_lint/src/non_fmt_panic.rs index 4e7aeca9ce1..cdad2d2e8f9 100644 --- a/compiler/rustc_lint/src/non_fmt_panic.rs +++ b/compiler/rustc_lint/src/non_fmt_panic.rs @@ -1,6 +1,6 @@ use crate::{LateContext, LateLintPass, LintContext}; use rustc_ast as ast; -use rustc_errors::{pluralize, Applicability}; +use rustc_errors::{fluent, Applicability}; use rustc_hir as hir; use rustc_infer::infer::TyCtxtInferExt; use rustc_middle::lint::in_external_macro; @@ -120,9 +120,10 @@ fn check_panic<'tcx>(cx: &LateContext<'tcx>, f: &'tcx hir::Expr<'tcx>, arg: &'tc } cx.struct_span_lint(NON_FMT_PANICS, arg_span, |lint| { - let mut l = lint.build("panic message is not a string literal"); - l.note(&format!("this usage of {}!() is deprecated; it will be a hard error in Rust 2021", symbol)); - l.note("for more information, see <https://doc.rust-lang.org/nightly/edition-guide/rust-2021/panic-macro-consistency.html>"); + let mut l = lint.build(fluent::lint::non_fmt_panic); + l.set_arg("name", symbol); + l.note(fluent::lint::note); + l.note(fluent::lint::more_info_note); if !is_arg_inside_call(arg_span, span) { // No clue where this argument is coming from. l.emit(); @@ -130,10 +131,10 @@ fn check_panic<'tcx>(cx: &LateContext<'tcx>, f: &'tcx hir::Expr<'tcx>, arg: &'tc } if arg_macro.map_or(false, |id| cx.tcx.is_diagnostic_item(sym::format_macro, id)) { // A case of `panic!(format!(..))`. - l.note(format!("the {}!() macro supports formatting, so there's no need for the format!() macro here", symbol).as_str()); + l.note(fluent::lint::supports_fmt_note); if let Some((open, close, _)) = find_delimiters(cx, arg_span) { l.multipart_suggestion( - "remove the `format!(..)` macro call", + fluent::lint::supports_fmt_suggestion, vec![ (arg_span.until(open.shrink_to_hi()), "".into()), (close.until(arg_span.shrink_to_hi()), "".into()), @@ -153,12 +154,18 @@ fn check_panic<'tcx>(cx: &LateContext<'tcx>, f: &'tcx hir::Expr<'tcx>, arg: &'tc ); let (suggest_display, suggest_debug) = cx.tcx.infer_ctxt().enter(|infcx| { - let display = is_str || cx.tcx.get_diagnostic_item(sym::Display).map(|t| { - infcx.type_implements_trait(t, ty, InternalSubsts::empty(), cx.param_env).may_apply() - }) == Some(true); - let debug = !display && cx.tcx.get_diagnostic_item(sym::Debug).map(|t| { - infcx.type_implements_trait(t, ty, InternalSubsts::empty(), cx.param_env).may_apply() - }) == Some(true); + let display = is_str + || cx.tcx.get_diagnostic_item(sym::Display).map(|t| { + infcx + .type_implements_trait(t, ty, InternalSubsts::empty(), cx.param_env) + .may_apply() + }) == Some(true); + let debug = !display + && cx.tcx.get_diagnostic_item(sym::Debug).map(|t| { + infcx + .type_implements_trait(t, ty, InternalSubsts::empty(), cx.param_env) + .may_apply() + }) == Some(true); (display, debug) }); @@ -175,17 +182,15 @@ fn check_panic<'tcx>(cx: &LateContext<'tcx>, f: &'tcx hir::Expr<'tcx>, arg: &'tc if suggest_display { l.span_suggestion_verbose( arg_span.shrink_to_lo(), - "add a \"{}\" format string to Display the message", + fluent::lint::display_suggestion, "\"{}\", ", fmt_applicability, ); } else if suggest_debug { + l.set_arg("ty", ty); l.span_suggestion_verbose( arg_span.shrink_to_lo(), - &format!( - "add a \"{{:?}}\" format string to use the Debug implementation of `{}`", - ty, - ), + fluent::lint::debug_suggestion, "\"{:?}\", ", fmt_applicability, ); @@ -193,15 +198,9 @@ fn check_panic<'tcx>(cx: &LateContext<'tcx>, f: &'tcx hir::Expr<'tcx>, arg: &'tc if suggest_panic_any { if let Some((open, close, del)) = find_delimiters(cx, span) { + l.set_arg("already_suggested", suggest_display || suggest_debug); l.multipart_suggestion( - &format!( - "{}use std::panic::panic_any instead", - if suggest_display || suggest_debug { - "or " - } else { - "" - }, - ), + fluent::lint::panic_suggestion, if del == '(' { vec![(span.until(open), "std::panic::panic_any".into())] } else { @@ -260,21 +259,19 @@ fn check_panic_str<'tcx>( .collect(), }; cx.struct_span_lint(NON_FMT_PANICS, arg_spans, |lint| { - let mut l = lint.build(match n_arguments { - 1 => "panic message contains an unused formatting placeholder", - _ => "panic message contains unused formatting placeholders", - }); - l.note("this message is not used as a format string when given without arguments, but will be in Rust 2021"); + let mut l = lint.build(fluent::lint::non_fmt_panic_unused); + l.set_arg("count", n_arguments); + l.note(fluent::lint::note); if is_arg_inside_call(arg.span, span) { l.span_suggestion( arg.span.shrink_to_hi(), - &format!("add the missing argument{}", pluralize!(n_arguments)), + fluent::lint::add_args_suggestion, ", ...", Applicability::HasPlaceholders, ); l.span_suggestion( arg.span.shrink_to_lo(), - "or add a \"{}\" format string to use the message literally", + fluent::lint::add_fmt_suggestion, "\"{}\", ", Applicability::MachineApplicable, ); @@ -289,17 +286,15 @@ fn check_panic_str<'tcx>( .map(|(i, _)| fmt_span.from_inner(InnerSpan { start: i, end: i + 1 })) .collect() }); - let msg = match &brace_spans { - Some(v) if v.len() == 1 => "panic message contains a brace", - _ => "panic message contains braces", - }; + let count = brace_spans.as_ref().map(|v| v.len()).unwrap_or(/* any number >1 */ 2); cx.struct_span_lint(NON_FMT_PANICS, brace_spans.unwrap_or_else(|| vec![span]), |lint| { - let mut l = lint.build(msg); - l.note("this message is not used as a format string, but will be in Rust 2021"); + let mut l = lint.build(fluent::lint::non_fmt_panic_braces); + l.set_arg("count", count); + l.note(fluent::lint::note); if is_arg_inside_call(arg.span, span) { l.span_suggestion( arg.span.shrink_to_lo(), - "add a \"{}\" format string to use the message literally", + fluent::lint::suggestion, "\"{}\", ", Applicability::MachineApplicable, ); diff --git a/compiler/rustc_lint/src/nonstandard_style.rs b/compiler/rustc_lint/src/nonstandard_style.rs index e1507d0fbb4..33ac2ed02aa 100644 --- a/compiler/rustc_lint/src/nonstandard_style.rs +++ b/compiler/rustc_lint/src/nonstandard_style.rs @@ -1,7 +1,7 @@ use crate::{EarlyContext, EarlyLintPass, LateContext, LateLintPass, LintContext}; use rustc_ast as ast; use rustc_attr as attr; -use rustc_errors::Applicability; +use rustc_errors::{fluent, Applicability}; use rustc_hir as hir; use rustc_hir::def::{DefKind, Res}; use rustc_hir::intravisit::FnKind; @@ -137,22 +137,23 @@ impl NonCamelCaseTypes { if !is_camel_case(name) { cx.struct_span_lint(NON_CAMEL_CASE_TYPES, ident.span, |lint| { - let msg = format!("{} `{}` should have an upper camel case name", sort, name); - let mut err = lint.build(&msg); + let mut err = lint.build(fluent::lint::non_camel_case_type); let cc = to_camel_case(name); // We cannot provide meaningful suggestions // if the characters are in the category of "Lowercase Letter". if *name != cc { err.span_suggestion( ident.span, - "convert the identifier to upper camel case", + fluent::lint::suggestion, to_camel_case(name), Applicability::MaybeIncorrect, ); } else { - err.span_label(ident.span, "should have an UpperCamelCase name"); + err.span_label(ident.span, fluent::lint::label); } + err.set_arg("sort", sort); + err.set_arg("name", name); err.emit(); }) } @@ -281,11 +282,10 @@ impl NonSnakeCase { if !is_snake_case(name) { cx.struct_span_lint(NON_SNAKE_CASE, ident.span, |lint| { let sc = NonSnakeCase::to_snake_case(name); - let msg = format!("{} `{}` should have a snake case name", sort, name); - let mut err = lint.build(&msg); + let mut err = lint.build(fluent::lint::non_snake_case); // We cannot provide meaningful suggestions // if the characters are in the category of "Uppercase Letter". - if *name != sc { + if name != sc { // We have a valid span in almost all cases, but we don't have one when linting a crate // name provided via the command line. if !ident.span.is_dummy() { @@ -295,13 +295,13 @@ impl NonSnakeCase { // Instead, recommend renaming the identifier entirely or, if permitted, // escaping it to create a raw identifier. if sc_ident.name.can_be_raw() { - ("rename the identifier or convert it to a snake case raw identifier", sc_ident.to_string()) + (fluent::lint::rename_or_convert_suggestion, sc_ident.to_string()) } else { - err.note(&format!("`{}` cannot be used as a raw identifier", sc)); - ("rename the identifier", String::new()) + err.note(fluent::lint::cannot_convert_note); + (fluent::lint::rename_suggestion, String::new()) } } else { - ("convert the identifier to snake case", sc) + (fluent::lint::convert_suggestion, sc.clone()) }; err.span_suggestion( @@ -311,12 +311,15 @@ impl NonSnakeCase { Applicability::MaybeIncorrect, ); } else { - err.help(&format!("convert the identifier to snake case: `{}`", sc)); + err.help(fluent::lint::help); } } else { - err.span_label(ident.span, "should have a snake_case name"); + err.span_label(ident.span, fluent::lint::label); } + err.set_arg("sort", sort); + err.set_arg("name", name); + err.set_arg("sc", sc); err.emit(); }); } @@ -488,21 +491,22 @@ impl NonUpperCaseGlobals { if name.chars().any(|c| c.is_lowercase()) { cx.struct_span_lint(NON_UPPER_CASE_GLOBALS, ident.span, |lint| { let uc = NonSnakeCase::to_snake_case(&name).to_uppercase(); - let mut err = - lint.build(&format!("{} `{}` should have an upper case name", sort, name)); + let mut err = lint.build(fluent::lint::non_upper_case_global); // We cannot provide meaningful suggestions // if the characters are in the category of "Lowercase Letter". if *name != uc { err.span_suggestion( ident.span, - "convert the identifier to upper case", + fluent::lint::suggestion, uc, Applicability::MaybeIncorrect, ); } else { - err.span_label(ident.span, "should have an UPPER_CASE name"); + err.span_label(ident.span, fluent::lint::label); } + err.set_arg("sort", sort); + err.set_arg("name", name); err.emit(); }) } diff --git a/compiler/rustc_lint/src/noop_method_call.rs b/compiler/rustc_lint/src/noop_method_call.rs index 675bee738a6..11a752ff097 100644 --- a/compiler/rustc_lint/src/noop_method_call.rs +++ b/compiler/rustc_lint/src/noop_method_call.rs @@ -1,7 +1,8 @@ use crate::context::LintContext; -use crate::rustc_middle::ty::TypeFoldable; +use crate::rustc_middle::ty::TypeVisitable; use crate::LateContext; use crate::LateLintPass; +use rustc_errors::fluent; use rustc_hir::def::DefKind; use rustc_hir::{Expr, ExprKind}; use rustc_middle::ty; @@ -80,7 +81,6 @@ impl<'tcx> LateLintPass<'tcx> for NoopMethodCall { ) { return; } - let method = &call.ident.name; let receiver = &elements[0]; let receiver_ty = cx.typeck_results().expr_ty(receiver); let expr_ty = cx.typeck_results().expr_ty_adjusted(expr); @@ -90,19 +90,14 @@ impl<'tcx> LateLintPass<'tcx> for NoopMethodCall { return; } let expr_span = expr.span; - let note = format!( - "the type `{:?}` which `{}` is being called on is the same as \ - the type returned from `{}`, so the method call does not do \ - anything and can be removed", - receiver_ty, method, method, - ); - let span = expr_span.with_lo(receiver.span.hi()); cx.struct_span_lint(NOOP_METHOD_CALL, span, |lint| { - let method = &call.ident.name; - let message = - format!("call to `.{}()` on a reference in this situation does nothing", &method,); - lint.build(&message).span_label(span, "unnecessary method call").note(¬e).emit(); + lint.build(fluent::lint::noop_method_call) + .set_arg("method", call.ident.name) + .set_arg("receiver_ty", receiver_ty) + .span_label(span, fluent::lint::label) + .note(fluent::lint::note) + .emit(); }); } } diff --git a/compiler/rustc_lint/src/pass_by_value.rs b/compiler/rustc_lint/src/pass_by_value.rs index 2c8b41d7214..af5e5faf1f5 100644 --- a/compiler/rustc_lint/src/pass_by_value.rs +++ b/compiler/rustc_lint/src/pass_by_value.rs @@ -1,5 +1,5 @@ use crate::{LateContext, LateLintPass, LintContext}; -use rustc_errors::Applicability; +use rustc_errors::{fluent, Applicability}; use rustc_hir as hir; use rustc_hir::def::Res; use rustc_hir::{GenericArg, PathSegment, QPath, TyKind}; @@ -30,10 +30,11 @@ impl<'tcx> LateLintPass<'tcx> for PassByValue { } if let Some(t) = path_for_pass_by_value(cx, &inner_ty) { cx.struct_span_lint(PASS_BY_VALUE, ty.span, |lint| { - lint.build(&format!("passing `{}` by reference", t)) + lint.build(fluent::lint::pass_by_value) + .set_arg("ty", t.clone()) .span_suggestion( ty.span, - "try passing by value", + fluent::lint::suggestion, t, // Changing type of function argument Applicability::MaybeIncorrect, diff --git a/compiler/rustc_lint/src/redundant_semicolon.rs b/compiler/rustc_lint/src/redundant_semicolon.rs index f06a8b8f4b0..26f41345383 100644 --- a/compiler/rustc_lint/src/redundant_semicolon.rs +++ b/compiler/rustc_lint/src/redundant_semicolon.rs @@ -1,6 +1,6 @@ use crate::{EarlyContext, EarlyLintPass, LintContext}; use rustc_ast::{Block, StmtKind}; -use rustc_errors::Applicability; +use rustc_errors::{fluent, Applicability}; use rustc_span::Span; declare_lint! { @@ -49,12 +49,10 @@ fn maybe_lint_redundant_semis(cx: &EarlyContext<'_>, seq: &mut Option<(Span, boo } cx.struct_span_lint(REDUNDANT_SEMICOLONS, span, |lint| { - let (msg, rem) = if multiple { - ("unnecessary trailing semicolons", "remove these semicolons") - } else { - ("unnecessary trailing semicolon", "remove this semicolon") - }; - lint.build(msg).span_suggestion(span, rem, "", Applicability::MaybeIncorrect).emit(); + lint.build(fluent::lint::redundant_semicolons) + .set_arg("multiple", multiple) + .span_suggestion(span, fluent::lint::suggestion, "", Applicability::MaybeIncorrect) + .emit(); }); } } diff --git a/compiler/rustc_lint/src/traits.rs b/compiler/rustc_lint/src/traits.rs index 81d308ee347..df1587c5948 100644 --- a/compiler/rustc_lint/src/traits.rs +++ b/compiler/rustc_lint/src/traits.rs @@ -1,6 +1,7 @@ use crate::LateContext; use crate::LateLintPass; use crate::LintContext; +use rustc_errors::fluent; use rustc_hir as hir; use rustc_span::symbol::sym; @@ -103,13 +104,10 @@ impl<'tcx> LateLintPass<'tcx> for DropTraitConstraints { let Some(needs_drop) = cx.tcx.get_diagnostic_item(sym::needs_drop) else { return }; - let msg = format!( - "bounds on `{}` are most likely incorrect, consider instead \ - using `{}` to detect whether a type can be trivially dropped", - predicate, - cx.tcx.def_path_str(needs_drop) - ); - lint.build(&msg).emit(); + lint.build(fluent::lint::drop_trait_constraints) + .set_arg("predicate", predicate) + .set_arg("needs_drop", cx.tcx.def_path_str(needs_drop)) + .emit(); }); } } @@ -126,12 +124,9 @@ impl<'tcx> LateLintPass<'tcx> for DropTraitConstraints { let Some(needs_drop) = cx.tcx.get_diagnostic_item(sym::needs_drop) else { return }; - let msg = format!( - "types that do not implement `Drop` can still have drop glue, consider \ - instead using `{}` to detect whether a type is trivially dropped", - cx.tcx.def_path_str(needs_drop) - ); - lint.build(&msg).emit(); + lint.build(fluent::lint::drop_glue) + .set_arg("needs_drop", cx.tcx.def_path_str(needs_drop)) + .emit(); }); } } diff --git a/compiler/rustc_lint/src/types.rs b/compiler/rustc_lint/src/types.rs index 5579e4d19cf..be4843c7ff1 100644 --- a/compiler/rustc_lint/src/types.rs +++ b/compiler/rustc_lint/src/types.rs @@ -2,12 +2,13 @@ use crate::{LateContext, LateLintPass, LintContext}; use rustc_ast as ast; use rustc_attr as attr; use rustc_data_structures::fx::FxHashSet; -use rustc_errors::Applicability; +use rustc_errors::{fluent, Applicability, DiagnosticMessage}; use rustc_hir as hir; use rustc_hir::{is_range_literal, Expr, ExprKind, Node}; +use rustc_macros::LintDiagnostic; use rustc_middle::ty::layout::{IntegerExt, LayoutOf, SizeSkeleton}; use rustc_middle::ty::subst::SubstsRef; -use rustc_middle::ty::{self, AdtKind, DefIdTree, Ty, TyCtxt, TypeFoldable, TypeSuperFoldable}; +use rustc_middle::ty::{self, AdtKind, DefIdTree, Ty, TyCtxt, TypeSuperVisitable, TypeVisitable}; use rustc_span::source_map; use rustc_span::symbol::sym; use rustc_span::{Span, Symbol, DUMMY_SP}; @@ -139,7 +140,8 @@ fn lint_overflowing_range_endpoint<'tcx>( // overflowing and only by 1. if eps[1].expr.hir_id == expr.hir_id && lit_val - 1 == max { cx.struct_span_lint(OVERFLOWING_LITERALS, parent_expr.span, |lint| { - let mut err = lint.build(&format!("range endpoint is out of range for `{}`", ty)); + let mut err = lint.build(fluent::lint::range_endpoint_out_of_range); + err.set_arg("ty", ty); if let Ok(start) = cx.sess().source_map().span_to_snippet(eps[0].span) { use ast::{LitIntType, LitKind}; // We need to preserve the literal's suffix, @@ -153,7 +155,7 @@ fn lint_overflowing_range_endpoint<'tcx>( let suggestion = format!("{}..={}{}", start, lit_val - 1, suffix); err.span_suggestion( parent_expr.span, - "use an inclusive range instead", + fluent::lint::suggestion, suggestion, Applicability::MachineApplicable, ); @@ -229,38 +231,35 @@ fn report_bin_hex_error( (t.name_str(), actually.to_string()) } }; - let mut err = lint.build(&format!("literal out of range for `{}`", t)); + let mut err = lint.build(fluent::lint::overflowing_bin_hex); if negative { // If the value is negative, // emits a note about the value itself, apart from the literal. - err.note(&format!( - "the literal `{}` (decimal `{}`) does not fit into \ - the type `{}`", - repr_str, val, t - )); - err.note(&format!("and the value `-{}` will become `{}{}`", repr_str, actually, t)); + err.note(fluent::lint::negative_note); + err.note(fluent::lint::negative_becomes_note); } else { - err.note(&format!( - "the literal `{}` (decimal `{}`) does not fit into \ - the type `{}` and will become `{}{}`", - repr_str, val, t, actually, t - )); + err.note(fluent::lint::positive_note); } if let Some(sugg_ty) = get_type_suggestion(cx.typeck_results().node_type(expr.hir_id), val, negative) { + err.set_arg("suggestion_ty", sugg_ty); if let Some(pos) = repr_str.chars().position(|c| c == 'i' || c == 'u') { let (sans_suffix, _) = repr_str.split_at(pos); err.span_suggestion( expr.span, - &format!("consider using the type `{}` instead", sugg_ty), + fluent::lint::suggestion, format!("{}{}", sans_suffix, sugg_ty), Applicability::MachineApplicable, ); } else { - err.help(&format!("consider using the type `{}` instead", sugg_ty)); + err.help(fluent::lint::help); } } + err.set_arg("ty", t); + err.set_arg("lit", repr_str); + err.set_arg("dec", val); + err.set_arg("actually", actually); err.emit(); }); } @@ -353,21 +352,23 @@ fn lint_int_literal<'tcx>( } cx.struct_span_lint(OVERFLOWING_LITERALS, e.span, |lint| { - let mut err = lint.build(&format!("literal out of range for `{}`", t.name_str())); - err.note(&format!( - "the literal `{}` does not fit into the type `{}` whose range is `{}..={}`", + let mut err = lint.build(fluent::lint::overflowing_int); + err.set_arg("ty", t.name_str()); + err.set_arg( + "lit", cx.sess() .source_map() .span_to_snippet(lit.span) .expect("must get snippet from literal"), - t.name_str(), - min, - max, - )); + ); + err.set_arg("min", min); + err.set_arg("max", max); + err.note(fluent::lint::note); if let Some(sugg_ty) = get_type_suggestion(cx.typeck_results().node_type(e.hir_id), v, negative) { - err.help(&format!("consider using the type `{}` instead", sugg_ty)); + err.set_arg("suggestion_ty", sugg_ty); + err.help(fluent::lint::help); } err.emit(); }); @@ -395,10 +396,10 @@ fn lint_uint_literal<'tcx>( hir::ExprKind::Cast(..) => { if let ty::Char = cx.typeck_results().expr_ty(par_e).kind() { cx.struct_span_lint(OVERFLOWING_LITERALS, par_e.span, |lint| { - lint.build("only `u8` can be cast into `char`") + lint.build(fluent::lint::only_cast_u8_to_char) .span_suggestion( par_e.span, - "use a `char` literal instead", + fluent::lint::suggestion, format!("'\\u{{{:X}}}'", lit_val), Applicability::MachineApplicable, ) @@ -429,17 +430,18 @@ fn lint_uint_literal<'tcx>( return; } cx.struct_span_lint(OVERFLOWING_LITERALS, e.span, |lint| { - lint.build(&format!("literal out of range for `{}`", t.name_str())) - .note(&format!( - "the literal `{}` does not fit into the type `{}` whose range is `{}..={}`", + lint.build(fluent::lint::overflowing_uint) + .set_arg("ty", t.name_str()) + .set_arg( + "lit", cx.sess() .source_map() .span_to_snippet(lit.span) .expect("must get snippet from literal"), - t.name_str(), - min, - max, - )) + ) + .set_arg("min", min) + .set_arg("max", max) + .note(fluent::lint::note) .emit(); }); } @@ -471,16 +473,16 @@ fn lint_literal<'tcx>( }; if is_infinite == Ok(true) { cx.struct_span_lint(OVERFLOWING_LITERALS, e.span, |lint| { - lint.build(&format!("literal out of range for `{}`", t.name_str())) - .note(&format!( - "the literal `{}` does not fit into the type `{}` and will be converted to `{}::INFINITY`", + lint.build(fluent::lint::overflowing_literal) + .set_arg("ty", t.name_str()) + .set_arg( + "lit", cx.sess() .source_map() .span_to_snippet(lit.span) .expect("must get snippet from literal"), - t.name_str(), - t.name_str(), - )) + ) + .note(fluent::lint::note) .emit(); }); } @@ -501,7 +503,7 @@ impl<'tcx> LateLintPass<'tcx> for TypeLimits { hir::ExprKind::Binary(binop, ref l, ref r) => { if is_comparison(binop) && !check_limits(cx, binop, &l, &r) { cx.struct_span_lint(UNUSED_COMPARISONS, e.span, |lint| { - lint.build("comparison is useless due to type limits").emit(); + lint.build(fluent::lint::unused_comparisons).emit(); }); } } @@ -663,7 +665,7 @@ struct ImproperCTypesVisitor<'a, 'tcx> { enum FfiResult<'tcx> { FfiSafe, FfiPhantom(Ty<'tcx>), - FfiUnsafe { ty: Ty<'tcx>, reason: String, help: Option<String> }, + FfiUnsafe { ty: Ty<'tcx>, reason: DiagnosticMessage, help: Option<DiagnosticMessage> }, } pub(crate) fn nonnull_optimization_guaranteed<'tcx>( @@ -823,8 +825,8 @@ impl<'a, 'tcx> ImproperCTypesVisitor<'a, 'tcx> { self.emit_ffi_unsafe_type_lint( ty, sp, - "passing raw arrays by value is not FFI-safe", - Some("consider passing a pointer to the array"), + fluent::lint::improper_ctypes_array_reason, + Some(fluent::lint::improper_ctypes_array_help), ); true } else { @@ -867,11 +869,7 @@ impl<'a, 'tcx> ImproperCTypesVisitor<'a, 'tcx> { } else { // All fields are ZSTs; this means that the type should behave // like (), which is FFI-unsafe - FfiUnsafe { - ty, - reason: "this struct contains only zero-sized fields".into(), - help: None, - } + FfiUnsafe { ty, reason: fluent::lint::improper_ctypes_struct_zst, help: None } } } else { // We can't completely trust repr(C) markings; make sure the fields are @@ -885,7 +883,7 @@ impl<'a, 'tcx> ImproperCTypesVisitor<'a, 'tcx> { FfiPhantom(..) if def.is_enum() => { return FfiUnsafe { ty, - reason: "this enum contains a PhantomData field".into(), + reason: fluent::lint::improper_ctypes_enum_phantomdata, help: None, }; } @@ -921,7 +919,7 @@ impl<'a, 'tcx> ImproperCTypesVisitor<'a, 'tcx> { } else { return FfiUnsafe { ty, - reason: "box cannot be represented as a single pointer".to_string(), + reason: fluent::lint::improper_ctypes_box, help: None, }; } @@ -931,17 +929,19 @@ impl<'a, 'tcx> ImproperCTypesVisitor<'a, 'tcx> { } match def.adt_kind() { AdtKind::Struct | AdtKind::Union => { - let kind = if def.is_struct() { "struct" } else { "union" }; - if !def.repr().c() && !def.repr().transparent() { return FfiUnsafe { ty, - reason: format!("this {} has unspecified layout", kind), - help: Some(format!( - "consider adding a `#[repr(C)]` or \ - `#[repr(transparent)]` attribute to this {}", - kind - )), + reason: if def.is_struct() { + fluent::lint::improper_ctypes_struct_layout_reason + } else { + fluent::lint::improper_ctypes_union_layout_reason + }, + help: if def.is_struct() { + Some(fluent::lint::improper_ctypes_struct_layout_help) + } else { + Some(fluent::lint::improper_ctypes_union_layout_help) + }, }; } @@ -950,7 +950,11 @@ impl<'a, 'tcx> ImproperCTypesVisitor<'a, 'tcx> { if is_non_exhaustive && !def.did().is_local() { return FfiUnsafe { ty, - reason: format!("this {} is non-exhaustive", kind), + reason: if def.is_struct() { + fluent::lint::improper_ctypes_struct_non_exhaustive + } else { + fluent::lint::improper_ctypes_union_non_exhaustive + }, help: None, }; } @@ -958,8 +962,16 @@ impl<'a, 'tcx> ImproperCTypesVisitor<'a, 'tcx> { if def.non_enum_variant().fields.is_empty() { return FfiUnsafe { ty, - reason: format!("this {} has no fields", kind), - help: Some(format!("consider adding a member to this {}", kind)), + reason: if def.is_struct() { + fluent::lint::improper_ctypes_struct_fieldless_reason + } else { + fluent::lint::improper_ctypes_union_fieldless_reason + }, + help: if def.is_struct() { + Some(fluent::lint::improper_ctypes_struct_fieldless_help) + } else { + Some(fluent::lint::improper_ctypes_union_fieldless_help) + }, }; } @@ -979,13 +991,8 @@ impl<'a, 'tcx> ImproperCTypesVisitor<'a, 'tcx> { if repr_nullable_ptr(self.cx, ty, self.mode).is_none() { return FfiUnsafe { ty, - reason: "enum has no representation hint".into(), - help: Some( - "consider adding a `#[repr(C)]`, \ - `#[repr(transparent)]`, or integer `#[repr(...)]` \ - attribute to this enum" - .into(), - ), + reason: fluent::lint::improper_ctypes_enum_repr_reason, + help: Some(fluent::lint::improper_ctypes_enum_repr_help), }; } } @@ -993,7 +1000,7 @@ impl<'a, 'tcx> ImproperCTypesVisitor<'a, 'tcx> { if def.is_variant_list_non_exhaustive() && !def.did().is_local() { return FfiUnsafe { ty, - reason: "this enum is non-exhaustive".into(), + reason: fluent::lint::improper_ctypes_non_exhaustive, help: None, }; } @@ -1004,7 +1011,7 @@ impl<'a, 'tcx> ImproperCTypesVisitor<'a, 'tcx> { if is_non_exhaustive && !variant.def_id.is_local() { return FfiUnsafe { ty, - reason: "this enum has non-exhaustive variants".into(), + reason: fluent::lint::improper_ctypes_non_exhaustive_variant, help: None, }; } @@ -1022,39 +1029,37 @@ impl<'a, 'tcx> ImproperCTypesVisitor<'a, 'tcx> { ty::Char => FfiUnsafe { ty, - reason: "the `char` type has no C equivalent".into(), - help: Some("consider using `u32` or `libc::wchar_t` instead".into()), + reason: fluent::lint::improper_ctypes_char_reason, + help: Some(fluent::lint::improper_ctypes_char_help), }, - ty::Int(ty::IntTy::I128) | ty::Uint(ty::UintTy::U128) => FfiUnsafe { - ty, - reason: "128-bit integers don't currently have a known stable ABI".into(), - help: None, - }, + ty::Int(ty::IntTy::I128) | ty::Uint(ty::UintTy::U128) => { + FfiUnsafe { ty, reason: fluent::lint::improper_ctypes_128bit, help: None } + } // Primitive types with a stable representation. ty::Bool | ty::Int(..) | ty::Uint(..) | ty::Float(..) | ty::Never => FfiSafe, ty::Slice(_) => FfiUnsafe { ty, - reason: "slices have no C equivalent".into(), - help: Some("consider using a raw pointer instead".into()), + reason: fluent::lint::improper_ctypes_slice_reason, + help: Some(fluent::lint::improper_ctypes_slice_help), }, ty::Dynamic(..) => { - FfiUnsafe { ty, reason: "trait objects have no C equivalent".into(), help: None } + FfiUnsafe { ty, reason: fluent::lint::improper_ctypes_dyn, help: None } } ty::Str => FfiUnsafe { ty, - reason: "string slices have no C equivalent".into(), - help: Some("consider using `*const u8` and a length instead".into()), + reason: fluent::lint::improper_ctypes_str_reason, + help: Some(fluent::lint::improper_ctypes_str_help), }, ty::Tuple(..) => FfiUnsafe { ty, - reason: "tuples have unspecified layout".into(), - help: Some("consider using a struct instead".into()), + reason: fluent::lint::improper_ctypes_tuple_reason, + help: Some(fluent::lint::improper_ctypes_tuple_help), }, ty::RawPtr(ty::TypeAndMut { ty, .. }) | ty::Ref(_, ty, _) @@ -1085,12 +1090,8 @@ impl<'a, 'tcx> ImproperCTypesVisitor<'a, 'tcx> { if self.is_internal_abi(sig.abi()) { return FfiUnsafe { ty, - reason: "this function pointer has Rust-specific calling convention".into(), - help: Some( - "consider using an `extern fn(...) -> ...` \ - function pointer instead" - .into(), - ), + reason: fluent::lint::improper_ctypes_fnptr_reason, + help: Some(fluent::lint::improper_ctypes_fnptr_help), }; } @@ -1121,7 +1122,7 @@ impl<'a, 'tcx> ImproperCTypesVisitor<'a, 'tcx> { // While opaque types are checked for earlier, if a projection in a struct field // normalizes to an opaque type, then it will reach this branch. ty::Opaque(..) => { - FfiUnsafe { ty, reason: "opaque types have no C equivalent".into(), help: None } + FfiUnsafe { ty, reason: fluent::lint::improper_ctypes_opaque, help: None } } // `extern "C" fn` functions can have type parameters, which may or may not be FFI-safe, @@ -1147,8 +1148,8 @@ impl<'a, 'tcx> ImproperCTypesVisitor<'a, 'tcx> { &mut self, ty: Ty<'tcx>, sp: Span, - note: &str, - help: Option<&str>, + note: DiagnosticMessage, + help: Option<DiagnosticMessage>, ) { let lint = match self.mode { CItemKind::Declaration => IMPROPER_CTYPES, @@ -1160,18 +1161,17 @@ impl<'a, 'tcx> ImproperCTypesVisitor<'a, 'tcx> { CItemKind::Declaration => "block", CItemKind::Definition => "fn", }; - let mut diag = lint.build(&format!( - "`extern` {} uses type `{}`, which is not FFI-safe", - item_description, ty - )); - diag.span_label(sp, "not FFI-safe"); + let mut diag = lint.build(fluent::lint::improper_ctypes); + diag.set_arg("ty", ty); + diag.set_arg("desc", item_description); + diag.span_label(sp, fluent::lint::label); if let Some(help) = help { diag.help(help); } diag.note(note); if let ty::Adt(def, _) = ty.kind() { if let Some(sp) = self.cx.tcx.hir().span_if_local(def.did()) { - diag.span_note(sp, "the type is defined here"); + diag.span_note(sp, fluent::lint::note); } } diag.emit(); @@ -1183,7 +1183,7 @@ impl<'a, 'tcx> ImproperCTypesVisitor<'a, 'tcx> { cx: &'a LateContext<'tcx>, } - impl<'a, 'tcx> ty::fold::TypeVisitor<'tcx> for ProhibitOpaqueTypes<'a, 'tcx> { + impl<'a, 'tcx> ty::visit::TypeVisitor<'tcx> for ProhibitOpaqueTypes<'a, 'tcx> { type BreakTy = Ty<'tcx>; fn visit_ty(&mut self, ty: Ty<'tcx>) -> ControlFlow<Self::BreakTy> { @@ -1208,7 +1208,7 @@ impl<'a, 'tcx> ImproperCTypesVisitor<'a, 'tcx> { } if let Some(ty) = ty.visit_with(&mut ProhibitOpaqueTypes { cx: self.cx }).break_value() { - self.emit_ffi_unsafe_type_lint(ty, sp, "opaque types have no C equivalent", None); + self.emit_ffi_unsafe_type_lint(ty, sp, fluent::lint::improper_ctypes_opaque, None); true } else { false @@ -1250,13 +1250,18 @@ impl<'a, 'tcx> ImproperCTypesVisitor<'a, 'tcx> { match self.check_type_for_ffi(&mut FxHashSet::default(), ty) { FfiResult::FfiSafe => {} FfiResult::FfiPhantom(ty) => { - self.emit_ffi_unsafe_type_lint(ty, sp, "composed only of `PhantomData`", None); + self.emit_ffi_unsafe_type_lint( + ty, + sp, + fluent::lint::improper_ctypes_only_phantomdata, + None, + ); } // If `ty` is a `repr(transparent)` newtype, and the non-zero-sized type is a generic // argument, which after substitution, is `()`, then this branch can be hit. FfiResult::FfiUnsafe { ty, .. } if is_return_type && ty.is_unit() => {} FfiResult::FfiUnsafe { ty, reason, help } => { - self.emit_ffi_unsafe_type_lint(ty, sp, &reason, help.as_deref()); + self.emit_ffi_unsafe_type_lint(ty, sp, reason, help); } } } @@ -1383,12 +1388,9 @@ impl<'tcx> LateLintPass<'tcx> for VariantSizeDifferences { VARIANT_SIZE_DIFFERENCES, enum_definition.variants[largest_index].span, |lint| { - lint.build(&format!( - "enum variant is more than three times \ - larger ({} bytes) than the next largest", - largest - )) - .emit(); + lint.build(fluent::lint::variant_size_differences) + .set_arg("largest", largest) + .emit(); }, ); } @@ -1511,13 +1513,13 @@ impl InvalidAtomicOrdering { { cx.struct_span_lint(INVALID_ATOMIC_ORDERING, ordering_arg.span, |diag| { if method == sym::load { - diag.build("atomic loads cannot have `Release` or `AcqRel` ordering") - .help("consider using ordering modes `Acquire`, `SeqCst` or `Relaxed`") + diag.build(fluent::lint::atomic_ordering_load) + .help(fluent::lint::help) .emit() } else { debug_assert_eq!(method, sym::store); - diag.build("atomic stores cannot have `Acquire` or `AcqRel` ordering") - .help("consider using ordering modes `Release`, `SeqCst` or `Relaxed`") + diag.build(fluent::lint::atomic_ordering_store) + .help(fluent::lint::help) .emit(); } }); @@ -1532,8 +1534,8 @@ impl InvalidAtomicOrdering { && 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") - .help("consider using ordering modes `Acquire`, `Release`, `AcqRel` or `SeqCst`") + diag.build(fluent::lint::atomic_ordering_fence) + .help(fluent::lint::help) .emit(); }); } @@ -1552,15 +1554,20 @@ impl InvalidAtomicOrdering { 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(); - }); + #[derive(LintDiagnostic)] + #[lint(lint::atomic_ordering_invalid)] + #[help] + struct InvalidAtomicOrderingDiag { + method: Symbol, + #[label] + fail_order_arg_span: Span, + } + + cx.emit_spanned_lint( + INVALID_ATOMIC_ORDERING, + fail_order_arg.span, + InvalidAtomicOrderingDiag { method, fail_order_arg_span: fail_order_arg.span }, + ); } let Some(success_ordering) = Self::match_ordering(cx, success_order_arg) else { return }; @@ -1577,18 +1584,20 @@ impl InvalidAtomicOrdering { 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(); + diag.build(fluent::lint::atomic_ordering_invalid_fail_success) + .set_arg("method", method) + .set_arg("fail_ordering", fail_ordering) + .set_arg("success_ordering", success_ordering) + .set_arg("success_suggestion", success_suggestion) + .span_label(fail_order_arg.span, fluent::lint::fail_label) + .span_label(success_order_arg.span, fluent::lint::success_label) + .span_suggestion_short( + success_order_arg.span, + fluent::lint::suggestion, + format!("std::sync::atomic::Ordering::{success_suggestion}"), + Applicability::MaybeIncorrect, + ) + .emit(); }); } } diff --git a/compiler/rustc_lint/src/unused.rs b/compiler/rustc_lint/src/unused.rs index 73f353e62c1..53269d18527 100644 --- a/compiler/rustc_lint/src/unused.rs +++ b/compiler/rustc_lint/src/unused.rs @@ -3,7 +3,7 @@ use crate::{EarlyContext, EarlyLintPass, LateContext, LateLintPass, LintContext} use rustc_ast as ast; use rustc_ast::util::{classify, parser}; use rustc_ast::{ExprKind, StmtKind}; -use rustc_errors::{pluralize, Applicability, MultiSpan}; +use rustc_errors::{fluent, pluralize, Applicability, MultiSpan}; use rustc_hir as hir; use rustc_hir::def::{DefKind, Res}; use rustc_hir::def_id::DefId; @@ -155,22 +155,23 @@ impl<'tcx> LateLintPass<'tcx> for UnusedResults { if let Some(must_use_op) = must_use_op { cx.struct_span_lint(UNUSED_MUST_USE, expr.span, |lint| { - let mut lint = lint.build(&format!("unused {} that must be used", must_use_op)); - lint.span_label(expr.span, &format!("the {} produces a value", must_use_op)); - lint.span_suggestion_verbose( - expr.span.shrink_to_lo(), - "use `let _ = ...` to ignore the resulting value", - "let _ = ", - Applicability::MachineApplicable, - ); - lint.emit(); + lint.build(fluent::lint::unused_op) + .set_arg("op", must_use_op) + .span_label(expr.span, fluent::lint::label) + .span_suggestion_verbose( + expr.span.shrink_to_lo(), + fluent::lint::suggestion, + "let _ = ", + Applicability::MachineApplicable, + ) + .emit(); }); op_warned = true; } if !(type_permits_lack_of_use || fn_warned || op_warned) { cx.struct_span_lint(UNUSED_RESULTS, s.span, |lint| { - lint.build(&format!("unused result of type `{}`", ty)).emit(); + lint.build(fluent::lint::unused_result).set_arg("ty", ty).emit(); }); } @@ -267,23 +268,27 @@ impl<'tcx> LateLintPass<'tcx> for UnusedResults { }, ty::Closure(..) => { cx.struct_span_lint(UNUSED_MUST_USE, span, |lint| { - let mut err = lint.build(&format!( - "unused {}closure{}{} that must be used", - descr_pre, plural_suffix, descr_post, - )); - err.note("closures are lazy and do nothing unless called"); - err.emit(); + // FIXME(davidtwco): this isn't properly translatable becauses of the + // pre/post strings + lint.build(fluent::lint::unused_closure) + .set_arg("count", plural_len) + .set_arg("pre", descr_pre) + .set_arg("post", descr_post) + .note(fluent::lint::note) + .emit(); }); true } ty::Generator(..) => { cx.struct_span_lint(UNUSED_MUST_USE, span, |lint| { - let mut err = lint.build(&format!( - "unused {}generator{}{} that must be used", - descr_pre, plural_suffix, descr_post, - )); - err.note("generators are lazy and do nothing unless resumed"); - err.emit(); + // FIXME(davidtwco): this isn't properly translatable becauses of the + // pre/post strings + lint.build(fluent::lint::unused_generator) + .set_arg("count", plural_len) + .set_arg("pre", descr_pre) + .set_arg("post", descr_post) + .note(fluent::lint::note) + .emit(); }); true } @@ -305,13 +310,12 @@ impl<'tcx> LateLintPass<'tcx> for UnusedResults { ) -> bool { if let Some(attr) = cx.tcx.get_attr(def_id, sym::must_use) { cx.struct_span_lint(UNUSED_MUST_USE, span, |lint| { - let msg = format!( - "unused {}`{}`{} that must be used", - descr_pre_path, - cx.tcx.def_path_str(def_id), - descr_post_path - ); - let mut err = lint.build(&msg); + // FIXME(davidtwco): this isn't properly translatable becauses of the pre/post + // strings + let mut err = lint.build(fluent::lint::unused_def); + err.set_arg("pre", descr_pre_path); + err.set_arg("post", descr_post_path); + err.set_arg("def", cx.tcx.def_path_str(def_id)); // check for #[must_use = "..."] if let Some(note) = attr.value_str() { err.note(note.as_str()); @@ -356,20 +360,20 @@ impl<'tcx> LateLintPass<'tcx> for PathStatements { cx.struct_span_lint(PATH_STATEMENTS, s.span, |lint| { let ty = cx.typeck_results().expr_ty(expr); if ty.needs_drop(cx.tcx, cx.param_env) { - let mut lint = lint.build("path statement drops value"); + let mut lint = lint.build(fluent::lint::path_statement_drop); if let Ok(snippet) = cx.sess().source_map().span_to_snippet(expr.span) { lint.span_suggestion( s.span, - "use `drop` to clarify the intent", + fluent::lint::suggestion, format!("drop({});", snippet), Applicability::MachineApplicable, ); } else { - lint.span_help(s.span, "use `drop` to clarify the intent"); + lint.span_help(s.span, fluent::lint::suggestion); } lint.emit(); } else { - lint.build("path statement with no effect").emit(); + lint.build(fluent::lint::path_statement_no_effect).emit(); } }); } @@ -540,15 +544,19 @@ trait UnusedDelimLint { } cx.struct_span_lint(self.lint(), MultiSpan::from(vec![spans.0, spans.1]), |lint| { - let span_msg = format!("unnecessary {} around {}", Self::DELIM_STR, msg); - let mut err = lint.build(&span_msg); let replacement = vec![ (spans.0, if keep_space.0 { " ".into() } else { "".into() }), (spans.1, if keep_space.1 { " ".into() } else { "".into() }), ]; - let suggestion = format!("remove these {}", Self::DELIM_STR); - err.multipart_suggestion(&suggestion, replacement, Applicability::MachineApplicable); - err.emit(); + lint.build(fluent::lint::unused_delim) + .set_arg("delim", Self::DELIM_STR) + .set_arg("item", msg) + .multipart_suggestion( + fluent::lint::suggestion, + replacement, + Applicability::MachineApplicable, + ) + .emit(); }); } @@ -1110,7 +1118,7 @@ impl UnusedImportBraces { }; cx.struct_span_lint(UNUSED_IMPORT_BRACES, item.span, |lint| { - lint.build(&format!("braces around {} is unnecessary", node_name)).emit(); + lint.build(fluent::lint::unused_import_braces).set_arg("node", node_name).emit(); }); } } @@ -1161,15 +1169,13 @@ impl<'tcx> LateLintPass<'tcx> for UnusedAllocation { for adj in cx.typeck_results().expr_adjustments(e) { if let adjustment::Adjust::Borrow(adjustment::AutoBorrow::Ref(_, m)) = adj.kind { cx.struct_span_lint(UNUSED_ALLOCATION, e.span, |lint| { - let msg = match m { - adjustment::AutoBorrowMutability::Not => { - "unnecessary allocation, use `&` instead" - } + lint.build(match m { + adjustment::AutoBorrowMutability::Not => fluent::lint::unused_allocation, adjustment::AutoBorrowMutability::Mut { .. } => { - "unnecessary allocation, use `&mut` instead" + fluent::lint::unused_allocation_mut } - }; - lint.build(msg).emit(); + }) + .emit(); }); } } diff --git a/compiler/rustc_lint_defs/src/builtin.rs b/compiler/rustc_lint_defs/src/builtin.rs index d52455e2576..40601bb5aad 100644 --- a/compiler/rustc_lint_defs/src/builtin.rs +++ b/compiler/rustc_lint_defs/src/builtin.rs @@ -3231,6 +3231,7 @@ declare_lint_pass! { UNEXPECTED_CFGS, DEPRECATED_WHERE_CLAUSE_LOCATION, TEST_UNSTABLE_LINT, + FFI_UNWIND_CALLS, ] } @@ -3896,3 +3897,42 @@ declare_lint! { "this unstable lint is only for testing", @feature_gate = sym::test_unstable_lint; } + +declare_lint! { + /// The `ffi_unwind_calls` lint detects calls to foreign functions or function pointers with + /// `C-unwind` or other FFI-unwind ABIs. + /// + /// ### Example + /// + /// ```rust,ignore (need FFI) + /// #![feature(ffi_unwind_calls)] + /// #![feature(c_unwind)] + /// + /// # mod impl { + /// # #[no_mangle] + /// # pub fn "C-unwind" fn foo() {} + /// # } + /// + /// extern "C-unwind" { + /// fn foo(); + /// } + /// + /// fn bar() { + /// unsafe { foo(); } + /// let ptr: unsafe extern "C-unwind" fn() = foo; + /// unsafe { ptr(); } + /// } + /// ``` + /// + /// {{produces}} + /// + /// ### Explanation + /// + /// For crates containing such calls, if they are compiled with `-C panic=unwind` then the + /// produced library cannot be linked with crates compiled with `-C panic=abort`. For crates + /// that desire this ability it is therefore necessary to avoid such calls. + pub FFI_UNWIND_CALLS, + Allow, + "call to foreign functions or function pointers with FFI-unwind ABI", + @feature_gate = sym::c_unwind; +} diff --git a/compiler/rustc_llvm/llvm-wrapper/RustWrapper.cpp b/compiler/rustc_llvm/llvm-wrapper/RustWrapper.cpp index a52d5340242..8c5b4e2dc96 100644 --- a/compiler/rustc_llvm/llvm-wrapper/RustWrapper.cpp +++ b/compiler/rustc_llvm/llvm-wrapper/RustWrapper.cpp @@ -1865,3 +1865,11 @@ extern "C" void LLVMRustGetMangledName(LLVMValueRef V, RustStringRef Str) { GlobalValue *GV = unwrap<GlobalValue>(V); Mangler().getNameWithPrefix(OS, GV, true); } + +// LLVMGetAggregateElement was added in LLVM 15. For earlier LLVM versions just +// use its implementation. +#if LLVM_VERSION_LT(15, 0) +extern "C" LLVMValueRef LLVMGetAggregateElement(LLVMValueRef C, unsigned Idx) { + return wrap(unwrap<Constant>(C)->getAggregateElement(Idx)); +} +#endif diff --git a/compiler/rustc_macros/src/diagnostics/diagnostic.rs b/compiler/rustc_macros/src/diagnostics/diagnostic.rs index d0c86527189..027f377b0ac 100644 --- a/compiler/rustc_macros/src/diagnostics/diagnostic.rs +++ b/compiler/rustc_macros/src/diagnostics/diagnostic.rs @@ -1,125 +1,54 @@ #![deny(unused_must_use)] -use crate::diagnostics::error::{ - invalid_nested_attr, span_err, throw_invalid_attr, throw_invalid_nested_attr, throw_span_err, - SessionDiagnosticDeriveError, -}; -use crate::diagnostics::utils::{ - report_error_if_not_applied_to_span, report_type_error, type_is_unit, type_matches_path, - Applicability, FieldInfo, FieldInnerTy, HasFieldMap, SetOnce, -}; -use proc_macro2::{Ident, TokenStream}; -use quote::{format_ident, quote}; -use std::collections::HashMap; -use std::str::FromStr; -use syn::{ - parse_quote, spanned::Spanned, Attribute, Meta, MetaList, MetaNameValue, NestedMeta, Path, Type, -}; -use synstructure::{BindingInfo, Structure}; +use crate::diagnostics::diagnostic_builder::{DiagnosticDeriveBuilder, DiagnosticDeriveKind}; +use crate::diagnostics::error::{span_err, DiagnosticDeriveError}; +use crate::diagnostics::utils::{build_field_mapping, SetOnce}; +use proc_macro2::TokenStream; +use quote::quote; +use syn::spanned::Spanned; +use synstructure::Structure; /// The central struct for constructing the `into_diagnostic` method from an annotated struct. pub(crate) struct SessionDiagnosticDerive<'a> { structure: Structure<'a>, - builder: SessionDiagnosticDeriveBuilder, + sess: syn::Ident, + builder: DiagnosticDeriveBuilder, } impl<'a> SessionDiagnosticDerive<'a> { pub(crate) fn new(diag: syn::Ident, sess: syn::Ident, structure: Structure<'a>) -> Self { - // Build the mapping of field names to fields. This allows attributes to peek values from - // other fields. - let mut fields_map = HashMap::new(); - - // Convenience bindings. - let ast = structure.ast(); - - if let syn::Data::Struct(syn::DataStruct { fields, .. }) = &ast.data { - for field in fields.iter() { - if let Some(ident) = &field.ident { - fields_map.insert(ident.to_string(), quote! { &self.#ident }); - } - } - } - Self { - builder: SessionDiagnosticDeriveBuilder { + builder: DiagnosticDeriveBuilder { diag, - sess, - fields: fields_map, + fields: build_field_mapping(&structure), kind: None, code: None, slug: None, }, + sess, structure, } } pub(crate) fn into_tokens(self) -> TokenStream { - let SessionDiagnosticDerive { mut structure, mut builder } = self; + let SessionDiagnosticDerive { mut structure, sess, mut builder } = self; let ast = structure.ast(); - let attrs = &ast.attrs; - let (implementation, param_ty) = { if let syn::Data::Struct(..) = ast.data { - let preamble = { - let preamble = attrs.iter().map(|attr| { - builder - .generate_structure_code(attr) - .unwrap_or_else(|v| v.to_compile_error()) - }); - - quote! { - #(#preamble)*; - } - }; - - // Keep track of which fields are subdiagnostics or have no attributes. - let mut subdiagnostics_or_empty = std::collections::HashSet::new(); - - // Generates calls to `span_label` and similar functions based on the attributes - // on fields. Code for suggestions uses formatting machinery and the value of - // other fields - because any given field can be referenced multiple times, it - // should be accessed through a borrow. When passing fields to `add_subdiagnostic` - // or `set_arg` (which happens below) for Fluent, we want to move the data, so that - // has to happen in a separate pass over the fields. - let attrs = structure - .clone() - .filter(|field_binding| { - let attrs = &field_binding.ast().attrs; - - (!attrs.is_empty() - && attrs.iter().all(|attr| { - "subdiagnostic" - != attr.path.segments.last().unwrap().ident.to_string() - })) - || { - subdiagnostics_or_empty.insert(field_binding.binding.clone()); - false - } - }) - .each(|field_binding| builder.generate_field_attrs_code(field_binding)); - - structure.bind_with(|_| synstructure::BindStyle::Move); - // When a field has attributes like `#[label]` or `#[note]` then it doesn't - // need to be passed as an argument to the diagnostic. But when a field has no - // attributes or a `#[subdiagnostic]` attribute then it must be passed as an - // argument to the diagnostic so that it can be referred to by Fluent messages. - let args = structure - .filter(|field_binding| { - subdiagnostics_or_empty.contains(&field_binding.binding) - }) - .each(|field_binding| builder.generate_field_attrs_code(field_binding)); + let preamble = builder.preamble(&structure); + let (attrs, args) = builder.body(&mut structure); let span = ast.span().unwrap(); - let (diag, sess) = (&builder.diag, &builder.sess); - let init = match (builder.kind, builder.slug) { + let diag = &builder.diag; + let init = match (builder.kind.value(), builder.slug.value()) { (None, _) => { span_err(span, "diagnostic kind not specified") .help("use the `#[error(...)]` attribute to create an error") .emit(); - return SessionDiagnosticDeriveError::ErrorHandled.to_compile_error(); + return DiagnosticDeriveError::ErrorHandled.to_compile_error(); } - (Some((kind, _)), None) => { + (Some(kind), None) => { span_err(span, "diagnostic slug not specified") .help(&format!( "specify the slug as the first argument to the attribute, such as \ @@ -127,14 +56,20 @@ impl<'a> SessionDiagnosticDerive<'a> { kind.descr() )) .emit(); - return SessionDiagnosticDeriveError::ErrorHandled.to_compile_error(); + return DiagnosticDeriveError::ErrorHandled.to_compile_error(); } - (Some((SessionDiagnosticKind::Error, _)), Some((slug, _))) => { + (Some(DiagnosticDeriveKind::Lint), _) => { + span_err(span, "only `#[error(..)]` and `#[warn(..)]` are supported") + .help("use the `#[error(...)]` attribute to create a error") + .emit(); + return DiagnosticDeriveError::ErrorHandled.to_compile_error(); + } + (Some(DiagnosticDeriveKind::Error), Some(slug)) => { quote! { let mut #diag = #sess.struct_err(rustc_errors::fluent::#slug); } } - (Some((SessionDiagnosticKind::Warn, _)), Some((slug, _))) => { + (Some(DiagnosticDeriveKind::Warn), Some(slug)) => { quote! { let mut #diag = #sess.struct_warn(rustc_errors::fluent::#slug); } @@ -153,10 +88,12 @@ impl<'a> SessionDiagnosticDerive<'a> { #diag }; let param_ty = match builder.kind { - Some((SessionDiagnosticKind::Error, _)) => { + Some((DiagnosticDeriveKind::Error, _)) => { quote! { rustc_errors::ErrorGuaranteed } } - Some((SessionDiagnosticKind::Warn, _)) => quote! { () }, + Some((DiagnosticDeriveKind::Lint | DiagnosticDeriveKind::Warn, _)) => { + quote! { () } + } _ => unreachable!(), }; @@ -168,13 +105,12 @@ impl<'a> SessionDiagnosticDerive<'a> { ) .emit(); - let implementation = SessionDiagnosticDeriveError::ErrorHandled.to_compile_error(); + let implementation = DiagnosticDeriveError::ErrorHandled.to_compile_error(); let param_ty = quote! { rustc_errors::ErrorGuaranteed }; (implementation, param_ty) } }; - let sess = &builder.sess; structure.gen_impl(quote! { gen impl<'__session_diagnostic_sess> rustc_session::SessionDiagnostic<'__session_diagnostic_sess, #param_ty> for @Self @@ -191,525 +127,99 @@ impl<'a> SessionDiagnosticDerive<'a> { } } -/// What kind of session diagnostic is being derived - an error or a warning? -#[derive(Copy, Clone)] -enum SessionDiagnosticKind { - /// `#[error(..)]` - Error, - /// `#[warn(..)]` - Warn, +/// The central struct for constructing the `decorate_lint` method from an annotated struct. +pub(crate) struct LintDiagnosticDerive<'a> { + structure: Structure<'a>, + builder: DiagnosticDeriveBuilder, } -impl SessionDiagnosticKind { - /// Returns human-readable string corresponding to the kind. - fn descr(&self) -> &'static str { - match self { - SessionDiagnosticKind::Error => "error", - SessionDiagnosticKind::Warn => "warning", +impl<'a> LintDiagnosticDerive<'a> { + pub(crate) fn new(diag: syn::Ident, structure: Structure<'a>) -> Self { + Self { + builder: DiagnosticDeriveBuilder { + diag, + fields: build_field_mapping(&structure), + kind: None, + code: None, + slug: None, + }, + structure, } } -} - -/// Tracks persistent information required for building up the individual calls to diagnostic -/// methods for the final generated method. This is a separate struct to `SessionDiagnosticDerive` -/// only to be able to destructure and split `self.builder` and the `self.structure` up to avoid a -/// double mut borrow later on. -struct SessionDiagnosticDeriveBuilder { - /// Name of the session parameter that's passed in to the `as_error` method. - sess: syn::Ident, - /// The identifier to use for the generated `DiagnosticBuilder` instance. - diag: syn::Ident, - - /// Store a map of field name to its corresponding field. This is built on construction of the - /// derive builder. - fields: HashMap<String, TokenStream>, - - /// Kind of diagnostic requested via the struct attribute. - kind: Option<(SessionDiagnosticKind, proc_macro::Span)>, - /// Slug is a mandatory part of the struct attribute as corresponds to the Fluent message that - /// has the actual diagnostic message. - slug: Option<(Path, proc_macro::Span)>, - /// Error codes are a optional part of the struct attribute - this is only set to detect - /// multiple specifications. - code: Option<(String, proc_macro::Span)>, -} - -impl HasFieldMap for SessionDiagnosticDeriveBuilder { - fn get_field_binding(&self, field: &String) -> Option<&TokenStream> { - self.fields.get(field) - } -} - -impl SessionDiagnosticDeriveBuilder { - /// Establishes state in the `SessionDiagnosticDeriveBuilder` resulting from the struct - /// attributes like `#[error(..)`, such as the diagnostic kind and slug. Generates - /// diagnostic builder calls for setting error code and creating note/help messages. - fn generate_structure_code( - &mut self, - attr: &Attribute, - ) -> Result<TokenStream, SessionDiagnosticDeriveError> { - let diag = &self.diag; - let span = attr.span().unwrap(); - - let name = attr.path.segments.last().unwrap().ident.to_string(); - let name = name.as_str(); - let meta = attr.parse_meta()?; - - let is_help_or_note = matches!(name, "help" | "note"); - - let nested = match meta { - // Most attributes are lists, like `#[error(..)]`/`#[warning(..)]` for most cases or - // `#[help(..)]`/`#[note(..)]` when the user is specifying a alternative slug. - Meta::List(MetaList { ref nested, .. }) => nested, - // Subdiagnostics without spans can be applied to the type too, and these are just - // paths: `#[help]` and `#[note]` - Meta::Path(_) if is_help_or_note => { - let fn_name = proc_macro2::Ident::new(name, attr.span()); - return Ok(quote! { #diag.#fn_name(rustc_errors::fluent::_subdiag::#fn_name); }); - } - _ => throw_invalid_attr!(attr, &meta), - }; - - // Check the kind before doing any further processing so that there aren't misleading - // "no kind specified" errors if there are failures later. - match name { - "error" => self.kind.set_once((SessionDiagnosticKind::Error, span)), - "warning" => self.kind.set_once((SessionDiagnosticKind::Warn, span)), - "help" | "note" => (), - _ => throw_invalid_attr!(attr, &meta, |diag| { - diag.help("only `error`, `warning`, `help` and `note` are valid attributes") - }), - } - // First nested element should always be the path, e.g. `#[error(typeck::invalid)]` or - // `#[help(typeck::another_help)]`. - let mut nested_iter = nested.into_iter(); - if let Some(nested_attr) = nested_iter.next() { - // Report an error if there are any other list items after the path. - if is_help_or_note && nested_iter.next().is_some() { - throw_invalid_nested_attr!(attr, &nested_attr, |diag| { - diag.help("`help` and `note` struct attributes can only have one argument") - }); - } - - match nested_attr { - NestedMeta::Meta(Meta::Path(path)) if is_help_or_note => { - let fn_name = proc_macro2::Ident::new(name, attr.span()); - return Ok(quote! { #diag.#fn_name(rustc_errors::fluent::#path); }); - } - NestedMeta::Meta(Meta::Path(path)) => { - self.slug.set_once((path.clone(), span)); - } - NestedMeta::Meta(meta @ Meta::NameValue(_)) - if !is_help_or_note - && meta.path().segments.last().unwrap().ident.to_string() == "code" => - { - // don't error for valid follow-up attributes - } - nested_attr => throw_invalid_nested_attr!(attr, &nested_attr, |diag| { - diag.help("first argument of the attribute should be the diagnostic slug") - }), - }; - } + pub(crate) fn into_tokens(self) -> TokenStream { + let LintDiagnosticDerive { mut structure, mut builder } = self; - // Remaining attributes are optional, only `code = ".."` at the moment. - let mut tokens = Vec::new(); - for nested_attr in nested_iter { - let meta = match nested_attr { - syn::NestedMeta::Meta(meta) => meta, - _ => throw_invalid_nested_attr!(attr, &nested_attr), - }; + let ast = structure.ast(); + let implementation = { + if let syn::Data::Struct(..) = ast.data { + let preamble = builder.preamble(&structure); + let (attrs, args) = builder.body(&mut structure); - let path = meta.path(); - let nested_name = path.segments.last().unwrap().ident.to_string(); - // Struct attributes are only allowed to be applied once, and the diagnostic - // changes will be set in the initialisation code. - if let Meta::NameValue(MetaNameValue { lit: syn::Lit::Str(s), .. }) = &meta { - let span = s.span().unwrap(); - match nested_name.as_str() { - "code" => { - self.code.set_once((s.value(), span)); - let code = &self.code.as_ref().map(|(v, _)| v); - tokens.push(quote! { - #diag.code(rustc_errors::DiagnosticId::Error(#code.to_string())); - }); + let diag = &builder.diag; + let span = ast.span().unwrap(); + let init = match (builder.kind.value(), builder.slug.value()) { + (None, _) => { + span_err(span, "diagnostic kind not specified") + .help("use the `#[error(...)]` attribute to create an error") + .emit(); + return DiagnosticDeriveError::ErrorHandled.to_compile_error(); } - _ => invalid_nested_attr(attr, &nested_attr) - .help("only `code` is a valid nested attributes following the slug") - .emit(), - } - } else { - invalid_nested_attr(attr, &nested_attr).emit() - } - } - - Ok(tokens.drain(..).collect()) - } - - fn generate_field_attrs_code(&mut self, binding_info: &BindingInfo<'_>) -> TokenStream { - let field = binding_info.ast(); - let field_binding = &binding_info.binding; - - let inner_ty = FieldInnerTy::from_type(&field.ty); - - // When generating `set_arg` or `add_subdiagnostic` calls, move data rather than - // borrow it to avoid requiring clones - this must therefore be the last use of - // each field (for example, any formatting machinery that might refer to a field - // should be generated already). - if field.attrs.is_empty() { - let diag = &self.diag; - let ident = field.ident.as_ref().unwrap(); - quote! { - #diag.set_arg( - stringify!(#ident), - #field_binding - ); - } - } else { - field - .attrs - .iter() - .map(move |attr| { - let name = attr.path.segments.last().unwrap().ident.to_string(); - let (binding, needs_destructure) = match (name.as_str(), &inner_ty) { - // `primary_span` can accept a `Vec<Span>` so don't destructure that. - ("primary_span", FieldInnerTy::Vec(_)) => { - (quote! { #field_binding.clone() }, false) + (Some(kind), None) => { + span_err(span, "diagnostic slug not specified") + .help(&format!( + "specify the slug as the first argument to the attribute, such as \ + `#[{}(typeck::example_error)]`", + kind.descr() + )) + .emit(); + return DiagnosticDeriveError::ErrorHandled.to_compile_error(); + } + (Some(DiagnosticDeriveKind::Error | DiagnosticDeriveKind::Warn), _) => { + span_err(span, "only `#[lint(..)]` is supported") + .help("use the `#[lint(...)]` attribute to create a lint") + .emit(); + return DiagnosticDeriveError::ErrorHandled.to_compile_error(); + } + (Some(DiagnosticDeriveKind::Lint), Some(slug)) => { + quote! { + let mut #diag = #diag.build(rustc_errors::fluent::#slug); } - // `subdiagnostics` are not derefed because they are bound by value. - ("subdiagnostic", _) => (quote! { #field_binding }, true), - _ => (quote! { *#field_binding }, true), - }; - - let generated_code = self - .generate_inner_field_code( - attr, - FieldInfo { - binding: binding_info, - ty: inner_ty.inner_type().unwrap_or(&field.ty), - span: &field.span(), - }, - binding, - ) - .unwrap_or_else(|v| v.to_compile_error()); - - if needs_destructure { - inner_ty.with(field_binding, generated_code) - } else { - generated_code } - }) - .collect() - } - } - - fn generate_inner_field_code( - &mut self, - attr: &Attribute, - info: FieldInfo<'_>, - binding: TokenStream, - ) -> Result<TokenStream, SessionDiagnosticDeriveError> { - let meta = attr.parse_meta()?; - match meta { - Meta::Path(_) => self.generate_inner_field_code_path(attr, info, binding), - Meta::List(MetaList { .. }) => self.generate_inner_field_code_list(attr, info, binding), - _ => throw_invalid_attr!(attr, &meta), - } - } - - fn generate_inner_field_code_path( - &mut self, - attr: &Attribute, - info: FieldInfo<'_>, - binding: TokenStream, - ) -> Result<TokenStream, SessionDiagnosticDeriveError> { - assert!(matches!(attr.parse_meta()?, Meta::Path(_))); - let diag = &self.diag; - - let meta = attr.parse_meta()?; - - let ident = &attr.path.segments.last().unwrap().ident; - let name = ident.to_string(); - let name = name.as_str(); - match name { - "skip_arg" => { - // Don't need to do anything - by virtue of the attribute existing, the - // `set_arg` call will not be generated. - Ok(quote! {}) - } - "primary_span" => { - report_error_if_not_applied_to_span(attr, &info)?; - Ok(quote! { - #diag.set_span(#binding); - }) - } - "label" => { - report_error_if_not_applied_to_span(attr, &info)?; - Ok(self.add_spanned_subdiagnostic(binding, ident, parse_quote! { _subdiag::label })) - } - "note" | "help" => { - let path = match name { - "note" => parse_quote! { _subdiag::note }, - "help" => parse_quote! { _subdiag::help }, - _ => unreachable!(), }; - if type_matches_path(&info.ty, &["rustc_span", "Span"]) { - Ok(self.add_spanned_subdiagnostic(binding, ident, path)) - } else if type_is_unit(&info.ty) { - Ok(self.add_subdiagnostic(ident, path)) - } else { - report_type_error(attr, "`Span` or `()`")?; - } - } - "subdiagnostic" => Ok(quote! { #diag.subdiagnostic(#binding); }), - _ => throw_invalid_attr!(attr, &meta, |diag| { - diag.help( - "only `skip_arg`, `primary_span`, `label`, `note`, `help` and `subdiagnostic` \ - are valid field attributes", - ) - }), - } - } - - fn generate_inner_field_code_list( - &mut self, - attr: &Attribute, - info: FieldInfo<'_>, - binding: TokenStream, - ) -> Result<TokenStream, SessionDiagnosticDeriveError> { - let meta = attr.parse_meta()?; - let Meta::List(MetaList { ref path, ref nested, .. }) = meta else { unreachable!() }; - - let ident = &attr.path.segments.last().unwrap().ident; - let name = path.segments.last().unwrap().ident.to_string(); - let name = name.as_ref(); - match name { - "suggestion" | "suggestion_short" | "suggestion_hidden" | "suggestion_verbose" => { - return self.generate_inner_field_code_suggestion(attr, info); - } - "label" | "help" | "note" => (), - _ => throw_invalid_attr!(attr, &meta, |diag| { - diag.help( - "only `label`, `note`, `help` or `suggestion{,_short,_hidden,_verbose}` are \ - valid field attributes", - ) - }), - } - // For `#[label(..)]`, `#[note(..)]` and `#[help(..)]`, the first nested element must be a - // path, e.g. `#[label(typeck::label)]`. - let mut nested_iter = nested.into_iter(); - let msg = match nested_iter.next() { - Some(NestedMeta::Meta(Meta::Path(path))) => path.clone(), - Some(nested_attr) => throw_invalid_nested_attr!(attr, &nested_attr), - None => throw_invalid_attr!(attr, &meta), - }; - - // None of these attributes should have anything following the slug. - if nested_iter.next().is_some() { - throw_invalid_attr!(attr, &meta); - } - - match name { - "label" => { - report_error_if_not_applied_to_span(attr, &info)?; - Ok(self.add_spanned_subdiagnostic(binding, ident, msg)) - } - "note" | "help" if type_matches_path(&info.ty, &["rustc_span", "Span"]) => { - Ok(self.add_spanned_subdiagnostic(binding, ident, msg)) - } - "note" | "help" if type_is_unit(&info.ty) => Ok(self.add_subdiagnostic(ident, msg)), - "note" | "help" => { - report_type_error(attr, "`Span` or `()`")?; - } - _ => unreachable!(), - } - } - - fn generate_inner_field_code_suggestion( - &mut self, - attr: &Attribute, - info: FieldInfo<'_>, - ) -> Result<TokenStream, SessionDiagnosticDeriveError> { - let diag = &self.diag; - - let mut meta = attr.parse_meta()?; - let Meta::List(MetaList { ref path, ref mut nested, .. }) = meta else { unreachable!() }; - - let (span_field, mut applicability) = self.span_and_applicability_of_ty(info)?; - - let mut msg = None; - let mut code = None; - - let mut nested_iter = nested.into_iter().peekable(); - if let Some(nested_attr) = nested_iter.peek() { - if let NestedMeta::Meta(Meta::Path(path)) = nested_attr { - msg = Some(path.clone()); - } - }; - // Move the iterator forward if a path was found (don't otherwise so that - // code/applicability can be found or an error emitted). - if msg.is_some() { - let _ = nested_iter.next(); - } - - for nested_attr in nested_iter { - let meta = match nested_attr { - syn::NestedMeta::Meta(ref meta) => meta, - syn::NestedMeta::Lit(_) => throw_invalid_nested_attr!(attr, &nested_attr), - }; - - let nested_name = meta.path().segments.last().unwrap().ident.to_string(); - let nested_name = nested_name.as_str(); - match meta { - Meta::NameValue(MetaNameValue { lit: syn::Lit::Str(s), .. }) => { - let span = meta.span().unwrap(); - match nested_name { - "code" => { - let formatted_str = self.build_format(&s.value(), s.span()); - code = Some(formatted_str); - } - "applicability" => { - applicability = match applicability { - Some(v) => { - span_err( - span, - "applicability cannot be set in both the field and \ - attribute", - ) - .emit(); - Some(v) - } - None => match Applicability::from_str(&s.value()) { - Ok(v) => Some(quote! { #v }), - Err(()) => { - span_err(span, "invalid applicability").emit(); - None - } - }, - } - } - _ => throw_invalid_nested_attr!(attr, &nested_attr, |diag| { - diag.help( - "only `message`, `code` and `applicability` are valid field \ - attributes", - ) - }), + let implementation = quote! { + #init + #preamble + match self { + #attrs } - } - _ => throw_invalid_nested_attr!(attr, &nested_attr, |diag| { - if matches!(meta, Meta::Path(_)) { - diag.help("a diagnostic slug must be the first argument to the attribute") - } else { - diag + match self { + #args } - }), - } - } - - let applicability = - applicability.unwrap_or_else(|| quote!(rustc_errors::Applicability::Unspecified)); - - let name = path.segments.last().unwrap().ident.to_string(); - let method = format_ident!("span_{}", name); - - let msg = msg.unwrap_or_else(|| parse_quote! { _subdiag::suggestion }); - let msg = quote! { rustc_errors::fluent::#msg }; - let code = code.unwrap_or_else(|| quote! { String::new() }); - - Ok(quote! { #diag.#method(#span_field, #msg, #code, #applicability); }) - } - - /// Adds a spanned subdiagnostic by generating a `diag.span_$kind` call with the current slug - /// and `fluent_attr_identifier`. - fn add_spanned_subdiagnostic( - &self, - field_binding: TokenStream, - kind: &Ident, - fluent_attr_identifier: Path, - ) -> TokenStream { - let diag = &self.diag; - let fn_name = format_ident!("span_{}", kind); - quote! { - #diag.#fn_name( - #field_binding, - rustc_errors::fluent::#fluent_attr_identifier - ); - } - } + #diag.emit(); + }; - /// Adds a subdiagnostic by generating a `diag.span_$kind` call with the current slug - /// and `fluent_attr_identifier`. - fn add_subdiagnostic(&self, kind: &Ident, fluent_attr_identifier: Path) -> TokenStream { - let diag = &self.diag; - quote! { - #diag.#kind(rustc_errors::fluent::#fluent_attr_identifier); - } - } + implementation + } else { + span_err( + ast.span().unwrap(), + "`#[derive(LintDiagnostic)]` can only be used on structs", + ) + .emit(); - fn span_and_applicability_of_ty( - &self, - info: FieldInfo<'_>, - ) -> Result<(TokenStream, Option<TokenStream>), SessionDiagnosticDeriveError> { - match &info.ty { - // If `ty` is `Span` w/out applicability, then use `Applicability::Unspecified`. - ty @ Type::Path(..) if type_matches_path(ty, &["rustc_span", "Span"]) => { - let binding = &info.binding.binding; - Ok((quote!(*#binding), None)) + DiagnosticDeriveError::ErrorHandled.to_compile_error() } - // If `ty` is `(Span, Applicability)` then return tokens accessing those. - Type::Tuple(tup) => { - let mut span_idx = None; - let mut applicability_idx = None; - - for (idx, elem) in tup.elems.iter().enumerate() { - if type_matches_path(elem, &["rustc_span", "Span"]) { - if span_idx.is_none() { - span_idx = Some(syn::Index::from(idx)); - } else { - throw_span_err!( - info.span.unwrap(), - "type of field annotated with `#[suggestion(...)]` contains more \ - than one `Span`" - ); - } - } else if type_matches_path(elem, &["rustc_errors", "Applicability"]) { - if applicability_idx.is_none() { - applicability_idx = Some(syn::Index::from(idx)); - } else { - throw_span_err!( - info.span.unwrap(), - "type of field annotated with `#[suggestion(...)]` contains more \ - than one Applicability" - ); - } - } - } - - if let Some(span_idx) = span_idx { - let binding = &info.binding.binding; - let span = quote!(#binding.#span_idx); - let applicability = applicability_idx - .map(|applicability_idx| quote!(#binding.#applicability_idx)) - .unwrap_or_else(|| quote!(rustc_errors::Applicability::Unspecified)); + }; - return Ok((span, Some(applicability))); + let diag = &builder.diag; + structure.gen_impl(quote! { + gen impl<'__a> rustc_errors::DecorateLint<'__a, ()> for @Self { + fn decorate_lint(self, #diag: rustc_errors::LintDiagnosticBuilder<'__a, ()>) { + use rustc_errors::IntoDiagnosticArg; + #implementation } - - throw_span_err!(info.span.unwrap(), "wrong types for suggestion", |diag| { - diag.help( - "`#[suggestion(...)]` on a tuple field must be applied to fields of type \ - `(Span, Applicability)`", - ) - }); } - // If `ty` isn't a `Span` or `(Span, Applicability)` then emit an error. - _ => throw_span_err!(info.span.unwrap(), "wrong field type for suggestion", |diag| { - diag.help( - "`#[suggestion(...)]` should be applied to fields of type `Span` or \ - `(Span, Applicability)`", - ) - }), - } + }) } } diff --git a/compiler/rustc_macros/src/diagnostics/diagnostic_builder.rs b/compiler/rustc_macros/src/diagnostics/diagnostic_builder.rs new file mode 100644 index 00000000000..74ce1ab08c2 --- /dev/null +++ b/compiler/rustc_macros/src/diagnostics/diagnostic_builder.rs @@ -0,0 +1,590 @@ +#![deny(unused_must_use)] + +use crate::diagnostics::error::{ + invalid_nested_attr, span_err, throw_invalid_attr, throw_invalid_nested_attr, throw_span_err, + DiagnosticDeriveError, +}; +use crate::diagnostics::utils::{ + report_error_if_not_applied_to_span, report_type_error, type_is_unit, type_matches_path, + Applicability, FieldInfo, FieldInnerTy, HasFieldMap, SetOnce, +}; +use proc_macro2::{Ident, TokenStream}; +use quote::{format_ident, quote}; +use std::collections::HashMap; +use std::str::FromStr; +use syn::{ + parse_quote, spanned::Spanned, Attribute, Meta, MetaList, MetaNameValue, NestedMeta, Path, Type, +}; +use synstructure::{BindingInfo, Structure}; + +/// What kind of diagnostic is being derived - an error, a warning or a lint? +#[derive(Copy, Clone)] +pub(crate) enum DiagnosticDeriveKind { + /// `#[error(..)]` + Error, + /// `#[warn(..)]` + Warn, + /// `#[lint(..)]` + Lint, +} + +impl DiagnosticDeriveKind { + /// Returns human-readable string corresponding to the kind. + pub fn descr(&self) -> &'static str { + match self { + DiagnosticDeriveKind::Error => "error", + DiagnosticDeriveKind::Warn => "warning", + DiagnosticDeriveKind::Lint => "lint", + } + } +} + +/// Tracks persistent information required for building up individual calls to diagnostic methods +/// for generated diagnostic derives - both `SessionDiagnostic` for errors/warnings and +/// `LintDiagnostic` for lints. +pub(crate) struct DiagnosticDeriveBuilder { + /// The identifier to use for the generated `DiagnosticBuilder` instance. + pub diag: syn::Ident, + + /// Store a map of field name to its corresponding field. This is built on construction of the + /// derive builder. + pub fields: HashMap<String, TokenStream>, + + /// Kind of diagnostic requested via the struct attribute. + pub kind: Option<(DiagnosticDeriveKind, proc_macro::Span)>, + /// Slug is a mandatory part of the struct attribute as corresponds to the Fluent message that + /// has the actual diagnostic message. + pub slug: Option<(Path, proc_macro::Span)>, + /// Error codes are a optional part of the struct attribute - this is only set to detect + /// multiple specifications. + pub code: Option<(String, proc_macro::Span)>, +} + +impl HasFieldMap for DiagnosticDeriveBuilder { + fn get_field_binding(&self, field: &String) -> Option<&TokenStream> { + self.fields.get(field) + } +} + +impl DiagnosticDeriveBuilder { + pub fn preamble<'s>(&mut self, structure: &Structure<'s>) -> TokenStream { + let ast = structure.ast(); + let attrs = &ast.attrs; + let preamble = attrs.iter().map(|attr| { + self.generate_structure_code_for_attr(attr).unwrap_or_else(|v| v.to_compile_error()) + }); + + quote! { + #(#preamble)*; + } + } + + pub fn body<'s>(&mut self, structure: &mut Structure<'s>) -> (TokenStream, TokenStream) { + // Keep track of which fields are subdiagnostics or have no attributes. + let mut subdiagnostics_or_empty = std::collections::HashSet::new(); + + // Generates calls to `span_label` and similar functions based on the attributes + // on fields. Code for suggestions uses formatting machinery and the value of + // other fields - because any given field can be referenced multiple times, it + // should be accessed through a borrow. When passing fields to `add_subdiagnostic` + // or `set_arg` (which happens below) for Fluent, we want to move the data, so that + // has to happen in a separate pass over the fields. + let attrs = structure + .clone() + .filter(|field_binding| { + let attrs = &field_binding.ast().attrs; + + (!attrs.is_empty() + && attrs.iter().all(|attr| { + "subdiagnostic" != attr.path.segments.last().unwrap().ident.to_string() + })) + || { + subdiagnostics_or_empty.insert(field_binding.binding.clone()); + false + } + }) + .each(|field_binding| self.generate_field_attrs_code(field_binding)); + + structure.bind_with(|_| synstructure::BindStyle::Move); + // When a field has attributes like `#[label]` or `#[note]` then it doesn't + // need to be passed as an argument to the diagnostic. But when a field has no + // attributes or a `#[subdiagnostic]` attribute then it must be passed as an + // argument to the diagnostic so that it can be referred to by Fluent messages. + let args = structure + .filter(|field_binding| subdiagnostics_or_empty.contains(&field_binding.binding)) + .each(|field_binding| self.generate_field_attrs_code(field_binding)); + + (attrs, args) + } + + /// Establishes state in the `DiagnosticDeriveBuilder` resulting from the struct + /// attributes like `#[error(..)`, such as the diagnostic kind and slug. Generates + /// diagnostic builder calls for setting error code and creating note/help messages. + fn generate_structure_code_for_attr( + &mut self, + attr: &Attribute, + ) -> Result<TokenStream, DiagnosticDeriveError> { + let diag = &self.diag; + let span = attr.span().unwrap(); + + let name = attr.path.segments.last().unwrap().ident.to_string(); + let name = name.as_str(); + let meta = attr.parse_meta()?; + + let is_help_or_note = matches!(name, "help" | "note"); + + let nested = match meta { + // Most attributes are lists, like `#[error(..)]`/`#[warning(..)]` for most cases or + // `#[help(..)]`/`#[note(..)]` when the user is specifying a alternative slug. + Meta::List(MetaList { ref nested, .. }) => nested, + // Subdiagnostics without spans can be applied to the type too, and these are just + // paths: `#[help]` and `#[note]` + Meta::Path(_) if is_help_or_note => { + let fn_name = proc_macro2::Ident::new(name, attr.span()); + return Ok(quote! { #diag.#fn_name(rustc_errors::fluent::_subdiag::#fn_name); }); + } + _ => throw_invalid_attr!(attr, &meta), + }; + + // Check the kind before doing any further processing so that there aren't misleading + // "no kind specified" errors if there are failures later. + match name { + "error" => self.kind.set_once((DiagnosticDeriveKind::Error, span)), + "warning" => self.kind.set_once((DiagnosticDeriveKind::Warn, span)), + "lint" => self.kind.set_once((DiagnosticDeriveKind::Lint, span)), + "help" | "note" => (), + _ => throw_invalid_attr!(attr, &meta, |diag| { + diag.help("only `error`, `warning`, `help` and `note` are valid attributes") + }), + } + + // First nested element should always be the path, e.g. `#[error(typeck::invalid)]` or + // `#[help(typeck::another_help)]`. + let mut nested_iter = nested.into_iter(); + if let Some(nested_attr) = nested_iter.next() { + // Report an error if there are any other list items after the path. + if is_help_or_note && nested_iter.next().is_some() { + throw_invalid_nested_attr!(attr, &nested_attr, |diag| { + diag.help("`help` and `note` struct attributes can only have one argument") + }); + } + + match nested_attr { + NestedMeta::Meta(Meta::Path(path)) if is_help_or_note => { + let fn_name = proc_macro2::Ident::new(name, attr.span()); + return Ok(quote! { #diag.#fn_name(rustc_errors::fluent::#path); }); + } + NestedMeta::Meta(Meta::Path(path)) => { + self.slug.set_once((path.clone(), span)); + } + NestedMeta::Meta(meta @ Meta::NameValue(_)) + if !is_help_or_note + && meta.path().segments.last().unwrap().ident.to_string() == "code" => + { + // don't error for valid follow-up attributes + } + nested_attr => throw_invalid_nested_attr!(attr, &nested_attr, |diag| { + diag.help("first argument of the attribute should be the diagnostic slug") + }), + }; + } + + // Remaining attributes are optional, only `code = ".."` at the moment. + let mut tokens = Vec::new(); + for nested_attr in nested_iter { + let meta = match nested_attr { + syn::NestedMeta::Meta(meta) => meta, + _ => throw_invalid_nested_attr!(attr, &nested_attr), + }; + + let path = meta.path(); + let nested_name = path.segments.last().unwrap().ident.to_string(); + // Struct attributes are only allowed to be applied once, and the diagnostic + // changes will be set in the initialisation code. + if let Meta::NameValue(MetaNameValue { lit: syn::Lit::Str(s), .. }) = &meta { + let span = s.span().unwrap(); + match nested_name.as_str() { + "code" => { + self.code.set_once((s.value(), span)); + let code = &self.code.as_ref().map(|(v, _)| v); + tokens.push(quote! { + #diag.code(rustc_errors::DiagnosticId::Error(#code.to_string())); + }); + } + _ => invalid_nested_attr(attr, &nested_attr) + .help("only `code` is a valid nested attributes following the slug") + .emit(), + } + } else { + invalid_nested_attr(attr, &nested_attr).emit() + } + } + + Ok(tokens.drain(..).collect()) + } + + fn generate_field_attrs_code(&mut self, binding_info: &BindingInfo<'_>) -> TokenStream { + let field = binding_info.ast(); + let field_binding = &binding_info.binding; + + let inner_ty = FieldInnerTy::from_type(&field.ty); + + // When generating `set_arg` or `add_subdiagnostic` calls, move data rather than + // borrow it to avoid requiring clones - this must therefore be the last use of + // each field (for example, any formatting machinery that might refer to a field + // should be generated already). + if field.attrs.is_empty() { + let diag = &self.diag; + let ident = field.ident.as_ref().unwrap(); + quote! { + #diag.set_arg( + stringify!(#ident), + #field_binding + ); + } + } else { + field + .attrs + .iter() + .map(move |attr| { + let name = attr.path.segments.last().unwrap().ident.to_string(); + let (binding, needs_destructure) = match (name.as_str(), &inner_ty) { + // `primary_span` can accept a `Vec<Span>` so don't destructure that. + ("primary_span", FieldInnerTy::Vec(_)) => { + (quote! { #field_binding.clone() }, false) + } + // `subdiagnostics` are not derefed because they are bound by value. + ("subdiagnostic", _) => (quote! { #field_binding }, true), + _ => (quote! { *#field_binding }, true), + }; + + let generated_code = self + .generate_inner_field_code( + attr, + FieldInfo { + binding: binding_info, + ty: inner_ty.inner_type().unwrap_or(&field.ty), + span: &field.span(), + }, + binding, + ) + .unwrap_or_else(|v| v.to_compile_error()); + + if needs_destructure { + inner_ty.with(field_binding, generated_code) + } else { + generated_code + } + }) + .collect() + } + } + + fn generate_inner_field_code( + &mut self, + attr: &Attribute, + info: FieldInfo<'_>, + binding: TokenStream, + ) -> Result<TokenStream, DiagnosticDeriveError> { + let meta = attr.parse_meta()?; + match meta { + Meta::Path(_) => self.generate_inner_field_code_path(attr, info, binding), + Meta::List(MetaList { .. }) => self.generate_inner_field_code_list(attr, info, binding), + _ => throw_invalid_attr!(attr, &meta), + } + } + + fn generate_inner_field_code_path( + &mut self, + attr: &Attribute, + info: FieldInfo<'_>, + binding: TokenStream, + ) -> Result<TokenStream, DiagnosticDeriveError> { + assert!(matches!(attr.parse_meta()?, Meta::Path(_))); + let diag = &self.diag; + + let meta = attr.parse_meta()?; + + let ident = &attr.path.segments.last().unwrap().ident; + let name = ident.to_string(); + let name = name.as_str(); + match name { + "skip_arg" => { + // Don't need to do anything - by virtue of the attribute existing, the + // `set_arg` call will not be generated. + Ok(quote! {}) + } + "primary_span" => { + report_error_if_not_applied_to_span(attr, &info)?; + Ok(quote! { + #diag.set_span(#binding); + }) + } + "label" => { + report_error_if_not_applied_to_span(attr, &info)?; + Ok(self.add_spanned_subdiagnostic(binding, ident, parse_quote! { _subdiag::label })) + } + "note" | "help" => { + let path = match name { + "note" => parse_quote! { _subdiag::note }, + "help" => parse_quote! { _subdiag::help }, + _ => unreachable!(), + }; + if type_matches_path(&info.ty, &["rustc_span", "Span"]) { + Ok(self.add_spanned_subdiagnostic(binding, ident, path)) + } else if type_is_unit(&info.ty) { + Ok(self.add_subdiagnostic(ident, path)) + } else { + report_type_error(attr, "`Span` or `()`")? + } + } + "subdiagnostic" => Ok(quote! { #diag.subdiagnostic(#binding); }), + _ => throw_invalid_attr!(attr, &meta, |diag| { + diag.help( + "only `skip_arg`, `primary_span`, `label`, `note`, `help` and `subdiagnostic` \ + are valid field attributes", + ) + }), + } + } + + fn generate_inner_field_code_list( + &mut self, + attr: &Attribute, + info: FieldInfo<'_>, + binding: TokenStream, + ) -> Result<TokenStream, DiagnosticDeriveError> { + let meta = attr.parse_meta()?; + let Meta::List(MetaList { ref path, ref nested, .. }) = meta else { unreachable!() }; + + let ident = &attr.path.segments.last().unwrap().ident; + let name = path.segments.last().unwrap().ident.to_string(); + let name = name.as_ref(); + match name { + "suggestion" | "suggestion_short" | "suggestion_hidden" | "suggestion_verbose" => { + return self.generate_inner_field_code_suggestion(attr, info); + } + "label" | "help" | "note" => (), + _ => throw_invalid_attr!(attr, &meta, |diag| { + diag.help( + "only `label`, `note`, `help` or `suggestion{,_short,_hidden,_verbose}` are \ + valid field attributes", + ) + }), + } + + // For `#[label(..)]`, `#[note(..)]` and `#[help(..)]`, the first nested element must be a + // path, e.g. `#[label(typeck::label)]`. + let mut nested_iter = nested.into_iter(); + let msg = match nested_iter.next() { + Some(NestedMeta::Meta(Meta::Path(path))) => path.clone(), + Some(nested_attr) => throw_invalid_nested_attr!(attr, &nested_attr), + None => throw_invalid_attr!(attr, &meta), + }; + + // None of these attributes should have anything following the slug. + if nested_iter.next().is_some() { + throw_invalid_attr!(attr, &meta); + } + + match name { + "label" => { + report_error_if_not_applied_to_span(attr, &info)?; + Ok(self.add_spanned_subdiagnostic(binding, ident, msg)) + } + "note" | "help" if type_matches_path(&info.ty, &["rustc_span", "Span"]) => { + Ok(self.add_spanned_subdiagnostic(binding, ident, msg)) + } + "note" | "help" if type_is_unit(&info.ty) => Ok(self.add_subdiagnostic(ident, msg)), + "note" | "help" => report_type_error(attr, "`Span` or `()`")?, + _ => unreachable!(), + } + } + + fn generate_inner_field_code_suggestion( + &mut self, + attr: &Attribute, + info: FieldInfo<'_>, + ) -> Result<TokenStream, DiagnosticDeriveError> { + let diag = &self.diag; + + let mut meta = attr.parse_meta()?; + let Meta::List(MetaList { ref path, ref mut nested, .. }) = meta else { unreachable!() }; + + let (span_field, mut applicability) = self.span_and_applicability_of_ty(info)?; + + let mut msg = None; + let mut code = None; + + let mut nested_iter = nested.into_iter().peekable(); + if let Some(nested_attr) = nested_iter.peek() { + if let NestedMeta::Meta(Meta::Path(path)) = nested_attr { + msg = Some(path.clone()); + } + }; + // Move the iterator forward if a path was found (don't otherwise so that + // code/applicability can be found or an error emitted). + if msg.is_some() { + let _ = nested_iter.next(); + } + + for nested_attr in nested_iter { + let meta = match nested_attr { + syn::NestedMeta::Meta(ref meta) => meta, + syn::NestedMeta::Lit(_) => throw_invalid_nested_attr!(attr, &nested_attr), + }; + + let nested_name = meta.path().segments.last().unwrap().ident.to_string(); + let nested_name = nested_name.as_str(); + match meta { + Meta::NameValue(MetaNameValue { lit: syn::Lit::Str(s), .. }) => { + let span = meta.span().unwrap(); + match nested_name { + "code" => { + let formatted_str = self.build_format(&s.value(), s.span()); + code = Some(formatted_str); + } + "applicability" => { + applicability = match applicability { + Some(v) => { + span_err( + span, + "applicability cannot be set in both the field and \ + attribute", + ) + .emit(); + Some(v) + } + None => match Applicability::from_str(&s.value()) { + Ok(v) => Some(quote! { #v }), + Err(()) => { + span_err(span, "invalid applicability").emit(); + None + } + }, + } + } + _ => throw_invalid_nested_attr!(attr, &nested_attr, |diag| { + diag.help( + "only `message`, `code` and `applicability` are valid field \ + attributes", + ) + }), + } + } + _ => throw_invalid_nested_attr!(attr, &nested_attr, |diag| { + if matches!(meta, Meta::Path(_)) { + diag.help("a diagnostic slug must be the first argument to the attribute") + } else { + diag + } + }), + } + } + + let applicability = + applicability.unwrap_or_else(|| quote!(rustc_errors::Applicability::Unspecified)); + + let name = path.segments.last().unwrap().ident.to_string(); + let method = format_ident!("span_{}", name); + + let msg = msg.unwrap_or_else(|| parse_quote! { _subdiag::suggestion }); + let msg = quote! { rustc_errors::fluent::#msg }; + let code = code.unwrap_or_else(|| quote! { String::new() }); + + Ok(quote! { #diag.#method(#span_field, #msg, #code, #applicability); }) + } + + /// Adds a spanned subdiagnostic by generating a `diag.span_$kind` call with the current slug + /// and `fluent_attr_identifier`. + fn add_spanned_subdiagnostic( + &self, + field_binding: TokenStream, + kind: &Ident, + fluent_attr_identifier: Path, + ) -> TokenStream { + let diag = &self.diag; + let fn_name = format_ident!("span_{}", kind); + quote! { + #diag.#fn_name( + #field_binding, + rustc_errors::fluent::#fluent_attr_identifier + ); + } + } + + /// Adds a subdiagnostic by generating a `diag.span_$kind` call with the current slug + /// and `fluent_attr_identifier`. + fn add_subdiagnostic(&self, kind: &Ident, fluent_attr_identifier: Path) -> TokenStream { + let diag = &self.diag; + quote! { + #diag.#kind(rustc_errors::fluent::#fluent_attr_identifier); + } + } + + fn span_and_applicability_of_ty( + &self, + info: FieldInfo<'_>, + ) -> Result<(TokenStream, Option<TokenStream>), DiagnosticDeriveError> { + match &info.ty { + // If `ty` is `Span` w/out applicability, then use `Applicability::Unspecified`. + ty @ Type::Path(..) if type_matches_path(ty, &["rustc_span", "Span"]) => { + let binding = &info.binding.binding; + Ok((quote!(*#binding), None)) + } + // If `ty` is `(Span, Applicability)` then return tokens accessing those. + Type::Tuple(tup) => { + let mut span_idx = None; + let mut applicability_idx = None; + + for (idx, elem) in tup.elems.iter().enumerate() { + if type_matches_path(elem, &["rustc_span", "Span"]) { + if span_idx.is_none() { + span_idx = Some(syn::Index::from(idx)); + } else { + throw_span_err!( + info.span.unwrap(), + "type of field annotated with `#[suggestion(...)]` contains more \ + than one `Span`" + ); + } + } else if type_matches_path(elem, &["rustc_errors", "Applicability"]) { + if applicability_idx.is_none() { + applicability_idx = Some(syn::Index::from(idx)); + } else { + throw_span_err!( + info.span.unwrap(), + "type of field annotated with `#[suggestion(...)]` contains more \ + than one Applicability" + ); + } + } + } + + if let Some(span_idx) = span_idx { + let binding = &info.binding.binding; + let span = quote!(#binding.#span_idx); + let applicability = applicability_idx + .map(|applicability_idx| quote!(#binding.#applicability_idx)) + .unwrap_or_else(|| quote!(rustc_errors::Applicability::Unspecified)); + + return Ok((span, Some(applicability))); + } + + throw_span_err!(info.span.unwrap(), "wrong types for suggestion", |diag| { + diag.help( + "`#[suggestion(...)]` on a tuple field must be applied to fields of type \ + `(Span, Applicability)`", + ) + }); + } + // If `ty` isn't a `Span` or `(Span, Applicability)` then emit an error. + _ => throw_span_err!(info.span.unwrap(), "wrong field type for suggestion", |diag| { + diag.help( + "`#[suggestion(...)]` should be applied to fields of type `Span` or \ + `(Span, Applicability)`", + ) + }), + } + } +} diff --git a/compiler/rustc_macros/src/diagnostics/error.rs b/compiler/rustc_macros/src/diagnostics/error.rs index d088402abc6..0b1ededa775 100644 --- a/compiler/rustc_macros/src/diagnostics/error.rs +++ b/compiler/rustc_macros/src/diagnostics/error.rs @@ -4,16 +4,16 @@ use quote::quote; use syn::{spanned::Spanned, Attribute, Error as SynError, Meta, NestedMeta}; #[derive(Debug)] -pub(crate) enum SessionDiagnosticDeriveError { +pub(crate) enum DiagnosticDeriveError { SynError(SynError), ErrorHandled, } -impl SessionDiagnosticDeriveError { +impl DiagnosticDeriveError { pub(crate) fn to_compile_error(self) -> TokenStream { match self { - SessionDiagnosticDeriveError::SynError(e) => e.to_compile_error(), - SessionDiagnosticDeriveError::ErrorHandled => { + DiagnosticDeriveError::SynError(e) => e.to_compile_error(), + DiagnosticDeriveError::ErrorHandled => { // Return ! to avoid having to create a blank DiagnosticBuilder to return when an // error has already been emitted to the compiler. quote! { @@ -24,9 +24,9 @@ impl SessionDiagnosticDeriveError { } } -impl From<SynError> for SessionDiagnosticDeriveError { +impl From<SynError> for DiagnosticDeriveError { fn from(e: SynError) -> Self { - SessionDiagnosticDeriveError::SynError(e) + DiagnosticDeriveError::SynError(e) } } @@ -34,9 +34,9 @@ impl From<SynError> for SessionDiagnosticDeriveError { pub(crate) fn _throw_err( diag: Diagnostic, f: impl FnOnce(Diagnostic) -> Diagnostic, -) -> SessionDiagnosticDeriveError { +) -> DiagnosticDeriveError { f(diag).emit(); - SessionDiagnosticDeriveError::ErrorHandled + DiagnosticDeriveError::ErrorHandled } /// Helper function for printing `syn::Path` - doesn't handle arguments in paths and these are @@ -60,7 +60,7 @@ pub(crate) fn span_err(span: impl MultiSpan, msg: &str) -> Diagnostic { /// Emit a diagnostic on span `$span` with msg `$msg` (optionally performing additional decoration /// using the `FnOnce` passed in `diag`) and return `Err(ErrorHandled)`. /// -/// For methods that return a `Result<_, SessionDiagnosticDeriveError>`: +/// For methods that return a `Result<_, DiagnosticDeriveError>`: macro_rules! throw_span_err { ($span:expr, $msg:expr) => {{ throw_span_err!($span, $msg, |diag| diag) }}; ($span:expr, $msg:expr, $f:expr) => {{ @@ -87,7 +87,7 @@ pub(crate) fn invalid_attr(attr: &Attribute, meta: &Meta) -> Diagnostic { /// Emit a error diagnostic for an invalid attribute (optionally performing additional decoration /// using the `FnOnce` passed in `diag`) and return `Err(ErrorHandled)`. /// -/// For methods that return a `Result<_, SessionDiagnosticDeriveError>`: +/// For methods that return a `Result<_, DiagnosticDeriveError>`: macro_rules! throw_invalid_attr { ($attr:expr, $meta:expr) => {{ throw_invalid_attr!($attr, $meta, |diag| diag) }}; ($attr:expr, $meta:expr, $f:expr) => {{ @@ -129,7 +129,7 @@ pub(crate) fn invalid_nested_attr(attr: &Attribute, nested: &NestedMeta) -> Diag /// Emit a error diagnostic for an invalid nested attribute (optionally performing additional /// decoration using the `FnOnce` passed in `diag`) and return `Err(ErrorHandled)`. /// -/// For methods that return a `Result<_, SessionDiagnosticDeriveError>`: +/// For methods that return a `Result<_, DiagnosticDeriveError>`: macro_rules! throw_invalid_nested_attr { ($attr:expr, $nested_attr:expr) => {{ throw_invalid_nested_attr!($attr, $nested_attr, |diag| diag) }}; ($attr:expr, $nested_attr:expr, $f:expr) => {{ diff --git a/compiler/rustc_macros/src/diagnostics/mod.rs b/compiler/rustc_macros/src/diagnostics/mod.rs index 2eee4bfb5dd..39979002666 100644 --- a/compiler/rustc_macros/src/diagnostics/mod.rs +++ b/compiler/rustc_macros/src/diagnostics/mod.rs @@ -1,10 +1,11 @@ mod diagnostic; +mod diagnostic_builder; mod error; mod fluent; mod subdiagnostic; mod utils; -use diagnostic::SessionDiagnosticDerive; +use diagnostic::{LintDiagnosticDerive, SessionDiagnosticDerive}; pub(crate) use fluent::fluent_messages; use proc_macro2::TokenStream; use quote::format_ident; @@ -56,13 +57,55 @@ use synstructure::Structure; /// ``` /// /// See rustc dev guide for more examples on using the `#[derive(SessionDiagnostic)]`: -/// <https://rustc-dev-guide.rust-lang.org/diagnostics/sessiondiagnostic.html> +/// <https://rustc-dev-guide.rust-lang.org/diagnostics/diagnostic-structs.html> pub fn session_diagnostic_derive(s: Structure<'_>) -> TokenStream { - // Names for the diagnostic we build and the session we build it from. - let diag = format_ident!("diag"); - let sess = format_ident!("sess"); + SessionDiagnosticDerive::new(format_ident!("diag"), format_ident!("sess"), s).into_tokens() +} - SessionDiagnosticDerive::new(diag, sess, s).into_tokens() +/// Implements `#[derive(LintDiagnostic)]`, which allows for lints to be specified as a struct, +/// independent from the actual lint emitting code. +/// +/// ```ignore (rust) +/// #[derive(LintDiagnostic)] +/// #[lint(lint::atomic_ordering_invalid_fail_success)] +/// pub struct AtomicOrderingInvalidLint { +/// method: Symbol, +/// success_ordering: Symbol, +/// fail_ordering: Symbol, +/// #[label(lint::fail_label)] +/// fail_order_arg_span: Span, +/// #[label(lint::success_label)] +/// #[suggestion( +/// code = "std::sync::atomic::Ordering::{success_suggestion}", +/// applicability = "maybe-incorrect" +/// )] +/// success_order_arg_span: Span, +/// } +/// ``` +/// +/// ```fluent +/// lint-atomic-ordering-invalid-fail-success = `{$method}`'s success ordering must be at least as strong as its failure ordering +/// .fail-label = `{$fail_ordering}` failure ordering +/// .success-label = `{$success_ordering}` success ordering +/// .suggestion = consider using `{$success_suggestion}` success ordering instead +/// ``` +/// +/// Then, later, to emit the error: +/// +/// ```ignore (rust) +/// cx.struct_span_lint(INVALID_ATOMIC_ORDERING, fail_order_arg_span, AtomicOrderingInvalidLint { +/// method, +/// success_ordering, +/// fail_ordering, +/// fail_order_arg_span, +/// success_order_arg_span, +/// }); +/// ``` +/// +/// See rustc dev guide for more examples on using the `#[derive(LintDiagnostic)]`: +/// <https://rustc-dev-guide.rust-lang.org/diagnostics/sessiondiagnostic.html> +pub fn lint_diagnostic_derive(s: Structure<'_>) -> TokenStream { + LintDiagnosticDerive::new(format_ident!("diag"), s).into_tokens() } /// Implements `#[derive(SessionSubdiagnostic)]`, which allows for labels, notes, helps and diff --git a/compiler/rustc_macros/src/diagnostics/subdiagnostic.rs b/compiler/rustc_macros/src/diagnostics/subdiagnostic.rs index eab954a9c1b..2a5b6beba94 100644 --- a/compiler/rustc_macros/src/diagnostics/subdiagnostic.rs +++ b/compiler/rustc_macros/src/diagnostics/subdiagnostic.rs @@ -1,8 +1,7 @@ #![deny(unused_must_use)] use crate::diagnostics::error::{ - span_err, throw_invalid_attr, throw_invalid_nested_attr, throw_span_err, - SessionDiagnosticDeriveError, + span_err, throw_invalid_attr, throw_invalid_nested_attr, throw_span_err, DiagnosticDeriveError, }; use crate::diagnostics::utils::{ report_error_if_not_applied_to_applicability, report_error_if_not_applied_to_span, @@ -214,7 +213,7 @@ impl<'a> HasFieldMap for SessionSubdiagnosticDeriveBuilder<'a> { } impl<'a> SessionSubdiagnosticDeriveBuilder<'a> { - fn identify_kind(&mut self) -> Result<(), SessionDiagnosticDeriveError> { + fn identify_kind(&mut self) -> Result<(), DiagnosticDeriveError> { for attr in self.variant.ast().attrs { let span = attr.span().unwrap(); @@ -351,7 +350,7 @@ impl<'a> SessionSubdiagnosticDeriveBuilder<'a> { &mut self, binding: &BindingInfo<'_>, is_suggestion: bool, - ) -> Result<TokenStream, SessionDiagnosticDeriveError> { + ) -> Result<TokenStream, DiagnosticDeriveError> { let ast = binding.ast(); let inner_ty = FieldInnerTy::from_type(&ast.ty); @@ -411,7 +410,7 @@ impl<'a> SessionSubdiagnosticDeriveBuilder<'a> { Ok(inner_ty.with(binding, generated)) } - fn into_tokens(&mut self) -> Result<TokenStream, SessionDiagnosticDeriveError> { + fn into_tokens(&mut self) -> Result<TokenStream, DiagnosticDeriveError> { self.identify_kind()?; let Some(kind) = self.kind.map(|(kind, _)| kind) else { throw_span_err!( diff --git a/compiler/rustc_macros/src/diagnostics/utils.rs b/compiler/rustc_macros/src/diagnostics/utils.rs index 636bcf1f7b1..8977db4606c 100644 --- a/compiler/rustc_macros/src/diagnostics/utils.rs +++ b/compiler/rustc_macros/src/diagnostics/utils.rs @@ -1,11 +1,11 @@ -use crate::diagnostics::error::{span_err, throw_span_err, SessionDiagnosticDeriveError}; +use crate::diagnostics::error::{span_err, throw_span_err, DiagnosticDeriveError}; use proc_macro::Span; use proc_macro2::TokenStream; use quote::{format_ident, quote, ToTokens}; -use std::collections::BTreeSet; +use std::collections::{BTreeSet, HashMap}; use std::str::FromStr; use syn::{spanned::Spanned, Attribute, Meta, Type, TypeTuple}; -use synstructure::BindingInfo; +use synstructure::{BindingInfo, Structure}; /// Checks whether the type name of `ty` matches `name`. /// @@ -34,7 +34,7 @@ pub(crate) fn type_is_unit(ty: &Type) -> bool { pub(crate) fn report_type_error( attr: &Attribute, ty_name: &str, -) -> Result<!, SessionDiagnosticDeriveError> { +) -> Result<!, DiagnosticDeriveError> { let name = attr.path.segments.last().unwrap().ident.to_string(); let meta = attr.parse_meta()?; @@ -59,7 +59,7 @@ fn report_error_if_not_applied_to_ty( info: &FieldInfo<'_>, path: &[&str], ty_name: &str, -) -> Result<(), SessionDiagnosticDeriveError> { +) -> Result<(), DiagnosticDeriveError> { if !type_matches_path(&info.ty, path) { report_type_error(attr, ty_name)?; } @@ -71,7 +71,7 @@ fn report_error_if_not_applied_to_ty( pub(crate) fn report_error_if_not_applied_to_applicability( attr: &Attribute, info: &FieldInfo<'_>, -) -> Result<(), SessionDiagnosticDeriveError> { +) -> Result<(), DiagnosticDeriveError> { report_error_if_not_applied_to_ty( attr, info, @@ -84,7 +84,7 @@ pub(crate) fn report_error_if_not_applied_to_applicability( pub(crate) fn report_error_if_not_applied_to_span( attr: &Attribute, info: &FieldInfo<'_>, -) -> Result<(), SessionDiagnosticDeriveError> { +) -> Result<(), DiagnosticDeriveError> { report_error_if_not_applied_to_ty(attr, info, &["rustc_span", "Span"], "`Span`") } @@ -166,10 +166,12 @@ pub(crate) struct FieldInfo<'a> { /// Small helper trait for abstracting over `Option` fields that contain a value and a `Span` /// for error reporting if they are set more than once. pub(crate) trait SetOnce<T> { - fn set_once(&mut self, value: T); + fn set_once(&mut self, _: (T, Span)); + + fn value(self) -> Option<T>; } -impl<T> SetOnce<(T, Span)> for Option<(T, Span)> { +impl<T> SetOnce<T> for Option<(T, Span)> { fn set_once(&mut self, (value, span): (T, Span)) { match self { None => { @@ -182,6 +184,10 @@ impl<T> SetOnce<(T, Span)> for Option<(T, Span)> { } } } + + fn value(self) -> Option<T> { + self.map(|(v, _)| v) + } } pub(crate) trait HasFieldMap { @@ -325,3 +331,20 @@ impl quote::ToTokens for Applicability { }); } } + +/// Build the mapping of field names to fields. This allows attributes to peek values from +/// other fields. +pub(crate) fn build_field_mapping<'a>(structure: &Structure<'a>) -> HashMap<String, TokenStream> { + let mut fields_map = HashMap::new(); + + let ast = structure.ast(); + if let syn::Data::Struct(syn::DataStruct { fields, .. }) = &ast.data { + for field in fields.iter() { + if let Some(ident) = &field.ident { + fields_map.insert(ident.to_string(), quote! { &self.#ident }); + } + } + } + + fields_map +} diff --git a/compiler/rustc_macros/src/lib.rs b/compiler/rustc_macros/src/lib.rs index 7c8e3c6d140..168530c54b9 100644 --- a/compiler/rustc_macros/src/lib.rs +++ b/compiler/rustc_macros/src/lib.rs @@ -18,6 +18,7 @@ mod query; mod serialize; mod symbols; mod type_foldable; +mod type_visitable; #[proc_macro] pub fn rustc_queries(input: TokenStream) -> TokenStream { @@ -121,12 +122,14 @@ decl_derive!([TyEncodable] => serialize::type_encodable_derive); decl_derive!([MetadataDecodable] => serialize::meta_decodable_derive); decl_derive!([MetadataEncodable] => serialize::meta_encodable_derive); decl_derive!([TypeFoldable, attributes(type_foldable)] => type_foldable::type_foldable_derive); +decl_derive!([TypeVisitable, attributes(type_visitable)] => type_visitable::type_visitable_derive); decl_derive!([Lift, attributes(lift)] => lift::lift_derive); decl_derive!( [SessionDiagnostic, attributes( // struct attributes warning, error, + lint, note, help, // field attributes @@ -140,6 +143,24 @@ decl_derive!( suggestion_verbose)] => diagnostics::session_diagnostic_derive ); decl_derive!( + [LintDiagnostic, attributes( + // struct attributes + warning, + error, + lint, + note, + help, + // field attributes + skip_arg, + primary_span, + label, + subdiagnostic, + suggestion, + suggestion_short, + suggestion_hidden, + suggestion_verbose)] => diagnostics::lint_diagnostic_derive +); +decl_derive!( [SessionSubdiagnostic, attributes( // struct/variant attributes label, diff --git a/compiler/rustc_macros/src/type_foldable.rs b/compiler/rustc_macros/src/type_foldable.rs index 9e834d3ba1c..23e619221aa 100644 --- a/compiler/rustc_macros/src/type_foldable.rs +++ b/compiler/rustc_macros/src/type_foldable.rs @@ -11,11 +11,6 @@ pub fn type_foldable_derive(mut s: synstructure::Structure<'_>) -> proc_macro2:: } s.add_bounds(synstructure::AddBounds::Generics); - let body_visit = s.each(|bind| { - quote! { - ::rustc_middle::ty::fold::TypeFoldable::visit_with(#bind, __folder)?; - } - }); s.bind_with(|_| synstructure::BindStyle::Move); let body_fold = s.each_variant(|vi| { let bindings = vi.bindings(); @@ -36,14 +31,6 @@ pub fn type_foldable_derive(mut s: synstructure::Structure<'_>) -> proc_macro2:: ) -> Result<Self, __F::Error> { Ok(match self { #body_fold }) } - - fn visit_with<__F: ::rustc_middle::ty::fold::TypeVisitor<'tcx>>( - &self, - __folder: &mut __F - ) -> ::std::ops::ControlFlow<__F::BreakTy> { - match *self { #body_visit } - ::std::ops::ControlFlow::CONTINUE - } }, ) } diff --git a/compiler/rustc_macros/src/type_visitable.rs b/compiler/rustc_macros/src/type_visitable.rs new file mode 100644 index 00000000000..14e6aa6e0c1 --- /dev/null +++ b/compiler/rustc_macros/src/type_visitable.rs @@ -0,0 +1,33 @@ +use quote::quote; +use syn::parse_quote; + +pub fn type_visitable_derive(mut s: synstructure::Structure<'_>) -> proc_macro2::TokenStream { + if let syn::Data::Union(_) = s.ast().data { + panic!("cannot derive on union") + } + + if !s.ast().generics.lifetimes().any(|lt| lt.lifetime.ident == "tcx") { + s.add_impl_generic(parse_quote! { 'tcx }); + } + + s.add_bounds(synstructure::AddBounds::Generics); + let body_visit = s.each(|bind| { + quote! { + ::rustc_middle::ty::visit::TypeVisitable::visit_with(#bind, __visitor)?; + } + }); + s.bind_with(|_| synstructure::BindStyle::Move); + + s.bound_impl( + quote!(::rustc_middle::ty::visit::TypeVisitable<'tcx>), + quote! { + fn visit_with<__V: ::rustc_middle::ty::visit::TypeVisitor<'tcx>>( + &self, + __visitor: &mut __V + ) -> ::std::ops::ControlFlow<__V::BreakTy> { + match *self { #body_visit } + ::std::ops::ControlFlow::CONTINUE + } + }, + ) +} diff --git a/compiler/rustc_metadata/src/creader.rs b/compiler/rustc_metadata/src/creader.rs index 555db5846ed..cb50c0fb738 100644 --- a/compiler/rustc_metadata/src/creader.rs +++ b/compiler/rustc_metadata/src/creader.rs @@ -748,7 +748,7 @@ impl<'a> CrateLoader<'a> { if !data.is_panic_runtime() { self.sess.err(&format!("the crate `{}` is not a panic runtime", name)); } - if data.panic_strategy() != desired_strategy { + if data.required_panic_strategy() != Some(desired_strategy) { self.sess.err(&format!( "the crate `{}` does not have the panic \ strategy `{}`", diff --git a/compiler/rustc_metadata/src/dependency_format.rs b/compiler/rustc_metadata/src/dependency_format.rs index 245b2076ebc..770d164894a 100644 --- a/compiler/rustc_metadata/src/dependency_format.rs +++ b/compiler/rustc_metadata/src/dependency_format.rs @@ -60,7 +60,6 @@ use rustc_middle::ty::TyCtxt; use rustc_session::config::CrateType; use rustc_session::cstore::CrateDepKind; use rustc_session::cstore::LinkagePreference::{self, RequireDynamic, RequireStatic}; -use rustc_target::spec::PanicStrategy; pub(crate) fn calculate(tcx: TyCtxt<'_>) -> Dependencies { tcx.sess @@ -367,14 +366,19 @@ fn verify_ok(tcx: TyCtxt<'_>, list: &[Linkage]) { prev_name, cur_name )); } - panic_runtime = Some((cnum, tcx.panic_strategy(cnum))); + panic_runtime = Some(( + cnum, + tcx.required_panic_strategy(cnum).unwrap_or_else(|| { + bug!("cannot determine panic strategy of a panic runtime"); + }), + )); } } // If we found a panic runtime, then we know by this point that it's the // only one, but we perform validation here that all the panic strategy // compilation modes for the whole DAG are valid. - if let Some((cnum, found_strategy)) = panic_runtime { + if let Some((runtime_cnum, found_strategy)) = panic_runtime { let desired_strategy = sess.panic_strategy(); // First up, validate that our selected panic runtime is indeed exactly @@ -384,7 +388,7 @@ fn verify_ok(tcx: TyCtxt<'_>, list: &[Linkage]) { "the linked panic runtime `{}` is \ not compiled with this crate's \ panic strategy `{}`", - tcx.crate_name(cnum), + tcx.crate_name(runtime_cnum), desired_strategy.desc() )); } @@ -397,18 +401,14 @@ fn verify_ok(tcx: TyCtxt<'_>, list: &[Linkage]) { if let Linkage::NotLinked = *linkage { continue; } - if desired_strategy == PanicStrategy::Abort { - continue; - } let cnum = CrateNum::new(i + 1); - if tcx.is_compiler_builtins(cnum) { + if cnum == runtime_cnum || tcx.is_compiler_builtins(cnum) { continue; } - let found_strategy = tcx.panic_strategy(cnum); - if desired_strategy != found_strategy { + if let Some(found_strategy) = tcx.required_panic_strategy(cnum) && desired_strategy != found_strategy { sess.err(&format!( - "the crate `{}` is compiled with the \ + "the crate `{}` requires \ panic strategy `{}` which is \ incompatible with this crate's \ strategy of `{}`", diff --git a/compiler/rustc_metadata/src/rmeta/decoder.rs b/compiler/rustc_metadata/src/rmeta/decoder.rs index 3280fd5c310..f0ccf02c9fa 100644 --- a/compiler/rustc_metadata/src/rmeta/decoder.rs +++ b/compiler/rustc_metadata/src/rmeta/decoder.rs @@ -1758,8 +1758,8 @@ impl CrateMetadata { self.dep_kind.with_lock(|dep_kind| *dep_kind = f(*dep_kind)) } - pub(crate) fn panic_strategy(&self) -> PanicStrategy { - self.root.panic_strategy + pub(crate) fn required_panic_strategy(&self) -> Option<PanicStrategy> { + self.root.required_panic_strategy } pub(crate) fn needs_panic_runtime(&self) -> bool { diff --git a/compiler/rustc_metadata/src/rmeta/decoder/cstore_impl.rs b/compiler/rustc_metadata/src/rmeta/decoder/cstore_impl.rs index 0bea2a10da8..565eec18ea9 100644 --- a/compiler/rustc_metadata/src/rmeta/decoder/cstore_impl.rs +++ b/compiler/rustc_metadata/src/rmeta/decoder/cstore_impl.rs @@ -246,7 +246,7 @@ provide! { <'tcx> tcx, def_id, other, cdata, has_global_allocator => { cdata.root.has_global_allocator } has_panic_handler => { cdata.root.has_panic_handler } is_profiler_runtime => { cdata.root.profiler_runtime } - panic_strategy => { cdata.root.panic_strategy } + required_panic_strategy => { cdata.root.required_panic_strategy } panic_in_drop_strategy => { cdata.root.panic_in_drop_strategy } extern_crate => { let r = *cdata.extern_crate.lock(); diff --git a/compiler/rustc_metadata/src/rmeta/encoder.rs b/compiler/rustc_metadata/src/rmeta/encoder.rs index 75286b89068..bb4b502bded 100644 --- a/compiler/rustc_metadata/src/rmeta/encoder.rs +++ b/compiler/rustc_metadata/src/rmeta/encoder.rs @@ -665,7 +665,7 @@ impl<'a, 'tcx> EncodeContext<'a, 'tcx> { triple: tcx.sess.opts.target_triple.clone(), hash: tcx.crate_hash(LOCAL_CRATE), stable_crate_id: tcx.def_path_hash(LOCAL_CRATE.as_def_id()).stable_crate_id(), - panic_strategy: tcx.sess.panic_strategy(), + required_panic_strategy: tcx.required_panic_strategy(LOCAL_CRATE), panic_in_drop_strategy: tcx.sess.opts.debugging_opts.panic_in_drop, edition: tcx.sess.edition(), has_global_allocator: tcx.has_global_allocator(LOCAL_CRATE), diff --git a/compiler/rustc_metadata/src/rmeta/mod.rs b/compiler/rustc_metadata/src/rmeta/mod.rs index a58c0e68ee3..a50eb2a71cf 100644 --- a/compiler/rustc_metadata/src/rmeta/mod.rs +++ b/compiler/rustc_metadata/src/rmeta/mod.rs @@ -217,7 +217,7 @@ pub(crate) struct CrateRoot { extra_filename: String, hash: Svh, stable_crate_id: StableCrateId, - panic_strategy: PanicStrategy, + required_panic_strategy: Option<PanicStrategy>, panic_in_drop_strategy: PanicStrategy, edition: Edition, has_global_allocator: bool, diff --git a/compiler/rustc_middle/src/hir/map/mod.rs b/compiler/rustc_middle/src/hir/map/mod.rs index a27b8470e95..3539acbc06e 100644 --- a/compiler/rustc_middle/src/hir/map/mod.rs +++ b/compiler/rustc_middle/src/hir/map/mod.rs @@ -225,7 +225,8 @@ impl<'hir> Map<'hir> { self.tcx.definitions_untracked().iter_local_def_id() } - pub fn opt_def_kind(self, local_def_id: LocalDefId) -> Option<DefKind> { + /// Do not call this function directly. The query should be called. + pub(super) fn opt_def_kind(self, local_def_id: LocalDefId) -> Option<DefKind> { let hir_id = self.local_def_id_to_hir_id(local_def_id); let def_kind = match self.find(hir_id)? { Node::Item(item) => match item.kind { @@ -302,7 +303,6 @@ impl<'hir> Map<'hir> { | Node::Infer(_) | Node::TraitRef(_) | Node::Pat(_) - | Node::Binding(_) | Node::Local(_) | Node::Param(_) | Node::Arm(_) @@ -901,7 +901,7 @@ impl<'hir> Map<'hir> { #[inline] fn opt_ident(self, id: HirId) -> Option<Ident> { match self.get(id) { - Node::Binding(&Pat { kind: PatKind::Binding(_, _, ident, _), .. }) => Some(ident), + Node::Pat(&Pat { kind: PatKind::Binding(_, _, ident, _), .. }) => Some(ident), // A `Ctor` doesn't have an identifier itself, but its parent // struct/variant does. Compare with `hir::Map::opt_span`. Node::Ctor(..) => match self.find(self.get_parent_node(id))? { @@ -934,28 +934,105 @@ impl<'hir> Map<'hir> { } /// Gets the span of the definition of the specified HIR node. - /// This is used by `tcx.get_span` + /// This is used by `tcx.def_span`. pub fn span(self, hir_id: HirId) -> Span { self.opt_span(hir_id) .unwrap_or_else(|| bug!("hir::map::Map::span: id not in map: {:?}", hir_id)) } pub fn opt_span(self, hir_id: HirId) -> Option<Span> { + fn until_within(outer: Span, end: Span) -> Span { + if let Some(end) = end.find_ancestor_inside(outer) { + outer.with_hi(end.hi()) + } else { + outer + } + } + + fn named_span(item_span: Span, ident: Ident, generics: Option<&Generics<'_>>) -> Span { + if ident.name != kw::Empty { + let mut span = until_within(item_span, ident.span); + if let Some(g) = generics + && !g.span.is_dummy() + && let Some(g_span) = g.span.find_ancestor_inside(item_span) + { + span = span.to(g_span); + } + span + } else { + item_span + } + } + let span = match self.find(hir_id)? { - Node::Param(param) => param.span, + // Function-like. + Node::Item(Item { kind: ItemKind::Fn(sig, ..), .. }) + | Node::TraitItem(TraitItem { kind: TraitItemKind::Fn(sig, ..), .. }) + | Node::ImplItem(ImplItem { kind: ImplItemKind::Fn(sig, ..), .. }) => sig.span, + // Constants and Statics. + Node::Item(Item { + kind: + ItemKind::Const(ty, ..) + | ItemKind::Static(ty, ..) + | ItemKind::Impl(Impl { self_ty: ty, .. }), + span: outer_span, + .. + }) + | Node::TraitItem(TraitItem { + kind: TraitItemKind::Const(ty, ..), + span: outer_span, + .. + }) + | Node::ImplItem(ImplItem { + kind: ImplItemKind::Const(ty, ..), + span: outer_span, + .. + }) + | Node::ForeignItem(ForeignItem { + kind: ForeignItemKind::Static(ty, ..), + span: outer_span, + .. + }) => until_within(*outer_span, ty.span), + // With generics and bounds. + Node::Item(Item { + kind: ItemKind::Trait(_, _, generics, bounds, _), + span: outer_span, + .. + }) + | Node::TraitItem(TraitItem { + kind: TraitItemKind::Type(bounds, _), + generics, + span: outer_span, + .. + }) => { + let end = if let Some(b) = bounds.last() { b.span() } else { generics.span }; + until_within(*outer_span, end) + } + // Other cases. Node::Item(item) => match &item.kind { - ItemKind::Fn(sig, _, _) => sig.span, - _ => item.span, + ItemKind::Use(path, _) => path.span, + _ => named_span(item.span, item.ident, item.kind.generics()), }, - Node::ForeignItem(foreign_item) => foreign_item.span, - Node::TraitItem(trait_item) => match &trait_item.kind { - TraitItemKind::Fn(sig, _) => sig.span, - _ => trait_item.span, - }, - Node::ImplItem(impl_item) => match &impl_item.kind { - ImplItemKind::Fn(sig, _) => sig.span, - _ => impl_item.span, + Node::ImplItem(item) => named_span(item.span, item.ident, Some(item.generics)), + Node::ForeignItem(item) => match item.kind { + ForeignItemKind::Fn(decl, _, _) => until_within(item.span, decl.output.span()), + _ => named_span(item.span, item.ident, None), }, + Node::Ctor(..) => return self.opt_span(self.get_parent_node(hir_id)), + _ => self.span_with_body(hir_id), + }; + Some(span) + } + + /// Like `hir.span()`, but includes the body of items + /// (instead of just the item header) + pub fn span_with_body(self, hir_id: HirId) -> Span { + match self.get(hir_id) { + Node::Param(param) => param.span, + Node::Item(item) => item.span, + Node::ForeignItem(foreign_item) => foreign_item.span, + Node::TraitItem(trait_item) => trait_item.span, + Node::ImplItem(impl_item) => impl_item.span, Node::Variant(variant) => variant.span, Node::Field(field) => field.span, Node::AnonConst(constant) => self.body(constant.body).value.span, @@ -969,33 +1046,15 @@ impl<'hir> Map<'hir> { Node::Ty(ty) => ty.span, Node::TypeBinding(tb) => tb.span, Node::TraitRef(tr) => tr.path.span, - Node::Binding(pat) => pat.span, Node::Pat(pat) => pat.span, Node::Arm(arm) => arm.span, Node::Block(block) => block.span, - Node::Ctor(..) => match self.find(self.get_parent_node(hir_id))? { - Node::Item(item) => item.span, - Node::Variant(variant) => variant.span, - _ => unreachable!(), - }, + Node::Ctor(..) => self.span_with_body(self.get_parent_node(hir_id)), Node::Lifetime(lifetime) => lifetime.span, Node::GenericParam(param) => param.span, Node::Infer(i) => i.span, Node::Local(local) => local.span, Node::Crate(item) => item.spans.inner_span, - }; - Some(span) - } - - /// Like `hir.span()`, but includes the body of function items - /// (instead of just the function header) - pub fn span_with_body(self, hir_id: HirId) -> Span { - match self.find(hir_id) { - Some(Node::TraitItem(item)) => item.span, - Some(Node::ImplItem(impl_item)) => impl_item.span, - Some(Node::Item(item)) => item.span, - Some(_) => self.span(hir_id), - _ => bug!("hir::map::Map::span_with_body: id not in map: {:?}", hir_id), } } @@ -1203,7 +1262,6 @@ fn hir_id_to_string(map: Map<'_>, id: HirId) -> String { Some(Node::Ty(_)) => node_str("type"), Some(Node::TypeBinding(_)) => node_str("type binding"), Some(Node::TraitRef(_)) => node_str("trait ref"), - Some(Node::Binding(_)) => node_str("local"), Some(Node::Pat(_)) => node_str("pat"), Some(Node::Param(_)) => node_str("param"), Some(Node::Arm(_)) => node_str("arm"), diff --git a/compiler/rustc_middle/src/hir/place.rs b/compiler/rustc_middle/src/hir/place.rs index 00db19019c4..83d3b0100b8 100644 --- a/compiler/rustc_middle/src/hir/place.rs +++ b/compiler/rustc_middle/src/hir/place.rs @@ -4,18 +4,8 @@ use crate::ty::Ty; use rustc_hir::HirId; use rustc_target::abi::VariantIdx; -#[derive( - Clone, - Copy, - Debug, - PartialEq, - Eq, - Hash, - TyEncodable, - TyDecodable, - TypeFoldable, - HashStable -)] +#[derive(Clone, Copy, Debug, PartialEq, Eq, Hash, TyEncodable, TyDecodable, HashStable)] +#[derive(TypeFoldable, TypeVisitable)] pub enum PlaceBase { /// A temporary variable. Rvalue, @@ -27,18 +17,8 @@ pub enum PlaceBase { Upvar(ty::UpvarId), } -#[derive( - Clone, - Copy, - Debug, - PartialEq, - Eq, - Hash, - TyEncodable, - TyDecodable, - TypeFoldable, - HashStable -)] +#[derive(Clone, Copy, Debug, PartialEq, Eq, Hash, TyEncodable, TyDecodable, HashStable)] +#[derive(TypeFoldable, TypeVisitable)] pub enum ProjectionKind { /// A dereference of a pointer, reference or `Box<T>` of the given type. Deref, @@ -58,18 +38,8 @@ pub enum ProjectionKind { Subslice, } -#[derive( - Clone, - Copy, - Debug, - PartialEq, - Eq, - Hash, - TyEncodable, - TyDecodable, - TypeFoldable, - HashStable -)] +#[derive(Clone, Copy, Debug, PartialEq, Eq, Hash, TyEncodable, TyDecodable, HashStable)] +#[derive(TypeFoldable, TypeVisitable)] pub struct Projection<'tcx> { /// Type after the projection is applied. pub ty: Ty<'tcx>, @@ -81,7 +51,8 @@ pub struct Projection<'tcx> { /// A `Place` represents how a value is located in memory. /// /// This is an HIR version of [`rustc_middle::mir::Place`]. -#[derive(Clone, Debug, PartialEq, Eq, Hash, TyEncodable, TyDecodable, TypeFoldable, HashStable)] +#[derive(Clone, Debug, PartialEq, Eq, Hash, TyEncodable, TyDecodable, HashStable)] +#[derive(TypeFoldable, TypeVisitable)] pub struct Place<'tcx> { /// The type of the `PlaceBase` pub base_ty: Ty<'tcx>, @@ -94,7 +65,8 @@ pub struct Place<'tcx> { /// A `PlaceWithHirId` represents how a value is located in memory. /// /// This is an HIR version of [`rustc_middle::mir::Place`]. -#[derive(Clone, Debug, PartialEq, Eq, Hash, TyEncodable, TyDecodable, TypeFoldable, HashStable)] +#[derive(Clone, Debug, PartialEq, Eq, Hash, TyEncodable, TyDecodable, HashStable)] +#[derive(TypeFoldable, TypeVisitable)] pub struct PlaceWithHirId<'tcx> { /// `HirId` of the expression or pattern producing this value. pub hir_id: HirId, diff --git a/compiler/rustc_middle/src/infer/canonical.rs b/compiler/rustc_middle/src/infer/canonical.rs index 79f94802d20..c6fe3e72103 100644 --- a/compiler/rustc_middle/src/infer/canonical.rs +++ b/compiler/rustc_middle/src/infer/canonical.rs @@ -34,7 +34,7 @@ use std::ops::Index; /// variables have been rewritten to "canonical vars". These are /// numbered starting from 0 in order of first appearance. #[derive(Copy, Clone, Debug, PartialEq, Eq, Hash, TyDecodable, TyEncodable)] -#[derive(HashStable, TypeFoldable, Lift)] +#[derive(HashStable, TypeFoldable, TypeVisitable, Lift)] pub struct Canonical<'tcx, V> { pub max_universe: ty::UniverseIndex, pub variables: CanonicalVarInfos<'tcx>, @@ -53,7 +53,7 @@ pub type CanonicalVarInfos<'tcx> = &'tcx List<CanonicalVarInfo<'tcx>>; /// variables. You will need to supply it later to instantiate the /// canonicalized query response. #[derive(Clone, Debug, PartialEq, Eq, Hash, TyDecodable, TyEncodable)] -#[derive(HashStable, TypeFoldable, Lift)] +#[derive(HashStable, TypeFoldable, TypeVisitable, Lift)] pub struct CanonicalVarValues<'tcx> { pub var_values: IndexVec<BoundVar, GenericArg<'tcx>>, } @@ -173,7 +173,7 @@ pub enum CanonicalTyVarKind { /// After we execute a query with a canonicalized key, we get back a /// `Canonical<QueryResponse<..>>`. You can use /// `instantiate_query_result` to access the data in this result. -#[derive(Clone, Debug, HashStable, TypeFoldable, Lift)] +#[derive(Clone, Debug, HashStable, TypeFoldable, TypeVisitable, Lift)] pub struct QueryResponse<'tcx, R> { pub var_values: CanonicalVarValues<'tcx>, pub region_constraints: QueryRegionConstraints<'tcx>, @@ -187,7 +187,7 @@ pub struct QueryResponse<'tcx, R> { pub value: R, } -#[derive(Clone, Debug, Default, HashStable, TypeFoldable, Lift)] +#[derive(Clone, Debug, Default, HashStable, TypeFoldable, TypeVisitable, Lift)] pub struct QueryRegionConstraints<'tcx> { pub outlives: Vec<QueryOutlivesConstraint<'tcx>>, pub member_constraints: Vec<MemberConstraint<'tcx>>, @@ -293,7 +293,7 @@ impl<'tcx, V> Canonical<'tcx, V> { pub type QueryOutlivesConstraint<'tcx> = ty::Binder<'tcx, ty::OutlivesPredicate<GenericArg<'tcx>, Region<'tcx>>>; -TrivialTypeFoldableAndLiftImpls! { +TrivialTypeTraversalAndLiftImpls! { for <'tcx> { crate::infer::canonical::Certainty, crate::infer::canonical::CanonicalVarInfo<'tcx>, @@ -301,7 +301,7 @@ TrivialTypeFoldableAndLiftImpls! { } } -TrivialTypeFoldableImpls! { +TrivialTypeTraversalImpls! { for <'tcx> { crate::infer::canonical::CanonicalVarInfos<'tcx>, } diff --git a/compiler/rustc_middle/src/infer/mod.rs b/compiler/rustc_middle/src/infer/mod.rs index 2350a6ab155..55e00c4c0d8 100644 --- a/compiler/rustc_middle/src/infer/mod.rs +++ b/compiler/rustc_middle/src/infer/mod.rs @@ -13,7 +13,7 @@ use rustc_span::Span; /// ```text /// R0 member of [O1..On] /// ``` -#[derive(Debug, Clone, HashStable, TypeFoldable, Lift)] +#[derive(Debug, Clone, HashStable, TypeFoldable, TypeVisitable, Lift)] pub struct MemberConstraint<'tcx> { /// The `DefId` of the opaque type causing this constraint: used for error reporting. pub opaque_type_def_id: DefId, diff --git a/compiler/rustc_middle/src/lint.rs b/compiler/rustc_middle/src/lint.rs index 215d8decf2a..4b156de410d 100644 --- a/compiler/rustc_middle/src/lint.rs +++ b/compiler/rustc_middle/src/lint.rs @@ -2,9 +2,7 @@ use std::cmp; use rustc_data_structures::fx::FxHashMap; use rustc_data_structures::stable_hasher::{HashStable, StableHasher}; -use rustc_errors::{ - Diagnostic, DiagnosticBuilder, DiagnosticId, EmissionGuarantee, ErrorGuaranteed, MultiSpan, -}; +use rustc_errors::{Diagnostic, DiagnosticId, LintDiagnosticBuilder, MultiSpan}; use rustc_hir::HirId; use rustc_index::vec::IndexVec; use rustc_query_system::ich::StableHashingContext; @@ -227,28 +225,6 @@ impl LintExpectation { } } -pub struct LintDiagnosticBuilder<'a, G: EmissionGuarantee>(DiagnosticBuilder<'a, G>); - -impl<'a, G: EmissionGuarantee> LintDiagnosticBuilder<'a, G> { - /// Return the inner `DiagnosticBuilder`, first setting the primary message to `msg`. - pub fn build(mut self, msg: &str) -> DiagnosticBuilder<'a, G> { - self.0.set_primary_message(msg); - self.0.set_is_lint(); - self.0 - } - - /// Create a `LintDiagnosticBuilder` from some existing `DiagnosticBuilder`. - pub fn new(err: DiagnosticBuilder<'a, G>) -> LintDiagnosticBuilder<'a, G> { - LintDiagnosticBuilder(err) - } -} - -impl<'a> LintDiagnosticBuilder<'a, ErrorGuaranteed> { - pub fn forget_guarantee(self) -> LintDiagnosticBuilder<'a, ()> { - LintDiagnosticBuilder(self.0.forget_guarantee()) - } -} - pub fn explain_lint_level_source( lint: &'static Lint, level: Level, diff --git a/compiler/rustc_middle/src/macros.rs b/compiler/rustc_middle/src/macros.rs index 33b4dff977e..0e85c60a363 100644 --- a/compiler/rustc_middle/src/macros.rs +++ b/compiler/rustc_middle/src/macros.rs @@ -18,7 +18,7 @@ macro_rules! span_bug { } /////////////////////////////////////////////////////////////////////////// -// Lift and TypeFoldable macros +// Lift and TypeFoldable/TypeVisitable macros // // When possible, use one of these (relatively) convenient macros to write // the impls for you. @@ -48,7 +48,7 @@ macro_rules! CloneLiftImpls { /// Used for types that are `Copy` and which **do not care arena /// allocated data** (i.e., don't need to be folded). #[macro_export] -macro_rules! TrivialTypeFoldableImpls { +macro_rules! TrivialTypeTraversalImpls { (for <$tcx:lifetime> { $($ty:ty,)+ }) => { $( impl<$tcx> $crate::ty::fold::TypeFoldable<$tcx> for $ty { @@ -58,8 +58,10 @@ macro_rules! TrivialTypeFoldableImpls { ) -> ::std::result::Result<$ty, F::Error> { Ok(self) } + } - fn visit_with<F: $crate::ty::fold::TypeVisitor<$tcx>>( + impl<$tcx> $crate::ty::visit::TypeVisitable<$tcx> for $ty { + fn visit_with<F: $crate::ty::visit::TypeVisitor<$tcx>>( &self, _: &mut F) -> ::std::ops::ControlFlow<F::BreakTy> @@ -71,7 +73,7 @@ macro_rules! TrivialTypeFoldableImpls { }; ($($ty:ty,)+) => { - TrivialTypeFoldableImpls! { + TrivialTypeTraversalImpls! { for <'tcx> { $($ty,)+ } @@ -80,15 +82,15 @@ macro_rules! TrivialTypeFoldableImpls { } #[macro_export] -macro_rules! TrivialTypeFoldableAndLiftImpls { +macro_rules! TrivialTypeTraversalAndLiftImpls { ($($t:tt)*) => { - TrivialTypeFoldableImpls! { $($t)* } + TrivialTypeTraversalImpls! { $($t)* } CloneLiftImpls! { $($t)* } } } #[macro_export] -macro_rules! EnumTypeFoldableImpl { +macro_rules! EnumTypeTraversalImpl { (impl<$($p:tt),*> TypeFoldable<$tcx:tt> for $s:path { $($variants:tt)* } $(where $($wc:tt)*)*) => { @@ -99,14 +101,22 @@ macro_rules! EnumTypeFoldableImpl { self, folder: &mut V, ) -> ::std::result::Result<Self, V::Error> { - EnumTypeFoldableImpl!(@FoldVariants(self, folder) input($($variants)*) output()) + EnumTypeTraversalImpl!(@FoldVariants(self, folder) input($($variants)*) output()) } + } + }; - fn visit_with<V: $crate::ty::fold::TypeVisitor<$tcx>>( + (impl<$($p:tt),*> TypeVisitable<$tcx:tt> for $s:path { + $($variants:tt)* + } $(where $($wc:tt)*)*) => { + impl<$($p),*> $crate::ty::visit::TypeVisitable<$tcx> for $s + $(where $($wc)*)* + { + fn visit_with<V: $crate::ty::visit::TypeVisitor<$tcx>>( &self, visitor: &mut V, ) -> ::std::ops::ControlFlow<V::BreakTy> { - EnumTypeFoldableImpl!(@VisitVariants(self, visitor) input($($variants)*) output()) + EnumTypeTraversalImpl!(@VisitVariants(self, visitor) input($($variants)*) output()) } } }; @@ -120,7 +130,7 @@ macro_rules! EnumTypeFoldableImpl { (@FoldVariants($this:expr, $folder:expr) input( ($variant:path) ( $($variant_arg:ident),* ) , $($input:tt)*) output( $($output:tt)*) ) => { - EnumTypeFoldableImpl!( + EnumTypeTraversalImpl!( @FoldVariants($this, $folder) input($($input)*) output( @@ -137,7 +147,7 @@ macro_rules! EnumTypeFoldableImpl { (@FoldVariants($this:expr, $folder:expr) input( ($variant:path) { $($variant_arg:ident),* $(,)? } , $($input:tt)*) output( $($output:tt)*) ) => { - EnumTypeFoldableImpl!( + EnumTypeTraversalImpl!( @FoldVariants($this, $folder) input($($input)*) output( @@ -155,7 +165,7 @@ macro_rules! EnumTypeFoldableImpl { (@FoldVariants($this:expr, $folder:expr) input( ($variant:path), $($input:tt)*) output( $($output:tt)*) ) => { - EnumTypeFoldableImpl!( + EnumTypeTraversalImpl!( @FoldVariants($this, $folder) input($($input)*) output( @@ -174,12 +184,12 @@ macro_rules! EnumTypeFoldableImpl { (@VisitVariants($this:expr, $visitor:expr) input( ($variant:path) ( $($variant_arg:ident),* ) , $($input:tt)*) output( $($output:tt)*) ) => { - EnumTypeFoldableImpl!( + EnumTypeTraversalImpl!( @VisitVariants($this, $visitor) input($($input)*) output( $variant ( $($variant_arg),* ) => { - $($crate::ty::fold::TypeFoldable::visit_with( + $($crate::ty::visit::TypeVisitable::visit_with( $variant_arg, $visitor )?;)* ::std::ops::ControlFlow::CONTINUE @@ -192,12 +202,12 @@ macro_rules! EnumTypeFoldableImpl { (@VisitVariants($this:expr, $visitor:expr) input( ($variant:path) { $($variant_arg:ident),* $(,)? } , $($input:tt)*) output( $($output:tt)*) ) => { - EnumTypeFoldableImpl!( + EnumTypeTraversalImpl!( @VisitVariants($this, $visitor) input($($input)*) output( $variant { $($variant_arg),* } => { - $($crate::ty::fold::TypeFoldable::visit_with( + $($crate::ty::visit::TypeVisitable::visit_with( $variant_arg, $visitor )?;)* ::std::ops::ControlFlow::CONTINUE @@ -210,7 +220,7 @@ macro_rules! EnumTypeFoldableImpl { (@VisitVariants($this:expr, $visitor:expr) input( ($variant:path), $($input:tt)*) output( $($output:tt)*) ) => { - EnumTypeFoldableImpl!( + EnumTypeTraversalImpl!( @VisitVariants($this, $visitor) input($($input)*) output( diff --git a/compiler/rustc_middle/src/mir/coverage.rs b/compiler/rustc_middle/src/mir/coverage.rs index 2336d460407..efa9464529e 100644 --- a/compiler/rustc_middle/src/mir/coverage.rs +++ b/compiler/rustc_middle/src/mir/coverage.rs @@ -100,7 +100,7 @@ impl From<InjectedExpressionId> for ExpressionOperandId { } } -#[derive(Clone, PartialEq, TyEncodable, TyDecodable, Hash, HashStable, TypeFoldable)] +#[derive(Clone, PartialEq, TyEncodable, TyDecodable, Hash, HashStable, TypeFoldable, TypeVisitable)] pub enum CoverageKind { Counter { function_source_hash: u64, @@ -148,18 +148,8 @@ impl Debug for CoverageKind { } } -#[derive( - Clone, - TyEncodable, - TyDecodable, - Hash, - HashStable, - TypeFoldable, - PartialEq, - Eq, - PartialOrd, - Ord -)] +#[derive(Clone, TyEncodable, TyDecodable, Hash, HashStable, PartialEq, Eq, PartialOrd, Ord)] +#[derive(TypeFoldable, TypeVisitable)] pub struct CodeRegion { pub file_name: Symbol, pub start_line: u32, @@ -178,7 +168,8 @@ impl Debug for CodeRegion { } } -#[derive(Copy, Clone, Debug, PartialEq, TyEncodable, TyDecodable, Hash, HashStable, TypeFoldable)] +#[derive(Copy, Clone, Debug, PartialEq, TyEncodable, TyDecodable, Hash, HashStable)] +#[derive(TypeFoldable, TypeVisitable)] pub enum Op { Subtract, Add, diff --git a/compiler/rustc_middle/src/mir/graph_cyclic_cache.rs b/compiler/rustc_middle/src/mir/graph_cyclic_cache.rs index 1279f5aee36..f97bf2883b3 100644 --- a/compiler/rustc_middle/src/mir/graph_cyclic_cache.rs +++ b/compiler/rustc_middle/src/mir/graph_cyclic_cache.rs @@ -58,6 +58,6 @@ impl<CTX> HashStable<CTX> for GraphIsCyclicCache { } } -TrivialTypeFoldableAndLiftImpls! { +TrivialTypeTraversalAndLiftImpls! { GraphIsCyclicCache, } diff --git a/compiler/rustc_middle/src/mir/interpret/allocation.rs b/compiler/rustc_middle/src/mir/interpret/allocation.rs index 10c4ea63a68..1bbd71c3f1f 100644 --- a/compiler/rustc_middle/src/mir/interpret/allocation.rs +++ b/compiler/rustc_middle/src/mir/interpret/allocation.rs @@ -160,12 +160,18 @@ impl AllocError { } /// The information that makes up a memory access: offset and size. -#[derive(Copy, Clone, Debug)] +#[derive(Copy, Clone)] pub struct AllocRange { pub start: Size, pub size: Size, } +impl fmt::Debug for AllocRange { + fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { + write!(f, "[{:#x}..{:#x}]", self.start.bytes(), self.end().bytes()) + } +} + /// Free-starting constructor for less syntactic overhead. #[inline(always)] pub fn alloc_range(start: Size, size: Size) -> AllocRange { @@ -537,21 +543,26 @@ impl<Tag: Provenance, Extra> Allocation<Tag, Extra> { /// Relocations. impl<Tag: Copy, Extra> Allocation<Tag, Extra> { /// Returns all relocations overlapping with the given pointer-offset pair. - pub fn get_relocations(&self, cx: &impl HasDataLayout, range: AllocRange) -> &[(Size, Tag)] { + fn get_relocations(&self, cx: &impl HasDataLayout, range: AllocRange) -> &[(Size, Tag)] { // We have to go back `pointer_size - 1` bytes, as that one would still overlap with // the beginning of this range. let start = range.start.bytes().saturating_sub(cx.data_layout().pointer_size.bytes() - 1); self.relocations.range(Size::from_bytes(start)..range.end()) } + /// Returns whether this allocation has relocations overlapping with the given range. + /// + /// Note: this function exists to allow `get_relocations` to be private, in order to somewhat + /// limit access to relocations outside of the `Allocation` abstraction. + /// + pub fn has_relocations(&self, cx: &impl HasDataLayout, range: AllocRange) -> bool { + !self.get_relocations(cx, range).is_empty() + } + /// Checks that there are no relocations overlapping with the given range. #[inline(always)] fn check_relocations(&self, cx: &impl HasDataLayout, range: AllocRange) -> AllocResult { - if self.get_relocations(cx, range).is_empty() { - Ok(()) - } else { - Err(AllocError::ReadPointerAsBytes) - } + if self.has_relocations(cx, range) { Err(AllocError::ReadPointerAsBytes) } else { Ok(()) } } /// Removes all relocations inside the given range. diff --git a/compiler/rustc_middle/src/mir/interpret/error.rs b/compiler/rustc_middle/src/mir/interpret/error.rs index a33a2921f57..2a1fd6f736e 100644 --- a/compiler/rustc_middle/src/mir/interpret/error.rs +++ b/compiler/rustc_middle/src/mir/interpret/error.rs @@ -29,7 +29,7 @@ impl From<ErrorGuaranteed> for ErrorHandled { } } -TrivialTypeFoldableAndLiftImpls! { +TrivialTypeTraversalAndLiftImpls! { ErrorHandled, } @@ -186,7 +186,7 @@ pub enum CheckInAllocMsg { impl fmt::Display for CheckInAllocMsg { /// When this is printed as an error the context looks like this: - /// "{msg}0x01 is not a valid pointer". + /// "{msg}{pointer} is a dangling pointer". fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { write!( f, @@ -194,9 +194,9 @@ impl fmt::Display for CheckInAllocMsg { match *self { CheckInAllocMsg::DerefTest => "dereferencing pointer failed: ", CheckInAllocMsg::MemoryAccessTest => "memory access failed: ", - CheckInAllocMsg::PointerArithmeticTest => "pointer arithmetic failed: ", + CheckInAllocMsg::PointerArithmeticTest => "out-of-bounds pointer arithmetic: ", CheckInAllocMsg::OffsetFromTest => "out-of-bounds offset_from: ", - CheckInAllocMsg::InboundsTest => "", + CheckInAllocMsg::InboundsTest => "out-of-bounds pointer use: ", } ) } @@ -334,36 +334,28 @@ impl fmt::Display for UndefinedBehaviorInfo<'_> { p, ), PointerUseAfterFree(a) => { - write!(f, "pointer to {} was dereferenced after this allocation got freed", a) + write!(f, "pointer to {a:?} was dereferenced after this allocation got freed") } PointerOutOfBounds { alloc_id, alloc_size, ptr_offset, ptr_size: Size::ZERO, msg } => { write!( f, - "{}{alloc_id} has size {alloc_size}, so pointer at offset {ptr_offset} is out-of-bounds", - msg, - alloc_id = alloc_id, + "{msg}{alloc_id:?} has size {alloc_size}, so pointer at offset {ptr_offset} is out-of-bounds", alloc_size = alloc_size.bytes(), - ptr_offset = ptr_offset, ) } PointerOutOfBounds { alloc_id, alloc_size, ptr_offset, ptr_size, msg } => write!( f, - "{}{alloc_id} has size {alloc_size}, so pointer to {ptr_size} byte{ptr_size_p} starting at offset {ptr_offset} is out-of-bounds", - msg, - alloc_id = alloc_id, + "{msg}{alloc_id:?} has size {alloc_size}, so pointer to {ptr_size} byte{ptr_size_p} starting at offset {ptr_offset} is out-of-bounds", alloc_size = alloc_size.bytes(), ptr_size = ptr_size.bytes(), ptr_size_p = pluralize!(ptr_size.bytes()), - ptr_offset = ptr_offset, ), - DanglingIntPointer(0, CheckInAllocMsg::InboundsTest) => { - write!(f, "null pointer is not a valid pointer for this operation") - } - DanglingIntPointer(0, msg) => { - write!(f, "{}null pointer is not a valid pointer", msg) - } DanglingIntPointer(i, msg) => { - write!(f, "{}0x{:x} is not a valid pointer", msg, i) + write!( + f, + "{msg}{pointer} is a dangling pointer (it has no provenance)", + pointer = Pointer::<Option<AllocId>>::from_addr(*i), + ) } AlignmentCheckFailed { required, has } => write!( f, @@ -371,8 +363,8 @@ impl fmt::Display for UndefinedBehaviorInfo<'_> { has.bytes(), required.bytes() ), - WriteToReadOnly(a) => write!(f, "writing to {} which is read-only", a), - DerefFunctionPointer(a) => write!(f, "accessing {} which contains a function", a), + WriteToReadOnly(a) => write!(f, "writing to {a:?} which is read-only"), + DerefFunctionPointer(a) => write!(f, "accessing {a:?} which contains a function"), ValidationFailure { path: None, msg } => { write!(f, "constructing invalid value: {}", msg) } diff --git a/compiler/rustc_middle/src/mir/interpret/mod.rs b/compiler/rustc_middle/src/mir/interpret/mod.rs index 8733a85ef3f..698024b2330 100644 --- a/compiler/rustc_middle/src/mir/interpret/mod.rs +++ b/compiler/rustc_middle/src/mir/interpret/mod.rs @@ -190,11 +190,7 @@ impl fmt::Debug for AllocId { } } -impl fmt::Display for AllocId { - fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { - fmt::Debug::fmt(self, f) - } -} +// No "Display" since AllocIds are not usually user-visible. #[derive(TyDecodable, TyEncodable)] enum AllocDiscriminant { @@ -470,7 +466,7 @@ impl<'tcx> TyCtxt<'tcx> { return alloc_id; } let id = alloc_map.reserve(); - debug!("creating alloc {:?} with id {}", alloc, id); + debug!("creating alloc {alloc:?} with id {id:?}"); alloc_map.alloc_map.insert(id, alloc.clone()); alloc_map.dedup.insert(alloc, id); id @@ -538,7 +534,7 @@ impl<'tcx> TyCtxt<'tcx> { pub fn global_alloc(self, id: AllocId) -> GlobalAlloc<'tcx> { match self.get_global_alloc(id) { Some(alloc) => alloc, - None => bug!("could not find allocation for {}", id), + None => bug!("could not find allocation for {id:?}"), } } @@ -546,7 +542,7 @@ impl<'tcx> TyCtxt<'tcx> { /// call this function twice, even with the same `Allocation` will ICE the compiler. pub fn set_alloc_id_memory(self, id: AllocId, mem: ConstAllocation<'tcx>) { if let Some(old) = self.alloc_map.lock().alloc_map.insert(id, GlobalAlloc::Memory(mem)) { - bug!("tried to set allocation ID {}, but it was already existing as {:#?}", id, old); + bug!("tried to set allocation ID {id:?}, but it was already existing as {old:#?}"); } } diff --git a/compiler/rustc_middle/src/mir/interpret/pointer.rs b/compiler/rustc_middle/src/mir/interpret/pointer.rs index 26da93b9dce..d4cdf45d186 100644 --- a/compiler/rustc_middle/src/mir/interpret/pointer.rs +++ b/compiler/rustc_middle/src/mir/interpret/pointer.rs @@ -144,7 +144,7 @@ impl Provenance for AllocId { } // Print offset only if it is non-zero. if ptr.offset.bytes() > 0 { - write!(f, "+0x{:x}", ptr.offset.bytes())?; + write!(f, "+{:#x}", ptr.offset.bytes())?; } Ok(()) } @@ -181,7 +181,17 @@ impl<Tag: Provenance> fmt::Debug for Pointer<Option<Tag>> { fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { match self.provenance { Some(tag) => Provenance::fmt(&Pointer::new(tag, self.offset), f), - None => write!(f, "0x{:x}", self.offset.bytes()), + None => write!(f, "{:#x}[noalloc]", self.offset.bytes()), + } + } +} + +impl<Tag: Provenance> fmt::Display for Pointer<Option<Tag>> { + fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { + if self.provenance.is_none() && self.offset.bytes() == 0 { + write!(f, "null pointer") + } else { + fmt::Debug::fmt(self, f) } } } @@ -227,8 +237,13 @@ impl<Tag> Pointer<Option<Tag>> { impl<Tag> Pointer<Option<Tag>> { #[inline(always)] + pub fn from_addr(addr: u64) -> Self { + Pointer { provenance: None, offset: Size::from_bytes(addr) } + } + + #[inline(always)] pub fn null() -> Self { - Pointer { provenance: None, offset: Size::ZERO } + Pointer::from_addr(0) } } diff --git a/compiler/rustc_middle/src/mir/interpret/queries.rs b/compiler/rustc_middle/src/mir/interpret/queries.rs index 575147feebc..786927e2dad 100644 --- a/compiler/rustc_middle/src/mir/interpret/queries.rs +++ b/compiler/rustc_middle/src/mir/interpret/queries.rs @@ -1,8 +1,8 @@ use super::{ErrorHandled, EvalToConstValueResult, EvalToValTreeResult, GlobalId}; use crate::mir; -use crate::ty::fold::TypeFoldable; use crate::ty::subst::InternalSubsts; +use crate::ty::visit::TypeVisitable; use crate::ty::{self, query::TyCtxtAt, query::TyCtxtEnsure, TyCtxt}; use rustc_hir::def_id::DefId; use rustc_span::{Span, DUMMY_SP}; diff --git a/compiler/rustc_middle/src/mir/interpret/value.rs b/compiler/rustc_middle/src/mir/interpret/value.rs index e80918d5e5d..8ecbb5ab0b3 100644 --- a/compiler/rustc_middle/src/mir/interpret/value.rs +++ b/compiler/rustc_middle/src/mir/interpret/value.rs @@ -167,7 +167,7 @@ impl<Tag: Provenance> fmt::LowerHex for Scalar<Tag> { fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { match self { Scalar::Ptr(ptr, _size) => write!(f, "pointer to {:?}", ptr), - Scalar::Int(int) => write!(f, "0x{:x}", int), + Scalar::Int(int) => write!(f, "{:#x}", int), } } } diff --git a/compiler/rustc_middle/src/mir/mod.rs b/compiler/rustc_middle/src/mir/mod.rs index ad33a54e0a2..e7d7317456c 100644 --- a/compiler/rustc_middle/src/mir/mod.rs +++ b/compiler/rustc_middle/src/mir/mod.rs @@ -8,9 +8,10 @@ use crate::mir::interpret::{ use crate::mir::traversal::PostorderCache; use crate::mir::visit::MirVisitable; use crate::ty::codec::{TyDecoder, TyEncoder}; -use crate::ty::fold::{FallibleTypeFolder, TypeFoldable, TypeSuperFoldable, TypeVisitor}; +use crate::ty::fold::{FallibleTypeFolder, TypeFoldable, TypeSuperFoldable}; use crate::ty::print::{FmtPrinter, Printer}; use crate::ty::subst::{GenericArg, InternalSubsts, Subst, SubstsRef}; +use crate::ty::visit::{TypeSuperVisitable, TypeVisitable, TypeVisitor}; use crate::ty::{self, List, Ty, TyCtxt}; use crate::ty::{AdtDef, InstanceDef, ScalarInt, UserTypeAnnotationIndex}; @@ -68,6 +69,7 @@ pub use terminator::*; pub mod traversal; mod type_foldable; +mod type_visitable; pub mod visit; pub use self::generic_graph::graphviz_safe_def_name; @@ -136,7 +138,7 @@ impl MirPhase { /// Where a specific `mir::Body` comes from. #[derive(Copy, Clone, Debug, PartialEq, Eq)] -#[derive(HashStable, TyEncodable, TyDecodable, TypeFoldable)] +#[derive(HashStable, TyEncodable, TyDecodable, TypeFoldable, TypeVisitable)] pub struct MirSource<'tcx> { pub instance: InstanceDef<'tcx>, @@ -166,7 +168,7 @@ impl<'tcx> MirSource<'tcx> { } } -#[derive(Clone, TyEncodable, TyDecodable, Debug, HashStable, TypeFoldable)] +#[derive(Clone, TyEncodable, TyDecodable, Debug, HashStable, TypeFoldable, TypeVisitable)] pub struct GeneratorInfo<'tcx> { /// The yield type of the function, if it is a generator. pub yield_ty: Option<Ty<'tcx>>, @@ -183,7 +185,7 @@ pub struct GeneratorInfo<'tcx> { } /// The lowered representation of a single function. -#[derive(Clone, TyEncodable, TyDecodable, Debug, HashStable, TypeFoldable)] +#[derive(Clone, TyEncodable, TyDecodable, Debug, HashStable, TypeFoldable, TypeVisitable)] pub struct Body<'tcx> { /// A list of basic blocks. References to basic block use a newtyped index type [`BasicBlock`] /// that indexes into this vector. @@ -357,10 +359,7 @@ impl<'tcx> Body<'tcx> { // // FIXME: Use a finer-grained API for this, so only transformations that alter terminators // invalidate the caches. - self.predecessor_cache.invalidate(); - self.switch_source_cache.invalidate(); - self.is_cyclic.invalidate(); - self.postorder_cache.invalidate(); + self.invalidate_cfg_cache(); &mut self.basic_blocks } @@ -368,10 +367,7 @@ impl<'tcx> Body<'tcx> { pub fn basic_blocks_and_local_decls_mut( &mut self, ) -> (&mut IndexVec<BasicBlock, BasicBlockData<'tcx>>, &mut LocalDecls<'tcx>) { - self.predecessor_cache.invalidate(); - self.switch_source_cache.invalidate(); - self.is_cyclic.invalidate(); - self.postorder_cache.invalidate(); + self.invalidate_cfg_cache(); (&mut self.basic_blocks, &mut self.local_decls) } @@ -383,11 +379,43 @@ impl<'tcx> Body<'tcx> { &mut LocalDecls<'tcx>, &mut Vec<VarDebugInfo<'tcx>>, ) { + self.invalidate_cfg_cache(); + (&mut self.basic_blocks, &mut self.local_decls, &mut self.var_debug_info) + } + + /// Get mutable access to parts of the Body without invalidating the CFG cache. + /// + /// By calling this method instead of eg [`Body::basic_blocks_mut`], you promise not to change + /// the CFG. This means that + /// + /// 1) The number of basic blocks remains unchanged + /// 2) The set of successors of each terminator remains unchanged. + /// 3) For each `TerminatorKind::SwitchInt`, the `targets` remains the same and the terminator + /// kind is not changed. + /// + /// If any of these conditions cannot be upheld, you should call [`Body::invalidate_cfg_cache`]. + #[inline] + pub fn basic_blocks_local_decls_mut_and_var_debug_info_no_invalidate( + &mut self, + ) -> ( + &mut IndexVec<BasicBlock, BasicBlockData<'tcx>>, + &mut LocalDecls<'tcx>, + &mut Vec<VarDebugInfo<'tcx>>, + ) { + (&mut self.basic_blocks, &mut self.local_decls, &mut self.var_debug_info) + } + + /// Invalidates cached information about the CFG. + /// + /// You will only ever need this if you have also called + /// [`Body::basic_blocks_local_decls_mut_and_var_debug_info_no_invalidate`]. All other methods + /// that allow you to mutate the body also call this method themselves, thereby avoiding any + /// risk of accidentaly cache invalidation. + pub fn invalidate_cfg_cache(&mut self) { self.predecessor_cache.invalidate(); self.switch_source_cache.invalidate(); self.is_cyclic.invalidate(); self.postorder_cache.invalidate(); - (&mut self.basic_blocks, &mut self.local_decls, &mut self.var_debug_info) } /// Returns `true` if a cycle exists in the control-flow graph that is reachable from the @@ -575,7 +603,7 @@ impl<'tcx> IndexMut<BasicBlock> for Body<'tcx> { } } -#[derive(Copy, Clone, Debug, HashStable, TypeFoldable)] +#[derive(Copy, Clone, Debug, HashStable, TypeFoldable, TypeVisitable)] pub enum ClearCrossCrate<T> { Clear, Set(T), @@ -736,7 +764,7 @@ pub enum ImplicitSelfKind { None, } -TrivialTypeFoldableAndLiftImpls! { BindingForm<'tcx>, } +TrivialTypeTraversalAndLiftImpls! { BindingForm<'tcx>, } mod binding_form_impl { use rustc_data_structures::stable_hasher::{HashStable, StableHasher}; @@ -781,7 +809,7 @@ pub struct BlockTailInfo { /// /// This can be a binding declared by the user, a temporary inserted by the compiler, a function /// argument, or the return place. -#[derive(Clone, Debug, TyEncodable, TyDecodable, HashStable, TypeFoldable)] +#[derive(Clone, Debug, TyEncodable, TyDecodable, HashStable, TypeFoldable, TypeVisitable)] pub struct LocalDecl<'tcx> { /// Whether this is a mutable binding (i.e., `let x` or `let mut x`). /// @@ -916,7 +944,7 @@ static_assert_size!(LocalDecl<'_>, 56); /// /// Not used for non-StaticRef temporaries, the return place, or anonymous /// function parameters. -#[derive(Clone, Debug, TyEncodable, TyDecodable, HashStable, TypeFoldable)] +#[derive(Clone, Debug, TyEncodable, TyDecodable, HashStable, TypeFoldable, TypeVisitable)] pub enum LocalInfo<'tcx> { /// A user-defined local variable or function parameter /// @@ -1055,7 +1083,7 @@ impl<'tcx> LocalDecl<'tcx> { } } -#[derive(Clone, TyEncodable, TyDecodable, HashStable, TypeFoldable)] +#[derive(Clone, TyEncodable, TyDecodable, HashStable, TypeFoldable, TypeVisitable)] pub enum VarDebugInfoContents<'tcx> { /// NOTE(eddyb) There's an unenforced invariant that this `Place` is /// based on a `Local`, not a `Static`, and contains no indexing. @@ -1073,7 +1101,7 @@ impl<'tcx> Debug for VarDebugInfoContents<'tcx> { } /// Debug information pertaining to a user variable. -#[derive(Clone, Debug, TyEncodable, TyDecodable, HashStable, TypeFoldable)] +#[derive(Clone, Debug, TyEncodable, TyDecodable, HashStable, TypeFoldable, TypeVisitable)] pub struct VarDebugInfo<'tcx> { pub name: Symbol, @@ -1129,7 +1157,7 @@ impl BasicBlock { // BasicBlockData /// See [`BasicBlock`] for documentation on what basic blocks are at a high level. -#[derive(Clone, Debug, TyEncodable, TyDecodable, HashStable, TypeFoldable)] +#[derive(Clone, Debug, TyEncodable, TyDecodable, HashStable, TypeFoldable, TypeVisitable)] pub struct BasicBlockData<'tcx> { /// List of statements in this block. pub statements: Vec<Statement<'tcx>>, @@ -1366,7 +1394,7 @@ impl<O: fmt::Debug> fmt::Debug for AssertKind<O> { /////////////////////////////////////////////////////////////////////////// // Statements -#[derive(Clone, TyEncodable, TyDecodable, HashStable, TypeFoldable)] +#[derive(Clone, TyEncodable, TyDecodable, HashStable, TypeFoldable, TypeVisitable)] pub struct Statement<'tcx> { pub source_info: SourceInfo, pub kind: StatementKind<'tcx>, @@ -1732,7 +1760,7 @@ impl SourceScope { } } -#[derive(Clone, Debug, TyEncodable, TyDecodable, HashStable, TypeFoldable)] +#[derive(Clone, Debug, TyEncodable, TyDecodable, HashStable, TypeFoldable, TypeVisitable)] pub struct SourceScopeData<'tcx> { pub span: Span, pub parent_scope: Option<SourceScope>, @@ -2498,7 +2526,7 @@ impl<'tcx> ConstantKind<'tcx> { /// The first will lead to the constraint `w: &'1 str` (for some /// inferred region `'1`). The second will lead to the constraint `w: /// &'static str`. -#[derive(Clone, Debug, TyEncodable, TyDecodable, HashStable, TypeFoldable)] +#[derive(Clone, Debug, TyEncodable, TyDecodable, HashStable, TypeFoldable, TypeVisitable)] pub struct UserTypeProjections { pub contents: Vec<(UserTypeProjection, Span)>, } @@ -2615,7 +2643,7 @@ impl UserTypeProjection { } } -TrivialTypeFoldableAndLiftImpls! { ProjectionKind, } +TrivialTypeTraversalAndLiftImpls! { ProjectionKind, } impl<'tcx> TypeFoldable<'tcx> for UserTypeProjection { fn try_fold_with<F: FallibleTypeFolder<'tcx>>(self, folder: &mut F) -> Result<Self, F::Error> { @@ -2624,7 +2652,9 @@ impl<'tcx> TypeFoldable<'tcx> for UserTypeProjection { projs: self.projs.try_fold_with(folder)?, }) } +} +impl<'tcx> TypeVisitable<'tcx> for UserTypeProjection { fn visit_with<Vs: TypeVisitor<'tcx>>(&self, visitor: &mut Vs) -> ControlFlow<Vs::BreakTy> { self.base.visit_with(visitor) // Note: there's nothing in `self.proj` to visit. diff --git a/compiler/rustc_middle/src/mir/predecessors.rs b/compiler/rustc_middle/src/mir/predecessors.rs index 620cf7e336b..5f1fadaf3bc 100644 --- a/compiler/rustc_middle/src/mir/predecessors.rs +++ b/compiler/rustc_middle/src/mir/predecessors.rs @@ -73,6 +73,6 @@ impl<CTX> HashStable<CTX> for PredecessorCache { } } -TrivialTypeFoldableAndLiftImpls! { +TrivialTypeTraversalAndLiftImpls! { PredecessorCache, } diff --git a/compiler/rustc_middle/src/mir/pretty.rs b/compiler/rustc_middle/src/mir/pretty.rs index 462c0ada3cf..24c6cd91d0a 100644 --- a/compiler/rustc_middle/src/mir/pretty.rs +++ b/compiler/rustc_middle/src/mir/pretty.rs @@ -716,12 +716,12 @@ pub fn write_allocations<'tcx>( } write!(w, "{}", display_allocation(tcx, alloc.inner())) }; - write!(w, "\n{}", id)?; + write!(w, "\n{id:?}")?; match tcx.get_global_alloc(id) { // This can't really happen unless there are bugs, but it doesn't cost us anything to // gracefully handle it and allow buggy rustc to be debugged via allocation printing. None => write!(w, " (deallocated)")?, - Some(GlobalAlloc::Function(inst)) => write!(w, " (fn: {})", inst)?, + Some(GlobalAlloc::Function(inst)) => write!(w, " (fn: {inst})")?, Some(GlobalAlloc::Static(did)) if !tcx.is_foreign_item(did) => { match tcx.eval_static_initializer(did) { Ok(alloc) => { diff --git a/compiler/rustc_middle/src/mir/query.rs b/compiler/rustc_middle/src/mir/query.rs index da4793fa039..620f0380d53 100644 --- a/compiler/rustc_middle/src/mir/query.rs +++ b/compiler/rustc_middle/src/mir/query.rs @@ -161,7 +161,7 @@ rustc_index::newtype_index! { } /// The layout of generator state. -#[derive(Clone, TyEncodable, TyDecodable, HashStable, TypeFoldable)] +#[derive(Clone, TyEncodable, TyDecodable, HashStable, TypeFoldable, TypeVisitable)] pub struct GeneratorLayout<'tcx> { /// The type of every local stored inside the generator. pub field_tys: IndexVec<GeneratorSavedLocal, Ty<'tcx>>, diff --git a/compiler/rustc_middle/src/mir/switch_sources.rs b/compiler/rustc_middle/src/mir/switch_sources.rs index 99d13fcfef4..d1f3e6b6fe6 100644 --- a/compiler/rustc_middle/src/mir/switch_sources.rs +++ b/compiler/rustc_middle/src/mir/switch_sources.rs @@ -73,6 +73,6 @@ impl<CTX> HashStable<CTX> for SwitchSourceCache { } } -TrivialTypeFoldableAndLiftImpls! { +TrivialTypeTraversalAndLiftImpls! { SwitchSourceCache, } diff --git a/compiler/rustc_middle/src/mir/syntax.rs b/compiler/rustc_middle/src/mir/syntax.rs index f8ee59f306f..5d4f3ea9e4c 100644 --- a/compiler/rustc_middle/src/mir/syntax.rs +++ b/compiler/rustc_middle/src/mir/syntax.rs @@ -179,7 +179,8 @@ pub enum BorrowKind { /// Not all of these are allowed at every [`MirPhase`]. Check the documentation there to see which /// ones you do not have to worry about. The MIR validator will generally enforce such restrictions, /// causing an ICE if they are violated. -#[derive(Clone, Debug, PartialEq, TyEncodable, TyDecodable, Hash, HashStable, TypeFoldable)] +#[derive(Clone, Debug, PartialEq, TyEncodable, TyDecodable, Hash, HashStable)] +#[derive(TypeFoldable, TypeVisitable)] pub enum StatementKind<'tcx> { /// Assign statements roughly correspond to an assignment in Rust proper (`x = ...`) except /// without the possibility of dropping the previous value (that must be done separately, if at @@ -311,6 +312,7 @@ pub enum StatementKind<'tcx> { /// Describes what kind of retag is to be performed. #[derive(Copy, Clone, TyEncodable, TyDecodable, Debug, PartialEq, Eq, Hash, HashStable)] +#[rustc_pass_by_value] pub enum RetagKind { /// The initial retag when entering a function. FnEntry, @@ -375,13 +377,15 @@ pub enum FakeReadCause { ForIndex, } -#[derive(Clone, Debug, PartialEq, TyEncodable, TyDecodable, Hash, HashStable, TypeFoldable)] +#[derive(Clone, Debug, PartialEq, TyEncodable, TyDecodable, Hash, HashStable)] +#[derive(TypeFoldable, TypeVisitable)] pub struct Coverage { pub kind: CoverageKind, pub code_region: Option<CodeRegion>, } -#[derive(Clone, Debug, PartialEq, TyEncodable, TyDecodable, Hash, HashStable, TypeFoldable)] +#[derive(Clone, Debug, PartialEq, TyEncodable, TyDecodable, Hash, HashStable)] +#[derive(TypeFoldable, TypeVisitable)] pub struct CopyNonOverlapping<'tcx> { pub src: Operand<'tcx>, pub dst: Operand<'tcx>, @@ -671,7 +675,8 @@ pub enum AssertKind<O> { ResumedAfterPanic(GeneratorKind), } -#[derive(Clone, Debug, PartialEq, TyEncodable, TyDecodable, Hash, HashStable, TypeFoldable)] +#[derive(Clone, Debug, PartialEq, TyEncodable, TyDecodable, Hash, HashStable)] +#[derive(TypeFoldable, TypeVisitable)] pub enum InlineAsmOperand<'tcx> { In { reg: InlineAsmRegOrRegClass, @@ -990,11 +995,20 @@ pub enum Rvalue<'tcx> { /// matching types and return a value of that type. BinaryOp(BinOp, Box<(Operand<'tcx>, Operand<'tcx>)>), - /// Same as `BinaryOp`, but yields `(T, bool)` instead of `T`. In addition to performing the - /// same computation as the matching `BinaryOp`, checks if the infinite precison result would be - /// unequal to the actual result and sets the `bool` if this is the case. + /// Same as `BinaryOp`, but yields `(T, bool)` with a `bool` indicating an error condition. /// - /// This only supports addition, subtraction, multiplication, and shift operations on integers. + /// When overflow checking is disabled and we are generating run-time code, the error condition + /// is false. Otherwise, and always during CTFE, the error condition is determined as described + /// below. + /// + /// For addition, subtraction, and multiplication on integers the error condition is set when + /// the infinite precision result would be unequal to the actual result. + /// + /// For shift operations on integers the error condition is set when the value of right-hand + /// side is greater than or equal to the number of bits in the type of the left-hand side, or + /// when the value of right-hand side is negative. + /// + /// Other combinations of types and operators are unsupported. CheckedBinaryOp(BinOp, Box<(Operand<'tcx>, Operand<'tcx>)>), /// Computes a value as described by the operation. diff --git a/compiler/rustc_middle/src/mir/tcx.rs b/compiler/rustc_middle/src/mir/tcx.rs index c93b7a95502..c99faf80187 100644 --- a/compiler/rustc_middle/src/mir/tcx.rs +++ b/compiler/rustc_middle/src/mir/tcx.rs @@ -9,7 +9,7 @@ use crate::ty::{self, Ty, TyCtxt}; use rustc_hir as hir; use rustc_target::abi::VariantIdx; -#[derive(Copy, Clone, Debug, TypeFoldable)] +#[derive(Copy, Clone, Debug, TypeFoldable, TypeVisitable)] pub struct PlaceTy<'tcx> { pub ty: Ty<'tcx>, /// Downcast to a particular variant of an enum or a generator, if included. diff --git a/compiler/rustc_middle/src/mir/traversal.rs b/compiler/rustc_middle/src/mir/traversal.rs index 7228e3f33b1..30648679dae 100644 --- a/compiler/rustc_middle/src/mir/traversal.rs +++ b/compiler/rustc_middle/src/mir/traversal.rs @@ -384,6 +384,6 @@ impl<CTX> HashStable<CTX> for PostorderCache { } } -TrivialTypeFoldableAndLiftImpls! { +TrivialTypeTraversalAndLiftImpls! { PostorderCache, } diff --git a/compiler/rustc_middle/src/mir/type_foldable.rs b/compiler/rustc_middle/src/mir/type_foldable.rs index 4201b2d11ce..3c9850a9eb3 100644 --- a/compiler/rustc_middle/src/mir/type_foldable.rs +++ b/compiler/rustc_middle/src/mir/type_foldable.rs @@ -4,7 +4,7 @@ use super::*; use crate::ty; use rustc_data_structures::functor::IdFunctor; -TrivialTypeFoldableAndLiftImpls! { +TrivialTypeTraversalAndLiftImpls! { BlockTailInfo, MirPhase, SourceInfo, @@ -89,65 +89,12 @@ impl<'tcx> TypeFoldable<'tcx> for Terminator<'tcx> { }; Ok(Terminator { source_info: self.source_info, kind }) } - - fn visit_with<V: TypeVisitor<'tcx>>(&self, visitor: &mut V) -> ControlFlow<V::BreakTy> { - use crate::mir::TerminatorKind::*; - - match self.kind { - SwitchInt { ref discr, switch_ty, .. } => { - discr.visit_with(visitor)?; - switch_ty.visit_with(visitor) - } - Drop { ref place, .. } => place.visit_with(visitor), - DropAndReplace { ref place, ref value, .. } => { - place.visit_with(visitor)?; - value.visit_with(visitor) - } - Yield { ref value, .. } => value.visit_with(visitor), - Call { ref func, ref args, ref destination, .. } => { - destination.visit_with(visitor)?; - func.visit_with(visitor)?; - args.visit_with(visitor) - } - Assert { ref cond, ref msg, .. } => { - cond.visit_with(visitor)?; - use AssertKind::*; - match msg { - BoundsCheck { ref len, ref index } => { - len.visit_with(visitor)?; - index.visit_with(visitor) - } - Overflow(_, l, r) => { - l.visit_with(visitor)?; - r.visit_with(visitor) - } - OverflowNeg(op) | DivisionByZero(op) | RemainderByZero(op) => { - op.visit_with(visitor) - } - ResumedAfterReturn(_) | ResumedAfterPanic(_) => ControlFlow::CONTINUE, - } - } - InlineAsm { ref operands, .. } => operands.visit_with(visitor), - Goto { .. } - | Resume - | Abort - | Return - | GeneratorDrop - | Unreachable - | FalseEdge { .. } - | FalseUnwind { .. } => ControlFlow::CONTINUE, - } - } } impl<'tcx> TypeFoldable<'tcx> for GeneratorKind { fn try_fold_with<F: FallibleTypeFolder<'tcx>>(self, _: &mut F) -> Result<Self, F::Error> { Ok(self) } - - fn visit_with<V: TypeVisitor<'tcx>>(&self, _: &mut V) -> ControlFlow<V::BreakTy> { - ControlFlow::CONTINUE - } } impl<'tcx> TypeFoldable<'tcx> for Place<'tcx> { @@ -157,21 +104,12 @@ impl<'tcx> TypeFoldable<'tcx> for Place<'tcx> { projection: self.projection.try_fold_with(folder)?, }) } - - fn visit_with<V: TypeVisitor<'tcx>>(&self, visitor: &mut V) -> ControlFlow<V::BreakTy> { - self.local.visit_with(visitor)?; - self.projection.visit_with(visitor) - } } impl<'tcx> TypeFoldable<'tcx> for &'tcx ty::List<PlaceElem<'tcx>> { fn try_fold_with<F: FallibleTypeFolder<'tcx>>(self, folder: &mut F) -> Result<Self, F::Error> { ty::util::fold_list(self, folder, |tcx, v| tcx.intern_place_elems(v)) } - - fn visit_with<V: TypeVisitor<'tcx>>(&self, visitor: &mut V) -> ControlFlow<V::BreakTy> { - self.iter().try_for_each(|t| t.visit_with(visitor)) - } } impl<'tcx> TypeFoldable<'tcx> for Rvalue<'tcx> { @@ -224,55 +162,6 @@ impl<'tcx> TypeFoldable<'tcx> for Rvalue<'tcx> { } }) } - - fn visit_with<V: TypeVisitor<'tcx>>(&self, visitor: &mut V) -> ControlFlow<V::BreakTy> { - use crate::mir::Rvalue::*; - match *self { - Use(ref op) => op.visit_with(visitor), - Repeat(ref op, _) => op.visit_with(visitor), - ThreadLocalRef(did) => did.visit_with(visitor), - Ref(region, _, ref place) => { - region.visit_with(visitor)?; - place.visit_with(visitor) - } - AddressOf(_, ref place) => place.visit_with(visitor), - Len(ref place) => place.visit_with(visitor), - Cast(_, ref op, ty) => { - op.visit_with(visitor)?; - ty.visit_with(visitor) - } - BinaryOp(_, box (ref rhs, ref lhs)) | CheckedBinaryOp(_, box (ref rhs, ref lhs)) => { - rhs.visit_with(visitor)?; - lhs.visit_with(visitor) - } - UnaryOp(_, ref val) => val.visit_with(visitor), - Discriminant(ref place) => place.visit_with(visitor), - NullaryOp(_, ty) => ty.visit_with(visitor), - Aggregate(ref kind, ref fields) => { - match **kind { - AggregateKind::Array(ty) => { - ty.visit_with(visitor)?; - } - AggregateKind::Tuple => {} - AggregateKind::Adt(_, _, substs, user_ty, _) => { - substs.visit_with(visitor)?; - user_ty.visit_with(visitor)?; - } - AggregateKind::Closure(_, substs) => { - substs.visit_with(visitor)?; - } - AggregateKind::Generator(_, substs, _) => { - substs.visit_with(visitor)?; - } - } - fields.visit_with(visitor) - } - ShallowInitBox(ref op, ty) => { - op.visit_with(visitor)?; - ty.visit_with(visitor) - } - } - } } impl<'tcx> TypeFoldable<'tcx> for Operand<'tcx> { @@ -283,13 +172,6 @@ impl<'tcx> TypeFoldable<'tcx> for Operand<'tcx> { Operand::Constant(c) => Operand::Constant(c.try_fold_with(folder)?), }) } - - fn visit_with<V: TypeVisitor<'tcx>>(&self, visitor: &mut V) -> ControlFlow<V::BreakTy> { - match *self { - Operand::Copy(ref place) | Operand::Move(ref place) => place.visit_with(visitor), - Operand::Constant(ref c) => c.visit_with(visitor), - } - } } impl<'tcx> TypeFoldable<'tcx> for PlaceElem<'tcx> { @@ -307,43 +189,24 @@ impl<'tcx> TypeFoldable<'tcx> for PlaceElem<'tcx> { Subslice { from, to, from_end } => Subslice { from, to, from_end }, }) } - - fn visit_with<Vs: TypeVisitor<'tcx>>(&self, visitor: &mut Vs) -> ControlFlow<Vs::BreakTy> { - use crate::mir::ProjectionElem::*; - - match self { - Field(_, ty) => ty.visit_with(visitor), - Index(v) => v.visit_with(visitor), - _ => ControlFlow::CONTINUE, - } - } } impl<'tcx> TypeFoldable<'tcx> for Field { fn try_fold_with<F: FallibleTypeFolder<'tcx>>(self, _: &mut F) -> Result<Self, F::Error> { Ok(self) } - fn visit_with<V: TypeVisitor<'tcx>>(&self, _: &mut V) -> ControlFlow<V::BreakTy> { - ControlFlow::CONTINUE - } } impl<'tcx> TypeFoldable<'tcx> for GeneratorSavedLocal { fn try_fold_with<F: FallibleTypeFolder<'tcx>>(self, _: &mut F) -> Result<Self, F::Error> { Ok(self) } - fn visit_with<V: TypeVisitor<'tcx>>(&self, _: &mut V) -> ControlFlow<V::BreakTy> { - ControlFlow::CONTINUE - } } impl<'tcx, R: Idx, C: Idx> TypeFoldable<'tcx> for BitMatrix<R, C> { fn try_fold_with<F: FallibleTypeFolder<'tcx>>(self, _: &mut F) -> Result<Self, F::Error> { Ok(self) } - fn visit_with<V: TypeVisitor<'tcx>>(&self, _: &mut V) -> ControlFlow<V::BreakTy> { - ControlFlow::CONTINUE - } } impl<'tcx> TypeFoldable<'tcx> for Constant<'tcx> { @@ -354,10 +217,6 @@ impl<'tcx> TypeFoldable<'tcx> for Constant<'tcx> { literal: self.literal.try_fold_with(folder)?, }) } - fn visit_with<V: TypeVisitor<'tcx>>(&self, visitor: &mut V) -> ControlFlow<V::BreakTy> { - self.literal.visit_with(visitor)?; - self.user_ty.visit_with(visitor) - } } impl<'tcx> TypeFoldable<'tcx> for ConstantKind<'tcx> { @@ -365,10 +224,6 @@ impl<'tcx> TypeFoldable<'tcx> for ConstantKind<'tcx> { fn try_fold_with<F: FallibleTypeFolder<'tcx>>(self, folder: &mut F) -> Result<Self, F::Error> { folder.try_fold_mir_const(self) } - - fn visit_with<V: TypeVisitor<'tcx>>(&self, visitor: &mut V) -> ControlFlow<V::BreakTy> { - visitor.visit_mir_const(*self) - } } impl<'tcx> TypeSuperFoldable<'tcx> for ConstantKind<'tcx> { @@ -381,11 +236,4 @@ impl<'tcx> TypeSuperFoldable<'tcx> for ConstantKind<'tcx> { ConstantKind::Val(v, t) => Ok(ConstantKind::Val(v, t.try_fold_with(folder)?)), } } - - fn super_visit_with<V: TypeVisitor<'tcx>>(&self, visitor: &mut V) -> ControlFlow<V::BreakTy> { - match *self { - ConstantKind::Ty(c) => c.visit_with(visitor), - ConstantKind::Val(_, t) => t.visit_with(visitor), - } - } } diff --git a/compiler/rustc_middle/src/mir/type_visitable.rs b/compiler/rustc_middle/src/mir/type_visitable.rs new file mode 100644 index 00000000000..d52ae5fac67 --- /dev/null +++ b/compiler/rustc_middle/src/mir/type_visitable.rs @@ -0,0 +1,186 @@ +//! `TypeVisitable` implementations for MIR types + +use super::*; +use crate::ty; + +impl<'tcx> TypeVisitable<'tcx> for Terminator<'tcx> { + fn visit_with<V: TypeVisitor<'tcx>>(&self, visitor: &mut V) -> ControlFlow<V::BreakTy> { + use crate::mir::TerminatorKind::*; + + match self.kind { + SwitchInt { ref discr, switch_ty, .. } => { + discr.visit_with(visitor)?; + switch_ty.visit_with(visitor) + } + Drop { ref place, .. } => place.visit_with(visitor), + DropAndReplace { ref place, ref value, .. } => { + place.visit_with(visitor)?; + value.visit_with(visitor) + } + Yield { ref value, .. } => value.visit_with(visitor), + Call { ref func, ref args, ref destination, .. } => { + destination.visit_with(visitor)?; + func.visit_with(visitor)?; + args.visit_with(visitor) + } + Assert { ref cond, ref msg, .. } => { + cond.visit_with(visitor)?; + use AssertKind::*; + match msg { + BoundsCheck { ref len, ref index } => { + len.visit_with(visitor)?; + index.visit_with(visitor) + } + Overflow(_, l, r) => { + l.visit_with(visitor)?; + r.visit_with(visitor) + } + OverflowNeg(op) | DivisionByZero(op) | RemainderByZero(op) => { + op.visit_with(visitor) + } + ResumedAfterReturn(_) | ResumedAfterPanic(_) => ControlFlow::CONTINUE, + } + } + InlineAsm { ref operands, .. } => operands.visit_with(visitor), + Goto { .. } + | Resume + | Abort + | Return + | GeneratorDrop + | Unreachable + | FalseEdge { .. } + | FalseUnwind { .. } => ControlFlow::CONTINUE, + } + } +} + +impl<'tcx> TypeVisitable<'tcx> for GeneratorKind { + fn visit_with<V: TypeVisitor<'tcx>>(&self, _: &mut V) -> ControlFlow<V::BreakTy> { + ControlFlow::CONTINUE + } +} + +impl<'tcx> TypeVisitable<'tcx> for Place<'tcx> { + fn visit_with<V: TypeVisitor<'tcx>>(&self, visitor: &mut V) -> ControlFlow<V::BreakTy> { + self.local.visit_with(visitor)?; + self.projection.visit_with(visitor) + } +} + +impl<'tcx> TypeVisitable<'tcx> for &'tcx ty::List<PlaceElem<'tcx>> { + fn visit_with<V: TypeVisitor<'tcx>>(&self, visitor: &mut V) -> ControlFlow<V::BreakTy> { + self.iter().try_for_each(|t| t.visit_with(visitor)) + } +} + +impl<'tcx> TypeVisitable<'tcx> for Rvalue<'tcx> { + fn visit_with<V: TypeVisitor<'tcx>>(&self, visitor: &mut V) -> ControlFlow<V::BreakTy> { + use crate::mir::Rvalue::*; + match *self { + Use(ref op) => op.visit_with(visitor), + Repeat(ref op, _) => op.visit_with(visitor), + ThreadLocalRef(did) => did.visit_with(visitor), + Ref(region, _, ref place) => { + region.visit_with(visitor)?; + place.visit_with(visitor) + } + AddressOf(_, ref place) => place.visit_with(visitor), + Len(ref place) => place.visit_with(visitor), + Cast(_, ref op, ty) => { + op.visit_with(visitor)?; + ty.visit_with(visitor) + } + BinaryOp(_, box (ref rhs, ref lhs)) | CheckedBinaryOp(_, box (ref rhs, ref lhs)) => { + rhs.visit_with(visitor)?; + lhs.visit_with(visitor) + } + UnaryOp(_, ref val) => val.visit_with(visitor), + Discriminant(ref place) => place.visit_with(visitor), + NullaryOp(_, ty) => ty.visit_with(visitor), + Aggregate(ref kind, ref fields) => { + match **kind { + AggregateKind::Array(ty) => { + ty.visit_with(visitor)?; + } + AggregateKind::Tuple => {} + AggregateKind::Adt(_, _, substs, user_ty, _) => { + substs.visit_with(visitor)?; + user_ty.visit_with(visitor)?; + } + AggregateKind::Closure(_, substs) => { + substs.visit_with(visitor)?; + } + AggregateKind::Generator(_, substs, _) => { + substs.visit_with(visitor)?; + } + } + fields.visit_with(visitor) + } + ShallowInitBox(ref op, ty) => { + op.visit_with(visitor)?; + ty.visit_with(visitor) + } + } + } +} + +impl<'tcx> TypeVisitable<'tcx> for Operand<'tcx> { + fn visit_with<V: TypeVisitor<'tcx>>(&self, visitor: &mut V) -> ControlFlow<V::BreakTy> { + match *self { + Operand::Copy(ref place) | Operand::Move(ref place) => place.visit_with(visitor), + Operand::Constant(ref c) => c.visit_with(visitor), + } + } +} + +impl<'tcx> TypeVisitable<'tcx> for PlaceElem<'tcx> { + fn visit_with<Vs: TypeVisitor<'tcx>>(&self, visitor: &mut Vs) -> ControlFlow<Vs::BreakTy> { + use crate::mir::ProjectionElem::*; + + match self { + Field(_, ty) => ty.visit_with(visitor), + Index(v) => v.visit_with(visitor), + _ => ControlFlow::CONTINUE, + } + } +} + +impl<'tcx> TypeVisitable<'tcx> for Field { + fn visit_with<V: TypeVisitor<'tcx>>(&self, _: &mut V) -> ControlFlow<V::BreakTy> { + ControlFlow::CONTINUE + } +} + +impl<'tcx> TypeVisitable<'tcx> for GeneratorSavedLocal { + fn visit_with<V: TypeVisitor<'tcx>>(&self, _: &mut V) -> ControlFlow<V::BreakTy> { + ControlFlow::CONTINUE + } +} + +impl<'tcx, R: Idx, C: Idx> TypeVisitable<'tcx> for BitMatrix<R, C> { + fn visit_with<V: TypeVisitor<'tcx>>(&self, _: &mut V) -> ControlFlow<V::BreakTy> { + ControlFlow::CONTINUE + } +} + +impl<'tcx> TypeVisitable<'tcx> for Constant<'tcx> { + fn visit_with<V: TypeVisitor<'tcx>>(&self, visitor: &mut V) -> ControlFlow<V::BreakTy> { + self.literal.visit_with(visitor)?; + self.user_ty.visit_with(visitor) + } +} + +impl<'tcx> TypeVisitable<'tcx> for ConstantKind<'tcx> { + fn visit_with<V: TypeVisitor<'tcx>>(&self, visitor: &mut V) -> ControlFlow<V::BreakTy> { + visitor.visit_mir_const(*self) + } +} + +impl<'tcx> TypeSuperVisitable<'tcx> for ConstantKind<'tcx> { + fn super_visit_with<V: TypeVisitor<'tcx>>(&self, visitor: &mut V) -> ControlFlow<V::BreakTy> { + match *self { + ConstantKind::Ty(c) => c.visit_with(visitor), + ConstantKind::Val(_, t) => t.visit_with(visitor), + } + } +} diff --git a/compiler/rustc_middle/src/mir/visit.rs b/compiler/rustc_middle/src/mir/visit.rs index 5ce92d127f3..d1477f9e2ae 100644 --- a/compiler/rustc_middle/src/mir/visit.rs +++ b/compiler/rustc_middle/src/mir/visit.rs @@ -30,9 +30,11 @@ //! For example, the `super_basic_block_data` method begins like this: //! //! ```ignore (pseudo-rust) -//! fn super_basic_block_data(&mut self, -//! block: BasicBlock, -//! data: & $($mutability)? BasicBlockData<'tcx>) { +//! fn super_basic_block_data( +//! &mut self, +//! block: BasicBlock, +//! data: & $($mutability)? BasicBlockData<'tcx> +//! ) { //! let BasicBlockData { //! statements, //! terminator, @@ -78,106 +80,135 @@ macro_rules! make_mir_visitor { self.super_body(body); } - fn visit_basic_block_data(&mut self, - block: BasicBlock, - data: & $($mutability)? BasicBlockData<'tcx>) { + fn visit_basic_block_data( + &mut self, + block: BasicBlock, + data: & $($mutability)? BasicBlockData<'tcx>, + ) { self.super_basic_block_data(block, data); } - fn visit_source_scope_data(&mut self, - scope_data: & $($mutability)? SourceScopeData<'tcx>) { + fn visit_source_scope_data( + &mut self, + scope_data: & $($mutability)? SourceScopeData<'tcx>, + ) { self.super_source_scope_data(scope_data); } - fn visit_statement(&mut self, - statement: & $($mutability)? Statement<'tcx>, - location: Location) { + fn visit_statement( + &mut self, + statement: & $($mutability)? Statement<'tcx>, + location: Location, + ) { self.super_statement(statement, location); } - fn visit_assign(&mut self, - place: & $($mutability)? Place<'tcx>, - rvalue: & $($mutability)? Rvalue<'tcx>, - location: Location) { + fn visit_assign( + &mut self, + place: & $($mutability)? Place<'tcx>, + rvalue: & $($mutability)? Rvalue<'tcx>, + location: Location, + ) { self.super_assign(place, rvalue, location); } - fn visit_terminator(&mut self, - terminator: & $($mutability)? Terminator<'tcx>, - location: Location) { + fn visit_terminator( + &mut self, + terminator: & $($mutability)? Terminator<'tcx>, + location: Location, + ) { self.super_terminator(terminator, location); } - fn visit_assert_message(&mut self, - msg: & $($mutability)? AssertMessage<'tcx>, - location: Location) { + fn visit_assert_message( + &mut self, + msg: & $($mutability)? AssertMessage<'tcx>, + location: Location, + ) { self.super_assert_message(msg, location); } - fn visit_rvalue(&mut self, - rvalue: & $($mutability)? Rvalue<'tcx>, - location: Location) { + fn visit_rvalue( + &mut self, + rvalue: & $($mutability)? Rvalue<'tcx>, + location: Location, + ) { self.super_rvalue(rvalue, location); } - fn visit_operand(&mut self, - operand: & $($mutability)? Operand<'tcx>, - location: Location) { + fn visit_operand( + &mut self, + operand: & $($mutability)? Operand<'tcx>, + location: Location, + ) { self.super_operand(operand, location); } - fn visit_ascribe_user_ty(&mut self, - place: & $($mutability)? Place<'tcx>, - variance: & $($mutability)? ty::Variance, - user_ty: & $($mutability)? UserTypeProjection, - location: Location) { + fn visit_ascribe_user_ty( + &mut self, + place: & $($mutability)? Place<'tcx>, + variance: $(& $mutability)? ty::Variance, + user_ty: & $($mutability)? UserTypeProjection, + location: Location, + ) { self.super_ascribe_user_ty(place, variance, user_ty, location); } - fn visit_coverage(&mut self, - coverage: & $($mutability)? Coverage, - location: Location) { + fn visit_coverage( + &mut self, + coverage: & $($mutability)? Coverage, + location: Location, + ) { self.super_coverage(coverage, location); } - fn visit_retag(&mut self, - kind: & $($mutability)? RetagKind, - place: & $($mutability)? Place<'tcx>, - location: Location) { + fn visit_retag( + &mut self, + kind: $(& $mutability)? RetagKind, + place: & $($mutability)? Place<'tcx>, + location: Location, + ) { self.super_retag(kind, place, location); } - fn visit_place(&mut self, - place: & $($mutability)? Place<'tcx>, - context: PlaceContext, - location: Location) { + fn visit_place( + &mut self, + place: & $($mutability)? Place<'tcx>, + context: PlaceContext, + location: Location, + ) { self.super_place(place, context, location); } visit_place_fns!($($mutability)?); - fn visit_constant(&mut self, - constant: & $($mutability)? Constant<'tcx>, - location: Location) { + fn visit_constant( + &mut self, + constant: & $($mutability)? Constant<'tcx>, + location: Location, + ) { self.super_constant(constant, location); } - // The macro results in a false positive of sorts, where &mut Span - // is fine, but &Span is not; just allow the lint. - #[allow(rustc::pass_by_value)] - fn visit_span(&mut self, - span: & $($mutability)? Span) { + fn visit_span( + &mut self, + span: $(& $mutability)? Span, + ) { self.super_span(span); } - fn visit_source_info(&mut self, - source_info: & $($mutability)? SourceInfo) { + fn visit_source_info( + &mut self, + source_info: & $($mutability)? SourceInfo, + ) { self.super_source_info(source_info); } - fn visit_ty(&mut self, - ty: $(& $mutability)? Ty<'tcx>, - _: TyContext) { + fn visit_ty( + &mut self, + ty: $(& $mutability)? Ty<'tcx>, + _: TyContext, + ) { self.super_ty(ty); } @@ -196,45 +227,56 @@ macro_rules! make_mir_visitor { self.super_user_type_annotation(index, ty); } - fn visit_region(&mut self, - region: $(& $mutability)? ty::Region<'tcx>, - _: Location) { + fn visit_region( + &mut self, + region: $(& $mutability)? ty::Region<'tcx>, + _: Location, + ) { self.super_region(region); } - fn visit_const(&mut self, - constant: $(& $mutability)? ty::Const<'tcx>, - _: Location) { + fn visit_const( + &mut self, + constant: $(& $mutability)? ty::Const<'tcx>, + _: Location, + ) { self.super_const(constant); } - fn visit_substs(&mut self, - substs: & $($mutability)? SubstsRef<'tcx>, - _: Location) { + fn visit_substs( + &mut self, + substs: & $($mutability)? SubstsRef<'tcx>, + _: Location, + ) { self.super_substs(substs); } - fn visit_local_decl(&mut self, - local: Local, - local_decl: & $($mutability)? LocalDecl<'tcx>) { + fn visit_local_decl( + &mut self, + local: Local, + local_decl: & $($mutability)? LocalDecl<'tcx>, + ) { self.super_local_decl(local, local_decl); } - fn visit_var_debug_info(&mut self, - var_debug_info: & $($mutability)* VarDebugInfo<'tcx>) { + fn visit_var_debug_info( + &mut self, + var_debug_info: & $($mutability)* VarDebugInfo<'tcx>, + ) { self.super_var_debug_info(var_debug_info); } - #[allow(rustc::pass_by_value)] - fn visit_local(&mut self, - _local: & $($mutability)? Local, - _context: PlaceContext, - _location: Location) { - } + fn visit_local( + &mut self, + _local: $(& $mutability)? Local, + _context: PlaceContext, + _location: Location, + ) {} - #[allow(rustc::pass_by_value)] - fn visit_source_scope(&mut self, - scope: & $($mutability)? SourceScope) { + fn visit_source_scope( + &mut self, + scope: $(& $mutability)? SourceScope, + ) { self.super_source_scope(scope); } @@ -296,7 +338,7 @@ macro_rules! make_mir_visitor { self.visit_var_debug_info(var_debug_info); } - self.visit_span(&$($mutability)? body.span); + self.visit_span($(& $mutability)? body.span); for const_ in &$($mutability)? body.required_consts { let location = START_BLOCK.start_location(); @@ -338,14 +380,14 @@ macro_rules! make_mir_visitor { local_data: _, } = scope_data; - self.visit_span(span); + self.visit_span($(& $mutability)? *span); if let Some(parent_scope) = parent_scope { - self.visit_source_scope(parent_scope); + self.visit_source_scope($(& $mutability)? *parent_scope); } if let Some((callee, callsite_span)) = inlined { let location = START_BLOCK.start_location(); - self.visit_span(callsite_span); + self.visit_span($(& $mutability)? *callsite_span); let ty::Instance { def: callee_def, substs: callee_substs } = callee; match callee_def { @@ -368,7 +410,7 @@ macro_rules! make_mir_visitor { self.visit_substs(callee_substs, location); } if let Some(inlined_parent_scope) = inlined_parent_scope { - self.visit_source_scope(inlined_parent_scope); + self.visit_source_scope($(& $mutability)? *inlined_parent_scope); } } @@ -383,7 +425,7 @@ macro_rules! make_mir_visitor { self.visit_source_info(source_info); match kind { StatementKind::Assign( - box(ref $($mutability)? place, ref $($mutability)? rvalue) + box (place, rvalue) ) => { self.visit_assign(place, rvalue, location); } @@ -410,26 +452,26 @@ macro_rules! make_mir_visitor { } StatementKind::StorageLive(local) => { self.visit_local( - local, + $(& $mutability)? *local, PlaceContext::NonUse(NonUseContext::StorageLive), location ); } StatementKind::StorageDead(local) => { self.visit_local( - local, + $(& $mutability)? *local, PlaceContext::NonUse(NonUseContext::StorageDead), location ); } StatementKind::Retag(kind, place) => { - self.visit_retag(kind, place, location); + self.visit_retag($(& $mutability)? *kind, place, location); } StatementKind::AscribeUserType( - box(ref $($mutability)? place, ref $($mutability)? user_ty), + box (place, user_ty), variance ) => { - self.visit_ascribe_user_ty(place, variance, user_ty, location); + self.visit_ascribe_user_ty(place, $(& $mutability)? *variance, user_ty, location); } StatementKind::Coverage(coverage) => { self.visit_coverage( @@ -438,9 +480,9 @@ macro_rules! make_mir_visitor { ) } StatementKind::CopyNonOverlapping(box crate::mir::CopyNonOverlapping{ - ref $($mutability)? src, - ref $($mutability)? dst, - ref $($mutability)? count, + src, + dst, + count, }) => { self.visit_operand(src, location); self.visit_operand(dst, location); @@ -475,15 +517,14 @@ macro_rules! make_mir_visitor { TerminatorKind::GeneratorDrop | TerminatorKind::Unreachable | TerminatorKind::FalseEdge { .. } | - TerminatorKind::FalseUnwind { .. } => { - } + TerminatorKind::FalseUnwind { .. } => {} TerminatorKind::Return => { // `return` logically moves from the return place `_0`. Note that the place // cannot be changed by any visitor, though. let $($mutability)? local = RETURN_PLACE; self.visit_local( - & $($mutability)? local, + $(& $mutability)? local, PlaceContext::NonMutatingUse(NonMutatingUseContext::Move), location, ); @@ -788,7 +829,7 @@ macro_rules! make_mir_visitor { fn super_ascribe_user_ty(&mut self, place: & $($mutability)? Place<'tcx>, - _variance: & $($mutability)? ty::Variance, + _variance: $(& $mutability)? ty::Variance, user_ty: & $($mutability)? UserTypeProjection, location: Location) { self.visit_place( @@ -805,7 +846,7 @@ macro_rules! make_mir_visitor { } fn super_retag(&mut self, - _kind: & $($mutability)? RetagKind, + _kind: $(& $mutability)? RetagKind, place: & $($mutability)? Place<'tcx>, location: Location) { self.visit_place( @@ -840,8 +881,10 @@ macro_rules! make_mir_visitor { self.visit_source_info(source_info); } - fn super_var_debug_info(&mut self, - var_debug_info: & $($mutability)? VarDebugInfo<'tcx>) { + fn super_var_debug_info( + &mut self, + var_debug_info: & $($mutability)? VarDebugInfo<'tcx> + ) { let VarDebugInfo { name: _, source_info, @@ -861,21 +904,23 @@ macro_rules! make_mir_visitor { } } - #[allow(rustc::pass_by_value)] - fn super_source_scope(&mut self, - _scope: & $($mutability)? SourceScope) { - } + fn super_source_scope( + &mut self, + _scope: $(& $mutability)? SourceScope + ) {} - fn super_constant(&mut self, - constant: & $($mutability)? Constant<'tcx>, - location: Location) { + fn super_constant( + &mut self, + constant: & $($mutability)? Constant<'tcx>, + location: Location + ) { let Constant { span, user_ty, literal, } = constant; - self.visit_span(span); + self.visit_span($(& $mutability)? *span); drop(user_ty); // no visit method for this match literal { ConstantKind::Ty(ct) => self.visit_const($(& $mutability)? *ct, location), @@ -883,10 +928,7 @@ macro_rules! make_mir_visitor { } } - // The macro results in a false positive of sorts, where &mut Span - // is fine, but &Span is not; just allow the lint. - #[allow(rustc::pass_by_value)] - fn super_span(&mut self, _span: & $($mutability)? Span) { + fn super_span(&mut self, _span: $(& $mutability)? Span) { } fn super_source_info(&mut self, source_info: & $($mutability)? SourceInfo) { @@ -895,8 +937,8 @@ macro_rules! make_mir_visitor { scope, } = source_info; - self.visit_span(span); - self.visit_source_scope(scope); + self.visit_span($(& $mutability)? *span); + self.visit_source_scope($(& $mutability)? *scope); } fn super_user_type_projection( @@ -910,7 +952,7 @@ macro_rules! make_mir_visitor { _index: UserTypeAnnotationIndex, ty: & $($mutability)? CanonicalUserTypeAnnotation<'tcx>, ) { - self.visit_span(& $($mutability)? ty.span); + self.visit_span($(& $mutability)? ty.span); self.visit_ty($(& $mutability)? ty.inferred_ty, TyContext::UserTy(ty.span)); } @@ -1058,7 +1100,7 @@ macro_rules! visit_place_fns { } } - self.visit_local(&place.local, context, location); + self.visit_local(place.local, context, location); self.visit_projection(place.as_ref(), context, location); } @@ -1091,7 +1133,7 @@ macro_rules! visit_place_fns { } ProjectionElem::Index(local) => { self.visit_local( - &local, + local, PlaceContext::NonMutatingUse(NonMutatingUseContext::Copy), location, ); diff --git a/compiler/rustc_middle/src/query/mod.rs b/compiler/rustc_middle/src/query/mod.rs index a1065eef850..b8bb93891c2 100644 --- a/compiler/rustc_middle/src/query/mod.rs +++ b/compiler/rustc_middle/src/query/mod.rs @@ -1356,9 +1356,13 @@ rustc_queries! { desc { "query a crate is `#![profiler_runtime]`" } separate_provide_extern } - query panic_strategy(_: CrateNum) -> PanicStrategy { + query has_ffi_unwind_calls(key: LocalDefId) -> bool { + desc { |tcx| "check if `{}` contains FFI-unwind calls", tcx.def_path_str(key.to_def_id()) } + cache_on_disk_if { true } + } + query required_panic_strategy(_: CrateNum) -> Option<PanicStrategy> { fatal_cycle - desc { "query a crate's configured panic strategy" } + desc { "query a crate's required panic strategy" } separate_provide_extern } query panic_in_drop_strategy(_: CrateNum) -> PanicStrategy { @@ -1821,7 +1825,8 @@ rustc_queries! { remap_env_constness } - /// Do not call this query directly: invoke `infcx.at().dropck_outlives()` instead. + /// Do not call this query directly: + /// invoke `DropckOutlives::new(dropped_ty)).fully_perform(typeck.infcx)` instead. query dropck_outlives( goal: CanonicalTyGoal<'tcx> ) -> Result< diff --git a/compiler/rustc_middle/src/thir.rs b/compiler/rustc_middle/src/thir.rs index 120d09ee353..03c11c2863f 100644 --- a/compiler/rustc_middle/src/thir.rs +++ b/compiler/rustc_middle/src/thir.rs @@ -191,18 +191,8 @@ pub enum StmtKind<'tcx> { #[cfg(all(target_arch = "x86_64", target_pointer_width = "64"))] rustc_data_structures::static_assert_size!(Expr<'_>, 104); -#[derive( - Clone, - Debug, - Copy, - PartialEq, - Eq, - Hash, - HashStable, - TyEncodable, - TyDecodable, - TypeFoldable -)] +#[derive(Clone, Debug, Copy, PartialEq, Eq, Hash, HashStable, TyEncodable, TyDecodable)] +#[derive(TypeFoldable, TypeVisitable)] pub struct LocalVarId(pub hir::HirId); /// A THIR expression. diff --git a/compiler/rustc_middle/src/thir/abstract_const.rs b/compiler/rustc_middle/src/thir/abstract_const.rs index e02ed414574..527dbd1cd09 100644 --- a/compiler/rustc_middle/src/thir/abstract_const.rs +++ b/compiler/rustc_middle/src/thir/abstract_const.rs @@ -42,7 +42,7 @@ impl From<ErrorGuaranteed> for NotConstEvaluatable { } } -TrivialTypeFoldableAndLiftImpls! { +TrivialTypeTraversalAndLiftImpls! { NotConstEvaluatable, } diff --git a/compiler/rustc_middle/src/traits/chalk.rs b/compiler/rustc_middle/src/traits/chalk.rs index 70abdb9ab4c..6d4af8bea62 100644 --- a/compiler/rustc_middle/src/traits/chalk.rs +++ b/compiler/rustc_middle/src/traits/chalk.rs @@ -390,7 +390,7 @@ impl<'tcx> chalk_ir::interner::HasInterner for RustInterner<'tcx> { } /// A chalk environment and goal. -#[derive(Copy, Clone, PartialEq, Eq, Hash, Debug, HashStable, TypeFoldable)] +#[derive(Copy, Clone, PartialEq, Eq, Hash, Debug, HashStable, TypeFoldable, TypeVisitable)] pub struct ChalkEnvironmentAndGoal<'tcx> { pub environment: &'tcx ty::List<ty::Predicate<'tcx>>, pub goal: ty::Predicate<'tcx>, diff --git a/compiler/rustc_middle/src/traits/mod.rs b/compiler/rustc_middle/src/traits/mod.rs index 7f913faf860..eee44df8645 100644 --- a/compiler/rustc_middle/src/traits/mod.rs +++ b/compiler/rustc_middle/src/traits/mod.rs @@ -523,7 +523,7 @@ pub struct DerivedObligationCause<'tcx> { pub parent_code: InternedObligationCauseCode<'tcx>, } -#[derive(Clone, Debug, TypeFoldable, Lift)] +#[derive(Clone, Debug, TypeFoldable, TypeVisitable, Lift)] pub enum SelectionError<'tcx> { /// The trait is not implemented. Unimplemented, @@ -592,7 +592,8 @@ pub type SelectionResult<'tcx, T> = Result<Option<T>, SelectionError<'tcx>>; /// ### The type parameter `N` /// /// See explanation on `ImplSourceUserDefinedData`. -#[derive(Clone, PartialEq, Eq, TyEncodable, TyDecodable, HashStable, TypeFoldable, Lift)] +#[derive(Clone, PartialEq, Eq, TyEncodable, TyDecodable, HashStable, Lift)] +#[derive(TypeFoldable, TypeVisitable)] pub enum ImplSource<'tcx, N> { /// ImplSource identifying a particular impl. UserDefined(ImplSourceUserDefinedData<'tcx, N>), @@ -753,14 +754,16 @@ impl<'tcx, N> ImplSource<'tcx, N> { /// is `Obligation`, as one might expect. During codegen, however, this /// is `()`, because codegen only requires a shallow resolution of an /// impl, and nested obligations are satisfied later. -#[derive(Clone, PartialEq, Eq, TyEncodable, TyDecodable, HashStable, TypeFoldable, Lift)] +#[derive(Clone, PartialEq, Eq, TyEncodable, TyDecodable, HashStable, Lift)] +#[derive(TypeFoldable, TypeVisitable)] pub struct ImplSourceUserDefinedData<'tcx, N> { pub impl_def_id: DefId, pub substs: SubstsRef<'tcx>, pub nested: Vec<N>, } -#[derive(Clone, PartialEq, Eq, TyEncodable, TyDecodable, HashStable, TypeFoldable, Lift)] +#[derive(Clone, PartialEq, Eq, TyEncodable, TyDecodable, HashStable, Lift)] +#[derive(TypeFoldable, TypeVisitable)] pub struct ImplSourceGeneratorData<'tcx, N> { pub generator_def_id: DefId, pub substs: SubstsRef<'tcx>, @@ -769,7 +772,8 @@ pub struct ImplSourceGeneratorData<'tcx, N> { pub nested: Vec<N>, } -#[derive(Clone, PartialEq, Eq, TyEncodable, TyDecodable, HashStable, TypeFoldable, Lift)] +#[derive(Clone, PartialEq, Eq, TyEncodable, TyDecodable, HashStable, Lift)] +#[derive(TypeFoldable, TypeVisitable)] pub struct ImplSourceClosureData<'tcx, N> { pub closure_def_id: DefId, pub substs: SubstsRef<'tcx>, @@ -778,13 +782,15 @@ pub struct ImplSourceClosureData<'tcx, N> { pub nested: Vec<N>, } -#[derive(Clone, PartialEq, Eq, TyEncodable, TyDecodable, HashStable, TypeFoldable, Lift)] +#[derive(Clone, PartialEq, Eq, TyEncodable, TyDecodable, HashStable, Lift)] +#[derive(TypeFoldable, TypeVisitable)] pub struct ImplSourceAutoImplData<N> { pub trait_def_id: DefId, pub nested: Vec<N>, } -#[derive(Clone, PartialEq, Eq, TyEncodable, TyDecodable, HashStable, TypeFoldable, Lift)] +#[derive(Clone, PartialEq, Eq, TyEncodable, TyDecodable, HashStable, Lift)] +#[derive(TypeFoldable, TypeVisitable)] pub struct ImplSourceTraitUpcastingData<'tcx, N> { /// `Foo` upcast to the obligation trait. This will be some supertrait of `Foo`. pub upcast_trait_ref: ty::PolyTraitRef<'tcx>, @@ -798,12 +804,14 @@ pub struct ImplSourceTraitUpcastingData<'tcx, N> { pub nested: Vec<N>, } -#[derive(Clone, PartialEq, Eq, TyEncodable, TyDecodable, HashStable, TypeFoldable, Lift)] +#[derive(Clone, PartialEq, Eq, TyEncodable, TyDecodable, HashStable, Lift)] +#[derive(TypeFoldable, TypeVisitable)] pub struct ImplSourceBuiltinData<N> { pub nested: Vec<N>, } -#[derive(PartialEq, Eq, Clone, TyEncodable, TyDecodable, HashStable, TypeFoldable, Lift)] +#[derive(PartialEq, Eq, Clone, TyEncodable, TyDecodable, HashStable, Lift)] +#[derive(TypeFoldable, TypeVisitable)] pub struct ImplSourceObjectData<'tcx, N> { /// `Foo` upcast to the obligation trait. This will be some supertrait of `Foo`. pub upcast_trait_ref: ty::PolyTraitRef<'tcx>, @@ -817,7 +825,8 @@ pub struct ImplSourceObjectData<'tcx, N> { pub nested: Vec<N>, } -#[derive(Clone, PartialEq, Eq, TyEncodable, TyDecodable, HashStable, TypeFoldable, Lift)] +#[derive(Clone, PartialEq, Eq, TyEncodable, TyDecodable, HashStable, Lift)] +#[derive(TypeFoldable, TypeVisitable)] pub struct ImplSourceFnPointerData<'tcx, N> { pub fn_ty: Ty<'tcx>, pub nested: Vec<N>, @@ -830,12 +839,14 @@ pub struct ImplSourceDiscriminantKindData; #[derive(Clone, Debug, PartialEq, Eq, TyEncodable, TyDecodable, HashStable)] pub struct ImplSourcePointeeData; -#[derive(Clone, PartialEq, Eq, TyEncodable, TyDecodable, HashStable, TypeFoldable, Lift)] +#[derive(Clone, PartialEq, Eq, TyEncodable, TyDecodable, HashStable, Lift)] +#[derive(TypeFoldable, TypeVisitable)] pub struct ImplSourceConstDestructData<N> { pub nested: Vec<N>, } -#[derive(Clone, PartialEq, Eq, TyEncodable, TyDecodable, HashStable, TypeFoldable, Lift)] +#[derive(Clone, PartialEq, Eq, TyEncodable, TyDecodable, HashStable, Lift)] +#[derive(TypeFoldable, TypeVisitable)] pub struct ImplSourceTraitAliasData<'tcx, N> { pub alias_def_id: DefId, pub substs: SubstsRef<'tcx>, diff --git a/compiler/rustc_middle/src/traits/query.rs b/compiler/rustc_middle/src/traits/query.rs index d43492c903c..937b166d484 100644 --- a/compiler/rustc_middle/src/traits/query.rs +++ b/compiler/rustc_middle/src/traits/query.rs @@ -24,7 +24,8 @@ pub mod type_op { use rustc_hir::def_id::DefId; use std::fmt; - #[derive(Copy, Clone, Debug, Hash, PartialEq, Eq, HashStable, TypeFoldable, Lift)] + #[derive(Copy, Clone, Debug, Hash, PartialEq, Eq, HashStable, Lift)] + #[derive(TypeFoldable, TypeVisitable)] pub struct AscribeUserType<'tcx> { pub mir_ty: Ty<'tcx>, pub def_id: DefId, @@ -37,19 +38,22 @@ pub mod type_op { } } - #[derive(Copy, Clone, Debug, Hash, PartialEq, Eq, HashStable, TypeFoldable, Lift)] + #[derive(Copy, Clone, Debug, Hash, PartialEq, Eq, HashStable, Lift)] + #[derive(TypeFoldable, TypeVisitable)] pub struct Eq<'tcx> { pub a: Ty<'tcx>, pub b: Ty<'tcx>, } - #[derive(Copy, Clone, Debug, Hash, PartialEq, Eq, HashStable, TypeFoldable, Lift)] + #[derive(Copy, Clone, Debug, Hash, PartialEq, Eq, HashStable, Lift)] + #[derive(TypeFoldable, TypeVisitable)] pub struct Subtype<'tcx> { pub sub: Ty<'tcx>, pub sup: Ty<'tcx>, } - #[derive(Copy, Clone, Debug, Hash, PartialEq, Eq, HashStable, TypeFoldable, Lift)] + #[derive(Copy, Clone, Debug, Hash, PartialEq, Eq, HashStable, Lift)] + #[derive(TypeFoldable, TypeVisitable)] pub struct ProvePredicate<'tcx> { pub predicate: Predicate<'tcx>, } @@ -60,7 +64,8 @@ pub mod type_op { } } - #[derive(Copy, Clone, Debug, Hash, PartialEq, Eq, HashStable, TypeFoldable, Lift)] + #[derive(Copy, Clone, Debug, Hash, PartialEq, Eq, HashStable, Lift)] + #[derive(TypeFoldable, TypeVisitable)] pub struct Normalize<T> { pub value: T, } @@ -107,7 +112,7 @@ impl<'tcx> From<TypeError<'tcx>> for NoSolution { } } -#[derive(Clone, Debug, Default, HashStable, TypeFoldable, Lift)] +#[derive(Clone, Debug, Default, HashStable, TypeFoldable, TypeVisitable, Lift)] pub struct DropckOutlivesResult<'tcx> { pub kinds: Vec<GenericArg<'tcx>>, pub overflows: Vec<Ty<'tcx>>, @@ -208,7 +213,7 @@ pub struct MethodAutoderefBadTy<'tcx> { } /// Result from the `normalize_projection_ty` query. -#[derive(Clone, Debug, HashStable, TypeFoldable, Lift)] +#[derive(Clone, Debug, HashStable, TypeFoldable, TypeVisitable, Lift)] pub struct NormalizationResult<'tcx> { /// Result of normalization. pub normalized_ty: Ty<'tcx>, @@ -221,7 +226,7 @@ pub struct NormalizationResult<'tcx> { /// case they are called implied bounds). They are fed to the /// `OutlivesEnv` which in turn is supplied to the region checker and /// other parts of the inference system. -#[derive(Clone, Debug, TypeFoldable, Lift)] +#[derive(Clone, Debug, TypeFoldable, TypeVisitable, Lift)] pub enum OutlivesBound<'tcx> { RegionSubRegion(ty::Region<'tcx>, ty::Region<'tcx>), RegionSubParam(ty::Region<'tcx>, ty::ParamTy), diff --git a/compiler/rustc_middle/src/traits/select.rs b/compiler/rustc_middle/src/traits/select.rs index ffa70cddbd5..34703b62820 100644 --- a/compiler/rustc_middle/src/traits/select.rs +++ b/compiler/rustc_middle/src/traits/select.rs @@ -103,7 +103,7 @@ pub type EvaluationCache<'tcx> = Cache< /// required for associated types to work in default impls, as the bounds /// are visible both as projection bounds and as where-clauses from the /// parameter environment. -#[derive(PartialEq, Eq, Debug, Clone, TypeFoldable)] +#[derive(PartialEq, Eq, Debug, Clone, TypeFoldable, TypeVisitable)] pub enum SelectionCandidate<'tcx> { BuiltinCandidate { /// `false` if there are no *further* obligations. @@ -283,7 +283,7 @@ impl From<ErrorGuaranteed> for OverflowError { } } -TrivialTypeFoldableAndLiftImpls! { +TrivialTypeTraversalAndLiftImpls! { OverflowError, } diff --git a/compiler/rustc_middle/src/traits/specialization_graph.rs b/compiler/rustc_middle/src/traits/specialization_graph.rs index ce13825b016..3c1d0061ae1 100644 --- a/compiler/rustc_middle/src/traits/specialization_graph.rs +++ b/compiler/rustc_middle/src/traits/specialization_graph.rs @@ -1,5 +1,5 @@ use crate::ty::fast_reject::SimplifiedType; -use crate::ty::fold::TypeFoldable; +use crate::ty::visit::TypeVisitable; use crate::ty::{self, TyCtxt}; use rustc_data_structures::fx::FxIndexMap; use rustc_errors::ErrorGuaranteed; diff --git a/compiler/rustc_middle/src/traits/structural_impls.rs b/compiler/rustc_middle/src/traits/structural_impls.rs index ea706053231..8f1a1564fc8 100644 --- a/compiler/rustc_middle/src/traits/structural_impls.rs +++ b/compiler/rustc_middle/src/traits/structural_impls.rs @@ -129,7 +129,7 @@ impl<N: fmt::Debug> fmt::Debug for traits::ImplSourceConstDestructData<N> { /////////////////////////////////////////////////////////////////////////// // Lift implementations -TrivialTypeFoldableAndLiftImpls! { +TrivialTypeTraversalAndLiftImpls! { super::IfExpressionCause, super::ImplSourceDiscriminantKindData, super::ImplSourcePointeeData, diff --git a/compiler/rustc_middle/src/ty/adjustment.rs b/compiler/rustc_middle/src/ty/adjustment.rs index d9332f6896a..d36cf2fe3f8 100644 --- a/compiler/rustc_middle/src/ty/adjustment.rs +++ b/compiler/rustc_middle/src/ty/adjustment.rs @@ -77,7 +77,7 @@ pub enum PointerCast { /// At some point, of course, `Box` should move out of the compiler, in which /// case this is analogous to transforming a struct. E.g., `Box<[i32; 4]>` -> /// `Box<[i32]>` is an `Adjust::Unsize` with the target `Box<[i32]>`. -#[derive(Clone, TyEncodable, TyDecodable, HashStable, TypeFoldable)] +#[derive(Clone, TyEncodable, TyDecodable, HashStable, TypeFoldable, TypeVisitable)] pub struct Adjustment<'tcx> { pub kind: Adjust<'tcx>, pub target: Ty<'tcx>, @@ -89,7 +89,7 @@ impl<'tcx> Adjustment<'tcx> { } } -#[derive(Clone, Debug, TyEncodable, TyDecodable, HashStable, TypeFoldable)] +#[derive(Clone, Debug, TyEncodable, TyDecodable, HashStable, TypeFoldable, TypeVisitable)] pub enum Adjust<'tcx> { /// Go from ! to any type. NeverToAny, @@ -107,7 +107,8 @@ pub enum Adjust<'tcx> { /// call, with the signature `&'a T -> &'a U` or `&'a mut T -> &'a mut U`. /// The target type is `U` in both cases, with the region and mutability /// being those shared by both the receiver and the returned reference. -#[derive(Copy, Clone, PartialEq, Debug, TyEncodable, TyDecodable, HashStable, TypeFoldable)] +#[derive(Copy, Clone, PartialEq, Debug, TyEncodable, TyDecodable, HashStable)] +#[derive(TypeFoldable, TypeVisitable)] pub struct OverloadedDeref<'tcx> { pub region: ty::Region<'tcx>, pub mutbl: hir::Mutability, @@ -165,7 +166,8 @@ impl From<AutoBorrowMutability> for hir::Mutability { } } -#[derive(Copy, Clone, PartialEq, Debug, TyEncodable, TyDecodable, HashStable, TypeFoldable)] +#[derive(Copy, Clone, PartialEq, Debug, TyEncodable, TyDecodable, HashStable)] +#[derive(TypeFoldable, TypeVisitable)] pub enum AutoBorrow<'tcx> { /// Converts from T to &T. Ref(ty::Region<'tcx>, AutoBorrowMutability), diff --git a/compiler/rustc_middle/src/ty/binding.rs b/compiler/rustc_middle/src/ty/binding.rs index 7ab192daf4b..3d65429f2e5 100644 --- a/compiler/rustc_middle/src/ty/binding.rs +++ b/compiler/rustc_middle/src/ty/binding.rs @@ -8,7 +8,7 @@ pub enum BindingMode { BindByValue(Mutability), } -TrivialTypeFoldableAndLiftImpls! { BindingMode, } +TrivialTypeTraversalAndLiftImpls! { BindingMode, } impl BindingMode { pub fn convert(ba: BindingAnnotation) -> BindingMode { diff --git a/compiler/rustc_middle/src/ty/cast.rs b/compiler/rustc_middle/src/ty/cast.rs index 20a6af5f6c1..c4b743dd467 100644 --- a/compiler/rustc_middle/src/ty/cast.rs +++ b/compiler/rustc_middle/src/ty/cast.rs @@ -15,6 +15,12 @@ pub enum IntTy { Char, } +impl IntTy { + pub fn is_signed(self) -> bool { + matches!(self, Self::I) + } +} + // Valid types for the result of a non-coercion cast #[derive(Copy, Clone, Debug, PartialEq, Eq)] pub enum CastTy<'tcx> { diff --git a/compiler/rustc_middle/src/ty/closure.rs b/compiler/rustc_middle/src/ty/closure.rs index c88cac30a19..f5ce43f3afb 100644 --- a/compiler/rustc_middle/src/ty/closure.rs +++ b/compiler/rustc_middle/src/ty/closure.rs @@ -18,18 +18,8 @@ use self::BorrowKind::*; // This represents accessing self in the closure structure pub const CAPTURE_STRUCT_LOCAL: mir::Local = mir::Local::from_u32(1); -#[derive( - Clone, - Copy, - Debug, - PartialEq, - Eq, - Hash, - TyEncodable, - TyDecodable, - TypeFoldable, - HashStable -)] +#[derive(Clone, Copy, Debug, PartialEq, Eq, Hash, TyEncodable, TyDecodable, HashStable)] +#[derive(TypeFoldable, TypeVisitable)] pub struct UpvarPath { pub hir_id: hir::HirId, } @@ -37,7 +27,8 @@ pub struct UpvarPath { /// Upvars do not get their own `NodeId`. Instead, we use the pair of /// the original var ID (that is, the root variable that is referenced /// by the upvar) and the ID of the closure expression. -#[derive(Clone, Copy, PartialEq, Eq, Hash, TyEncodable, TyDecodable, TypeFoldable, HashStable)] +#[derive(Clone, Copy, PartialEq, Eq, Hash, TyEncodable, TyDecodable, HashStable)] +#[derive(TypeFoldable, TypeVisitable)] pub struct UpvarId { pub var_path: UpvarPath, pub closure_expr_id: LocalDefId, @@ -51,7 +42,8 @@ impl UpvarId { /// Information describing the capture of an upvar. This is computed /// during `typeck`, specifically by `regionck`. -#[derive(PartialEq, Clone, Debug, Copy, TyEncodable, TyDecodable, TypeFoldable, HashStable)] +#[derive(PartialEq, Clone, Debug, Copy, TyEncodable, TyDecodable, HashStable)] +#[derive(TypeFoldable, TypeVisitable)] pub enum UpvarCapture { /// Upvar is captured by value. This is always true when the /// closure is labeled `move`, but can also be true in other cases @@ -139,7 +131,8 @@ impl<'tcx> ClosureKind { } /// A composite describing a `Place` that is captured by a closure. -#[derive(PartialEq, Clone, Debug, TyEncodable, TyDecodable, TypeFoldable, HashStable)] +#[derive(PartialEq, Clone, Debug, TyEncodable, TyDecodable, HashStable)] +#[derive(TypeFoldable, TypeVisitable)] pub struct CapturedPlace<'tcx> { /// The `Place` that is captured. pub place: HirPlace<'tcx>, @@ -284,7 +277,8 @@ pub fn is_ancestor_or_same_capture( /// Part of `MinCaptureInformationMap`; describes the capture kind (&, &mut, move) /// for a particular capture as well as identifying the part of the source code /// that triggered this capture to occur. -#[derive(PartialEq, Clone, Debug, Copy, TyEncodable, TyDecodable, TypeFoldable, HashStable)] +#[derive(PartialEq, Clone, Debug, Copy, TyEncodable, TyDecodable, HashStable)] +#[derive(TypeFoldable, TypeVisitable)] pub struct CaptureInfo { /// Expr Id pointing to use that resulted in selecting the current capture kind /// @@ -362,7 +356,8 @@ pub fn place_to_string_for_capture<'tcx>(tcx: TyCtxt<'tcx>, place: &HirPlace<'tc curr_string } -#[derive(Clone, PartialEq, Debug, TyEncodable, TyDecodable, TypeFoldable, Copy, HashStable)] +#[derive(Clone, PartialEq, Debug, TyEncodable, TyDecodable, Copy, HashStable)] +#[derive(TypeFoldable, TypeVisitable)] pub enum BorrowKind { /// Data must be immutable and is aliasable. ImmBorrow, diff --git a/compiler/rustc_middle/src/ty/consts.rs b/compiler/rustc_middle/src/ty/consts.rs index bc52259b151..a4e7a12bba3 100644 --- a/compiler/rustc_middle/src/ty/consts.rs +++ b/compiler/rustc_middle/src/ty/consts.rs @@ -2,7 +2,7 @@ use crate::mir::interpret::LitToConstInput; use crate::mir::ConstantKind; use crate::ty::{ self, InlineConstSubsts, InlineConstSubstsParts, InternalSubsts, ParamEnv, ParamEnvAnd, Ty, - TyCtxt, TypeFoldable, + TyCtxt, TypeVisitable, }; use rustc_data_structures::intern::Interned; use rustc_errors::ErrorGuaranteed; diff --git a/compiler/rustc_middle/src/ty/consts/int.rs b/compiler/rustc_middle/src/ty/consts/int.rs index 51e51a63fd0..c7c2692281e 100644 --- a/compiler/rustc_middle/src/ty/consts/int.rs +++ b/compiler/rustc_middle/src/ty/consts/int.rs @@ -452,6 +452,10 @@ impl fmt::Debug for ScalarInt { impl fmt::LowerHex for ScalarInt { fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { self.check_data(); + if f.alternate() { + // Like regular ints, alternate flag adds leading `0x`. + write!(f, "0x")?; + } // Format as hex number wide enough to fit any value of the given `size`. // So data=20, size=1 will be "0x14", but with size=4 it'll be "0x00000014". // Using a block `{self.data}` here to force a copy instead of using `self.data` diff --git a/compiler/rustc_middle/src/ty/consts/kind.rs b/compiler/rustc_middle/src/ty/consts/kind.rs index 10d03065c79..cb0137d2e5e 100644 --- a/compiler/rustc_middle/src/ty/consts/kind.rs +++ b/compiler/rustc_middle/src/ty/consts/kind.rs @@ -4,7 +4,7 @@ use crate::mir::interpret::{AllocId, ConstValue, Scalar}; use crate::mir::Promoted; use crate::ty::subst::{InternalSubsts, SubstsRef}; use crate::ty::ParamEnv; -use crate::ty::{self, TyCtxt, TypeFoldable}; +use crate::ty::{self, TyCtxt, TypeVisitable}; use rustc_errors::ErrorGuaranteed; use rustc_hir::def_id::DefId; use rustc_macros::HashStable; diff --git a/compiler/rustc_middle/src/ty/context.rs b/compiler/rustc_middle/src/ty/context.rs index c3df9a66fe7..af071b4e939 100644 --- a/compiler/rustc_middle/src/ty/context.rs +++ b/compiler/rustc_middle/src/ty/context.rs @@ -4,7 +4,7 @@ use crate::arena::Arena; use crate::dep_graph::{DepGraph, DepKind, DepKindStruct}; use crate::hir::place::Place as HirPlace; use crate::infer::canonical::{Canonical, CanonicalVarInfo, CanonicalVarInfos}; -use crate::lint::{struct_lint_level, LintDiagnosticBuilder, LintLevelSource}; +use crate::lint::{struct_lint_level, LintLevelSource}; use crate::middle::codegen_fn_attrs::CodegenFnAttrs; use crate::middle::resolve_lifetime; use crate::middle::stability; @@ -34,7 +34,7 @@ use rustc_data_structures::stable_hasher::{HashStable, StableHasher}; use rustc_data_structures::steal::Steal; use rustc_data_structures::sync::{self, Lock, Lrc, WorkerLocal}; use rustc_data_structures::vec_map::VecMap; -use rustc_errors::{ErrorGuaranteed, MultiSpan}; +use rustc_errors::{DecorateLint, ErrorGuaranteed, LintDiagnosticBuilder, MultiSpan}; use rustc_hir as hir; use rustc_hir::def::{DefKind, Res}; use rustc_hir::def_id::{CrateNum, DefId, DefIdMap, LocalDefId, LOCAL_CRATE}; @@ -390,7 +390,7 @@ impl<'a, V> LocalTableInContextMut<'a, V> { /// Here, we would store the type `T`, the span of the value `x`, the "scope-span" for /// the scope that contains `x`, the expr `T` evaluated from, and the span of `foo.await`. #[derive(TyEncodable, TyDecodable, Clone, Debug, Eq, Hash, PartialEq, HashStable)] -#[derive(TypeFoldable)] +#[derive(TypeFoldable, TypeVisitable)] pub struct GeneratorInteriorTypeCause<'tcx> { /// Type of the captured binding. pub ty: Ty<'tcx>, @@ -871,7 +871,7 @@ rustc_index::newtype_index! { pub type CanonicalUserTypeAnnotations<'tcx> = IndexVec<UserTypeAnnotationIndex, CanonicalUserTypeAnnotation<'tcx>>; -#[derive(Clone, Debug, TyEncodable, TyDecodable, HashStable, TypeFoldable, Lift)] +#[derive(Clone, Debug, TyEncodable, TyDecodable, HashStable, TypeFoldable, TypeVisitable, Lift)] pub struct CanonicalUserTypeAnnotation<'tcx> { pub user_ty: CanonicalUserType<'tcx>, pub span: Span, @@ -931,7 +931,7 @@ impl<'tcx> CanonicalUserType<'tcx> { /// from constants that are named via paths, like `Foo::<A>::new` and /// so forth. #[derive(Copy, Clone, Debug, PartialEq, TyEncodable, TyDecodable)] -#[derive(HashStable, TypeFoldable, Lift)] +#[derive(HashStable, TypeFoldable, TypeVisitable, Lift)] pub enum UserType<'tcx> { Ty(Ty<'tcx>), @@ -2787,6 +2787,18 @@ impl<'tcx> TyCtxt<'tcx> { } } + /// Emit a lint at `span` from a lint struct (some type that implements `DecorateLint`, + /// typically generated by `#[derive(LintDiagnostic)]`). + pub fn emit_spanned_lint( + self, + lint: &'static Lint, + hir_id: HirId, + span: impl Into<MultiSpan>, + decorator: impl for<'a> DecorateLint<'a, ()>, + ) { + self.struct_span_lint_hir(lint, hir_id, span, |diag| decorator.decorate_lint(diag)) + } + pub fn struct_span_lint_hir( self, lint: &'static Lint, @@ -2798,6 +2810,17 @@ impl<'tcx> TyCtxt<'tcx> { struct_lint_level(self.sess, lint, level, src, Some(span.into()), decorate); } + /// Emit a lint from a lint struct (some type that implements `DecorateLint`, typically + /// generated by `#[derive(LintDiagnostic)]`). + pub fn emit_lint( + self, + lint: &'static Lint, + id: HirId, + decorator: impl for<'a> DecorateLint<'a, ()>, + ) { + self.struct_lint_node(lint, id, |diag| decorator.decorate_lint(diag)) + } + pub fn struct_lint_node( self, lint: &'static Lint, diff --git a/compiler/rustc_middle/src/ty/diagnostics.rs b/compiler/rustc_middle/src/ty/diagnostics.rs index a84b3c9373b..25bc6dc6167 100644 --- a/compiler/rustc_middle/src/ty/diagnostics.rs +++ b/compiler/rustc_middle/src/ty/diagnostics.rs @@ -3,8 +3,8 @@ use std::ops::ControlFlow; use crate::ty::{ - fold::TypeFoldable, Const, ConstKind, DefIdTree, ExistentialPredicate, InferTy, - PolyTraitPredicate, Ty, TyCtxt, TypeSuperFoldable, TypeVisitor, + visit::TypeVisitable, Const, ConstKind, DefIdTree, ExistentialPredicate, InferTy, + PolyTraitPredicate, Ty, TyCtxt, TypeSuperVisitable, TypeVisitor, }; use rustc_data_structures::fx::FxHashMap; @@ -87,7 +87,7 @@ pub trait IsSuggestable<'tcx> { impl<'tcx, T> IsSuggestable<'tcx> for T where - T: TypeFoldable<'tcx>, + T: TypeVisitable<'tcx>, { fn is_suggestable(self, tcx: TyCtxt<'tcx>) -> bool { self.visit_with(&mut IsSuggestableVisitor { tcx }).is_continue() diff --git a/compiler/rustc_middle/src/ty/erase_regions.rs b/compiler/rustc_middle/src/ty/erase_regions.rs index 6d7e60ecc31..f39fa363a16 100644 --- a/compiler/rustc_middle/src/ty/erase_regions.rs +++ b/compiler/rustc_middle/src/ty/erase_regions.rs @@ -1,5 +1,6 @@ use crate::mir; use crate::ty::fold::{TypeFoldable, TypeFolder, TypeSuperFoldable}; +use crate::ty::visit::TypeVisitable; use crate::ty::{self, Ty, TyCtxt, TypeFlags}; pub(super) fn provide(providers: &mut ty::query::Providers) { diff --git a/compiler/rustc_middle/src/ty/error.rs b/compiler/rustc_middle/src/ty/error.rs index 812dd2adc2e..9796b152911 100644 --- a/compiler/rustc_middle/src/ty/error.rs +++ b/compiler/rustc_middle/src/ty/error.rs @@ -13,7 +13,7 @@ use rustc_target::spec::abi; use std::borrow::Cow; use std::fmt; -#[derive(Clone, Copy, Debug, PartialEq, Eq, TypeFoldable)] +#[derive(Clone, Copy, Debug, PartialEq, Eq, TypeFoldable, TypeVisitable)] pub struct ExpectedFound<T> { pub expected: T, pub found: T, @@ -30,7 +30,7 @@ impl<T> ExpectedFound<T> { } // Data structures used in type unification -#[derive(Clone, Debug, TypeFoldable)] +#[derive(Clone, Debug, TypeFoldable, TypeVisitable)] pub enum TypeError<'tcx> { Mismatch, ConstnessMismatch(ExpectedFound<ty::BoundConstness>), diff --git a/compiler/rustc_middle/src/ty/fast_reject.rs b/compiler/rustc_middle/src/ty/fast_reject.rs index a8145e6820c..8d019a3bad8 100644 --- a/compiler/rustc_middle/src/ty/fast_reject.rs +++ b/compiler/rustc_middle/src/ty/fast_reject.rs @@ -1,6 +1,6 @@ use crate::mir::Mutability; use crate::ty::subst::GenericArgKind; -use crate::ty::{self, Ty, TyCtxt, TypeFoldable}; +use crate::ty::{self, Ty, TyCtxt, TypeVisitable}; use rustc_hir::def_id::DefId; use std::fmt::Debug; use std::hash::Hash; diff --git a/compiler/rustc_middle/src/ty/fold.rs b/compiler/rustc_middle/src/ty/fold.rs index a6310ae5e66..f8893ae29f5 100644 --- a/compiler/rustc_middle/src/ty/fold.rs +++ b/compiler/rustc_middle/src/ty/fold.rs @@ -1,76 +1,60 @@ -//! A generalized traversal mechanism for complex data structures that contain -//! type information. +//! A folding traversal mechanism for complex data structures that contain type +//! information. //! -//! There are two types of traversal. -//! - Folding. This is a modifying traversal. It consumes the data structure, -//! producing a (possibly) modified version of it. Both fallible and -//! infallible versions are available. The name is potentially -//! confusing, because this traversal is more like `Iterator::map` than -//! `Iterator::fold`. -//! - Visiting. This is a read-only traversal of the data structure. +//! This is a modifying traversal. It consumes the data structure, producing a +//! (possibly) modified version of it. Both fallible and infallible versions are +//! available. The name is potentially confusing, because this traversal is more +//! like `Iterator::map` than `Iterator::fold`. //! -//! These traversals have limited flexibility. Only a small number of "types of +//! This traversal has limited flexibility. Only a small number of "types of //! interest" within the complex data structures can receive custom -//! modification (when folding) or custom visitation (when visiting). These are -//! the ones containing the most important type-related information, such as -//! `Ty`, `Predicate`, `Region`, and `Const`. +//! modification. These are the ones containing the most important type-related +//! information, such as `Ty`, `Predicate`, `Region`, and `Const`. //! -//! There are three traits involved in each traversal type. -//! - `TypeFoldable`. This is implemented once for many types. This includes -//! both: +//! There are three groups of traits involved in each traversal. +//! - `TypeFoldable`. This is implemented once for many types, including: //! - Types of interest, for which the the methods delegate to the -//! folder/visitor. +//! folder. //! - All other types, including generic containers like `Vec` and `Option`. -//! It defines a "skeleton" of how they should be traversed, for both -//! folding and visiting. +//! It defines a "skeleton" of how they should be folded. //! - `TypeSuperFoldable`. This is implemented only for each type of interest, -//! and defines the traversal "skeleton" for these types. -//! - `TypeFolder`/`FallibleTypeFolder` (for infallible/fallible folding -//! traversals) or `TypeVisitor` (for visiting traversals). One of these is -//! implemented for each folder/visitor. This defines how types of interest -//! are folded/visited. +//! and defines the folding "skeleton" for these types. +//! - `TypeFolder`/`FallibleTypeFolder. One of these is implemented for each +//! folder. This defines how types of interest are folded. //! -//! This means each traversal is a mixture of (a) generic traversal operations, -//! and (b) custom fold/visit operations that are specific to the -//! folder/visitor. +//! This means each fold is a mixture of (a) generic folding operations, and (b) +//! custom fold operations that are specific to the folder. //! - The `TypeFoldable` impls handle most of the traversal, and call into -//! `TypeFolder`/`FallibleTypeFolder`/`TypeVisitor` when they encounter a -//! type of interest. -//! - A `TypeFolder`/`FallibleTypeFolder`/`TypeVisitor` may call into another -//! `TypeFoldable` impl, because some of the types of interest are recursive -//! and can contain other types of interest. -//! - A `TypeFolder`/`FallibleTypeFolder`/`TypeVisitor` may also call into -//! a `TypeSuperFoldable` impl, because each folder/visitor might provide -//! custom handling only for some types of interest, or only for some -//! variants of each type of interest, and then use default traversal for the -//! remaining cases. +//! `TypeFolder`/`FallibleTypeFolder` when they encounter a type of interest. +//! - A `TypeFolder`/`FallibleTypeFolder` may call into another `TypeFoldable` +//! impl, because some of the types of interest are recursive and can contain +//! other types of interest. +//! - A `TypeFolder`/`FallibleTypeFolder` may also call into a `TypeSuperFoldable` +//! impl, because each folder might provide custom handling only for some types +//! of interest, or only for some variants of each type of interest, and then +//! use default traversal for the remaining cases. //! //! For example, if you have `struct S(Ty, U)` where `S: TypeFoldable` and `U: -//! TypeFoldable`, and an instance `s = S(ty, u)`, it would be visited like so: +//! TypeFoldable`, and an instance `s = S(ty, u)`, it would be folded like so: //! ```text -//! s.visit_with(visitor) calls -//! - ty.visit_with(visitor) calls -//! - visitor.visit_ty(ty) may call -//! - ty.super_visit_with(visitor) -//! - u.visit_with(visitor) +//! s.fold_with(folder) calls +//! - ty.fold_with(folder) calls +//! - folder.fold_ty(ty) may call +//! - ty.super_fold_with(folder) +//! - u.fold_with(folder) //! ``` use crate::mir; -use crate::ty::{self, flags::FlagComputation, Binder, Ty, TyCtxt, TypeFlags}; -use rustc_errors::ErrorGuaranteed; +use crate::ty::{self, Binder, Ty, TyCtxt, TypeVisitable}; use rustc_hir::def_id::DefId; -use rustc_data_structures::fx::FxHashSet; -use rustc_data_structures::sso::SsoHashSet; use std::collections::BTreeMap; -use std::fmt; -use std::ops::ControlFlow; -/// This trait is implemented for every type that can be folded/visited, +/// This trait is implemented for every type that can be folded, /// providing the skeleton of the traversal. /// /// To implement this conveniently, use the derive macro located in /// `rustc_macros`. -pub trait TypeFoldable<'tcx>: fmt::Debug + Clone { +pub trait TypeFoldable<'tcx>: TypeVisitable<'tcx> { /// The entry point for folding. To fold a value `t` with a folder `f` /// call: `t.try_fold_with(f)`. /// @@ -89,115 +73,6 @@ pub trait TypeFoldable<'tcx>: fmt::Debug + Clone { fn fold_with<F: TypeFolder<'tcx>>(self, folder: &mut F) -> Self { self.try_fold_with(folder).into_ok() } - - /// The entry point for visiting. To visit a value `t` with a visitor `v` - /// call: `t.visit_with(v)`. - /// - /// For most types, this just traverses the value, calling `visit_with` on - /// each field/element. - /// - /// For types of interest (such as `Ty`), the implementation of this method - /// that calls a visitor method specifically for that type (such as - /// `V::visit_ty`). This is where control transfers from `TypeFoldable` to - /// `TypeVisitor`. - fn visit_with<V: TypeVisitor<'tcx>>(&self, visitor: &mut V) -> ControlFlow<V::BreakTy>; - - /// Returns `true` if `self` has any late-bound regions that are either - /// bound by `binder` or bound by some binder outside of `binder`. - /// If `binder` is `ty::INNERMOST`, this indicates whether - /// there are any late-bound regions that appear free. - fn has_vars_bound_at_or_above(&self, binder: ty::DebruijnIndex) -> bool { - self.visit_with(&mut HasEscapingVarsVisitor { outer_index: binder }).is_break() - } - - /// Returns `true` if this `self` has any regions that escape `binder` (and - /// hence are not bound by it). - fn has_vars_bound_above(&self, binder: ty::DebruijnIndex) -> bool { - self.has_vars_bound_at_or_above(binder.shifted_in(1)) - } - - fn has_escaping_bound_vars(&self) -> bool { - self.has_vars_bound_at_or_above(ty::INNERMOST) - } - - #[instrument(level = "trace")] - fn has_type_flags(&self, flags: TypeFlags) -> bool { - self.visit_with(&mut HasTypeFlagsVisitor { flags }).break_value() == Some(FoundFlags) - } - fn has_projections(&self) -> bool { - self.has_type_flags(TypeFlags::HAS_PROJECTION) - } - fn has_opaque_types(&self) -> bool { - self.has_type_flags(TypeFlags::HAS_TY_OPAQUE) - } - fn references_error(&self) -> bool { - self.has_type_flags(TypeFlags::HAS_ERROR) - } - fn error_reported(&self) -> Option<ErrorGuaranteed> { - if self.references_error() { - Some(ErrorGuaranteed::unchecked_claim_error_was_emitted()) - } else { - None - } - } - fn has_param_types_or_consts(&self) -> bool { - self.has_type_flags(TypeFlags::HAS_TY_PARAM | TypeFlags::HAS_CT_PARAM) - } - fn has_infer_regions(&self) -> bool { - self.has_type_flags(TypeFlags::HAS_RE_INFER) - } - fn has_infer_types(&self) -> bool { - self.has_type_flags(TypeFlags::HAS_TY_INFER) - } - fn has_infer_types_or_consts(&self) -> bool { - self.has_type_flags(TypeFlags::HAS_TY_INFER | TypeFlags::HAS_CT_INFER) - } - fn needs_infer(&self) -> bool { - self.has_type_flags(TypeFlags::NEEDS_INFER) - } - fn has_placeholders(&self) -> bool { - self.has_type_flags( - TypeFlags::HAS_RE_PLACEHOLDER - | TypeFlags::HAS_TY_PLACEHOLDER - | TypeFlags::HAS_CT_PLACEHOLDER, - ) - } - fn needs_subst(&self) -> bool { - self.has_type_flags(TypeFlags::NEEDS_SUBST) - } - /// "Free" regions in this context means that it has any region - /// that is not (a) erased or (b) late-bound. - fn has_free_regions(&self) -> bool { - self.has_type_flags(TypeFlags::HAS_FREE_REGIONS) - } - - fn has_erased_regions(&self) -> bool { - self.has_type_flags(TypeFlags::HAS_RE_ERASED) - } - - /// True if there are any un-erased free regions. - fn has_erasable_regions(&self) -> bool { - self.has_type_flags(TypeFlags::HAS_FREE_REGIONS) - } - - /// Indicates whether this value references only 'global' - /// generic parameters that are the same regardless of what fn we are - /// in. This is used for caching. - fn is_global(&self) -> bool { - !self.has_type_flags(TypeFlags::HAS_FREE_LOCAL_NAMES) - } - - /// True if there are any late-bound regions - fn has_late_bound_regions(&self) -> bool { - self.has_type_flags(TypeFlags::HAS_RE_LATE_BOUND) - } - - /// Indicates whether this value still has parameters/placeholders/inference variables - /// which could be replaced later, in a way that would change the results of `impl` - /// specialization. - fn still_further_specializable(&self) -> bool { - self.has_type_flags(TypeFlags::STILL_FURTHER_SPECIALIZABLE) - } } // This trait is implemented for types of interest. @@ -219,14 +94,6 @@ pub trait TypeSuperFoldable<'tcx>: TypeFoldable<'tcx> { fn super_fold_with<F: TypeFolder<'tcx>>(self, folder: &mut F) -> Self { self.try_super_fold_with(folder).into_ok() } - - /// Provides a default visit for a type of interest. This should only be - /// called within `TypeVisitor` methods, when a non-custom traversal is - /// desired for the value of the type of interest passed to that method. - /// For example, in `MyVisitor::visit_ty(ty)`, it is valid to call - /// `ty.super_visit_with(self)`, but any other visiting should be done - /// with `xyz.visit_with(self)`. - fn super_visit_with<V: TypeVisitor<'tcx>>(&self, visitor: &mut V) -> ControlFlow<V::BreakTy>; } /// This trait is implemented for every infallible folding traversal. There is @@ -376,44 +243,6 @@ where } } -/// This trait is implemented for every visiting traversal. There is a visit -/// method defined for every type of interest. Each such method has a default -/// that recurses into the type's fields in a non-custom fashion. -pub trait TypeVisitor<'tcx>: Sized { - type BreakTy = !; - - fn visit_binder<T: TypeFoldable<'tcx>>( - &mut self, - t: &Binder<'tcx, T>, - ) -> ControlFlow<Self::BreakTy> { - t.super_visit_with(self) - } - - fn visit_ty(&mut self, t: Ty<'tcx>) -> ControlFlow<Self::BreakTy> { - t.super_visit_with(self) - } - - fn visit_region(&mut self, r: ty::Region<'tcx>) -> ControlFlow<Self::BreakTy> { - r.super_visit_with(self) - } - - fn visit_const(&mut self, c: ty::Const<'tcx>) -> ControlFlow<Self::BreakTy> { - c.super_visit_with(self) - } - - fn visit_unevaluated(&mut self, uv: ty::Unevaluated<'tcx>) -> ControlFlow<Self::BreakTy> { - uv.super_visit_with(self) - } - - fn visit_predicate(&mut self, p: ty::Predicate<'tcx>) -> ControlFlow<Self::BreakTy> { - p.super_visit_with(self) - } - - fn visit_mir_const(&mut self, c: mir::ConstantKind<'tcx>) -> ControlFlow<Self::BreakTy> { - c.super_visit_with(self) - } -} - /////////////////////////////////////////////////////////////////////////// // Some sample folders @@ -472,99 +301,6 @@ impl<'tcx> TyCtxt<'tcx> { { value.fold_with(&mut RegionFolder::new(self, &mut f)) } - - /// Invoke `callback` on every region appearing free in `value`. - pub fn for_each_free_region( - self, - value: &impl TypeFoldable<'tcx>, - mut callback: impl FnMut(ty::Region<'tcx>), - ) { - self.any_free_region_meets(value, |r| { - callback(r); - false - }); - } - - /// Returns `true` if `callback` returns true for every region appearing free in `value`. - pub fn all_free_regions_meet( - self, - value: &impl TypeFoldable<'tcx>, - mut callback: impl FnMut(ty::Region<'tcx>) -> bool, - ) -> bool { - !self.any_free_region_meets(value, |r| !callback(r)) - } - - /// Returns `true` if `callback` returns true for some region appearing free in `value`. - pub fn any_free_region_meets( - self, - value: &impl TypeFoldable<'tcx>, - callback: impl FnMut(ty::Region<'tcx>) -> bool, - ) -> bool { - struct RegionVisitor<F> { - /// The index of a binder *just outside* the things we have - /// traversed. If we encounter a bound region bound by this - /// binder or one outer to it, it appears free. Example: - /// - /// ```ignore (illustrative) - /// for<'a> fn(for<'b> fn(), T) - /// // ^ ^ ^ ^ - /// // | | | | here, would be shifted in 1 - /// // | | | here, would be shifted in 2 - /// // | | here, would be `INNERMOST` shifted in by 1 - /// // | here, initially, binder would be `INNERMOST` - /// ``` - /// - /// You see that, initially, *any* bound value is free, - /// because we've not traversed any binders. As we pass - /// through a binder, we shift the `outer_index` by 1 to - /// account for the new binder that encloses us. - outer_index: ty::DebruijnIndex, - callback: F, - } - - impl<'tcx, F> TypeVisitor<'tcx> for RegionVisitor<F> - where - F: FnMut(ty::Region<'tcx>) -> bool, - { - type BreakTy = (); - - fn visit_binder<T: TypeFoldable<'tcx>>( - &mut self, - t: &Binder<'tcx, T>, - ) -> ControlFlow<Self::BreakTy> { - self.outer_index.shift_in(1); - let result = t.super_visit_with(self); - self.outer_index.shift_out(1); - result - } - - fn visit_region(&mut self, r: ty::Region<'tcx>) -> ControlFlow<Self::BreakTy> { - match *r { - ty::ReLateBound(debruijn, _) if debruijn < self.outer_index => { - ControlFlow::CONTINUE - } - _ => { - if (self.callback)(r) { - ControlFlow::BREAK - } else { - ControlFlow::CONTINUE - } - } - } - } - - fn visit_ty(&mut self, ty: Ty<'tcx>) -> ControlFlow<Self::BreakTy> { - // We're only interested in types involving regions - if ty.flags().intersects(TypeFlags::HAS_FREE_REGIONS) { - ty.super_visit_with(self) - } else { - ControlFlow::CONTINUE - } - } - } - - value.visit_with(&mut RegionVisitor { outer_index: ty::INNERMOST, callback }).is_break() - } } /// Folds over the substructure of a type, visiting its component @@ -861,45 +597,6 @@ impl<'tcx> TyCtxt<'tcx> { ) } - /// Returns a set of all late-bound regions that are constrained - /// by `value`, meaning that if we instantiate those LBR with - /// variables and equate `value` with something else, those - /// variables will also be equated. - pub fn collect_constrained_late_bound_regions<T>( - self, - value: &Binder<'tcx, T>, - ) -> FxHashSet<ty::BoundRegionKind> - where - T: TypeFoldable<'tcx>, - { - self.collect_late_bound_regions(value, true) - } - - /// Returns a set of all late-bound regions that appear in `value` anywhere. - pub fn collect_referenced_late_bound_regions<T>( - self, - value: &Binder<'tcx, T>, - ) -> FxHashSet<ty::BoundRegionKind> - where - T: TypeFoldable<'tcx>, - { - self.collect_late_bound_regions(value, false) - } - - fn collect_late_bound_regions<T>( - self, - value: &Binder<'tcx, T>, - just_constraint: bool, - ) -> FxHashSet<ty::BoundRegionKind> - where - T: TypeFoldable<'tcx>, - { - let mut collector = LateBoundRegionsCollector::new(just_constraint); - let result = value.as_ref().skip_binder().visit_with(&mut collector); - assert!(result.is_continue()); // should never have stopped early - collector.regions - } - /// Replaces any late-bound regions bound in `value` with `'erased`. Useful in codegen but also /// method lookup and a few other places where precise region relationships are not required. pub fn erase_late_bound_regions<T>(self, value: Binder<'tcx, T>) -> T @@ -940,103 +637,6 @@ impl<'tcx> TyCtxt<'tcx> { } } -pub struct ValidateBoundVars<'tcx> { - bound_vars: &'tcx ty::List<ty::BoundVariableKind>, - binder_index: ty::DebruijnIndex, - // We may encounter the same variable at different levels of binding, so - // this can't just be `Ty` - visited: SsoHashSet<(ty::DebruijnIndex, Ty<'tcx>)>, -} - -impl<'tcx> ValidateBoundVars<'tcx> { - pub fn new(bound_vars: &'tcx ty::List<ty::BoundVariableKind>) -> Self { - ValidateBoundVars { - bound_vars, - binder_index: ty::INNERMOST, - visited: SsoHashSet::default(), - } - } -} - -impl<'tcx> TypeVisitor<'tcx> for ValidateBoundVars<'tcx> { - type BreakTy = (); - - fn visit_binder<T: TypeFoldable<'tcx>>( - &mut self, - t: &Binder<'tcx, T>, - ) -> ControlFlow<Self::BreakTy> { - self.binder_index.shift_in(1); - let result = t.super_visit_with(self); - self.binder_index.shift_out(1); - result - } - - fn visit_ty(&mut self, t: Ty<'tcx>) -> ControlFlow<Self::BreakTy> { - if t.outer_exclusive_binder() < self.binder_index - || !self.visited.insert((self.binder_index, t)) - { - return ControlFlow::BREAK; - } - match *t.kind() { - ty::Bound(debruijn, bound_ty) if debruijn == self.binder_index => { - if self.bound_vars.len() <= bound_ty.var.as_usize() { - bug!("Not enough bound vars: {:?} not found in {:?}", t, self.bound_vars); - } - let list_var = self.bound_vars[bound_ty.var.as_usize()]; - match list_var { - ty::BoundVariableKind::Ty(kind) => { - if kind != bound_ty.kind { - bug!( - "Mismatched type kinds: {:?} doesn't var in list {:?}", - bound_ty.kind, - list_var - ); - } - } - _ => { - bug!("Mismatched bound variable kinds! Expected type, found {:?}", list_var) - } - } - } - - _ => (), - }; - - t.super_visit_with(self) - } - - fn visit_region(&mut self, r: ty::Region<'tcx>) -> ControlFlow<Self::BreakTy> { - match *r { - ty::ReLateBound(index, br) if index == self.binder_index => { - if self.bound_vars.len() <= br.var.as_usize() { - bug!("Not enough bound vars: {:?} not found in {:?}", br, self.bound_vars); - } - let list_var = self.bound_vars[br.var.as_usize()]; - match list_var { - ty::BoundVariableKind::Region(kind) => { - if kind != br.kind { - bug!( - "Mismatched region kinds: {:?} doesn't match var ({:?}) in list ({:?})", - br.kind, - list_var, - self.bound_vars - ); - } - } - _ => bug!( - "Mismatched bound variable kinds! Expected region, found {:?}", - list_var - ), - } - } - - _ => (), - }; - - r.super_visit_with(self) - } -} - /////////////////////////////////////////////////////////////////////////// // Shifter // @@ -1141,301 +741,3 @@ where value.fold_with(&mut Shifter::new(tcx, amount)) } - -#[derive(Debug, PartialEq, Eq, Copy, Clone)] -struct FoundEscapingVars; - -/// An "escaping var" is a bound var whose binder is not part of `t`. A bound var can be a -/// bound region or a bound type. -/// -/// So, for example, consider a type like the following, which has two binders: -/// -/// for<'a> fn(x: for<'b> fn(&'a isize, &'b isize)) -/// ^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ outer scope -/// ^~~~~~~~~~~~~~~~~~~~~~~~~~~~ inner scope -/// -/// This type has *bound regions* (`'a`, `'b`), but it does not have escaping regions, because the -/// binders of both `'a` and `'b` are part of the type itself. However, if we consider the *inner -/// fn type*, that type has an escaping region: `'a`. -/// -/// Note that what I'm calling an "escaping var" is often just called a "free var". However, -/// we already use the term "free var". It refers to the regions or types that we use to represent -/// bound regions or type params on a fn definition while we are type checking its body. -/// -/// To clarify, conceptually there is no particular difference between -/// an "escaping" var and a "free" var. However, there is a big -/// difference in practice. Basically, when "entering" a binding -/// level, one is generally required to do some sort of processing to -/// a bound var, such as replacing it with a fresh/placeholder -/// var, or making an entry in the environment to represent the -/// scope to which it is attached, etc. An escaping var represents -/// a bound var for which this processing has not yet been done. -struct HasEscapingVarsVisitor { - /// Anything bound by `outer_index` or "above" is escaping. - outer_index: ty::DebruijnIndex, -} - -impl<'tcx> TypeVisitor<'tcx> for HasEscapingVarsVisitor { - type BreakTy = FoundEscapingVars; - - fn visit_binder<T: TypeFoldable<'tcx>>( - &mut self, - t: &Binder<'tcx, T>, - ) -> ControlFlow<Self::BreakTy> { - self.outer_index.shift_in(1); - let result = t.super_visit_with(self); - self.outer_index.shift_out(1); - result - } - - #[inline] - fn visit_ty(&mut self, t: Ty<'tcx>) -> ControlFlow<Self::BreakTy> { - // If the outer-exclusive-binder is *strictly greater* than - // `outer_index`, that means that `t` contains some content - // bound at `outer_index` or above (because - // `outer_exclusive_binder` is always 1 higher than the - // content in `t`). Therefore, `t` has some escaping vars. - if t.outer_exclusive_binder() > self.outer_index { - ControlFlow::Break(FoundEscapingVars) - } else { - ControlFlow::CONTINUE - } - } - - #[inline] - fn visit_region(&mut self, r: ty::Region<'tcx>) -> ControlFlow<Self::BreakTy> { - // If the region is bound by `outer_index` or anything outside - // of outer index, then it escapes the binders we have - // visited. - if r.bound_at_or_above_binder(self.outer_index) { - ControlFlow::Break(FoundEscapingVars) - } else { - ControlFlow::CONTINUE - } - } - - fn visit_const(&mut self, ct: ty::Const<'tcx>) -> ControlFlow<Self::BreakTy> { - // we don't have a `visit_infer_const` callback, so we have to - // hook in here to catch this case (annoying...), but - // otherwise we do want to remember to visit the rest of the - // const, as it has types/regions embedded in a lot of other - // places. - match ct.kind() { - ty::ConstKind::Bound(debruijn, _) if debruijn >= self.outer_index => { - ControlFlow::Break(FoundEscapingVars) - } - _ => ct.super_visit_with(self), - } - } - - #[inline] - fn visit_predicate(&mut self, predicate: ty::Predicate<'tcx>) -> ControlFlow<Self::BreakTy> { - if predicate.outer_exclusive_binder() > self.outer_index { - ControlFlow::Break(FoundEscapingVars) - } else { - ControlFlow::CONTINUE - } - } -} - -#[derive(Debug, PartialEq, Eq, Copy, Clone)] -struct FoundFlags; - -// FIXME: Optimize for checking for infer flags -struct HasTypeFlagsVisitor { - flags: ty::TypeFlags, -} - -impl std::fmt::Debug for HasTypeFlagsVisitor { - fn fmt(&self, fmt: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { - self.flags.fmt(fmt) - } -} - -impl<'tcx> TypeVisitor<'tcx> for HasTypeFlagsVisitor { - type BreakTy = FoundFlags; - - #[inline] - #[instrument(skip(self), level = "trace")] - fn visit_ty(&mut self, t: Ty<'tcx>) -> ControlFlow<Self::BreakTy> { - let flags = t.flags(); - trace!(t.flags=?t.flags()); - if flags.intersects(self.flags) { - ControlFlow::Break(FoundFlags) - } else { - ControlFlow::CONTINUE - } - } - - #[inline] - #[instrument(skip(self), level = "trace")] - fn visit_region(&mut self, r: ty::Region<'tcx>) -> ControlFlow<Self::BreakTy> { - let flags = r.type_flags(); - trace!(r.flags=?flags); - if flags.intersects(self.flags) { - ControlFlow::Break(FoundFlags) - } else { - ControlFlow::CONTINUE - } - } - - #[inline] - #[instrument(level = "trace")] - fn visit_const(&mut self, c: ty::Const<'tcx>) -> ControlFlow<Self::BreakTy> { - let flags = FlagComputation::for_const(c); - trace!(r.flags=?flags); - if flags.intersects(self.flags) { - ControlFlow::Break(FoundFlags) - } else { - ControlFlow::CONTINUE - } - } - - #[inline] - #[instrument(level = "trace")] - fn visit_unevaluated(&mut self, uv: ty::Unevaluated<'tcx>) -> ControlFlow<Self::BreakTy> { - let flags = FlagComputation::for_unevaluated_const(uv); - trace!(r.flags=?flags); - if flags.intersects(self.flags) { - ControlFlow::Break(FoundFlags) - } else { - ControlFlow::CONTINUE - } - } - - #[inline] - #[instrument(level = "trace")] - fn visit_predicate(&mut self, predicate: ty::Predicate<'tcx>) -> ControlFlow<Self::BreakTy> { - debug!( - "HasTypeFlagsVisitor: predicate={:?} predicate.flags={:?} self.flags={:?}", - predicate, - predicate.flags(), - self.flags - ); - if predicate.flags().intersects(self.flags) { - ControlFlow::Break(FoundFlags) - } else { - ControlFlow::CONTINUE - } - } -} - -/// Collects all the late-bound regions at the innermost binding level -/// into a hash set. -struct LateBoundRegionsCollector { - current_index: ty::DebruijnIndex, - regions: FxHashSet<ty::BoundRegionKind>, - - /// `true` if we only want regions that are known to be - /// "constrained" when you equate this type with another type. In - /// particular, if you have e.g., `&'a u32` and `&'b u32`, equating - /// them constraints `'a == 'b`. But if you have `<&'a u32 as - /// Trait>::Foo` and `<&'b u32 as Trait>::Foo`, normalizing those - /// types may mean that `'a` and `'b` don't appear in the results, - /// so they are not considered *constrained*. - just_constrained: bool, -} - -impl LateBoundRegionsCollector { - fn new(just_constrained: bool) -> Self { - LateBoundRegionsCollector { - current_index: ty::INNERMOST, - regions: Default::default(), - just_constrained, - } - } -} - -impl<'tcx> TypeVisitor<'tcx> for LateBoundRegionsCollector { - fn visit_binder<T: TypeFoldable<'tcx>>( - &mut self, - t: &Binder<'tcx, T>, - ) -> ControlFlow<Self::BreakTy> { - self.current_index.shift_in(1); - let result = t.super_visit_with(self); - self.current_index.shift_out(1); - result - } - - fn visit_ty(&mut self, t: Ty<'tcx>) -> ControlFlow<Self::BreakTy> { - // if we are only looking for "constrained" region, we have to - // ignore the inputs to a projection, as they may not appear - // in the normalized form - if self.just_constrained { - if let ty::Projection(..) = t.kind() { - return ControlFlow::CONTINUE; - } - } - - t.super_visit_with(self) - } - - fn visit_const(&mut self, c: ty::Const<'tcx>) -> ControlFlow<Self::BreakTy> { - // if we are only looking for "constrained" region, we have to - // ignore the inputs of an unevaluated const, as they may not appear - // in the normalized form - if self.just_constrained { - if let ty::ConstKind::Unevaluated(..) = c.kind() { - return ControlFlow::CONTINUE; - } - } - - c.super_visit_with(self) - } - - fn visit_region(&mut self, r: ty::Region<'tcx>) -> ControlFlow<Self::BreakTy> { - if let ty::ReLateBound(debruijn, br) = *r { - if debruijn == self.current_index { - self.regions.insert(br.kind); - } - } - ControlFlow::CONTINUE - } -} - -/// Finds the max universe present -pub struct MaxUniverse { - max_universe: ty::UniverseIndex, -} - -impl MaxUniverse { - pub fn new() -> Self { - MaxUniverse { max_universe: ty::UniverseIndex::ROOT } - } - - pub fn max_universe(self) -> ty::UniverseIndex { - self.max_universe - } -} - -impl<'tcx> TypeVisitor<'tcx> for MaxUniverse { - fn visit_ty(&mut self, t: Ty<'tcx>) -> ControlFlow<Self::BreakTy> { - if let ty::Placeholder(placeholder) = t.kind() { - self.max_universe = ty::UniverseIndex::from_u32( - self.max_universe.as_u32().max(placeholder.universe.as_u32()), - ); - } - - t.super_visit_with(self) - } - - fn visit_const(&mut self, c: ty::consts::Const<'tcx>) -> ControlFlow<Self::BreakTy> { - if let ty::ConstKind::Placeholder(placeholder) = c.kind() { - self.max_universe = ty::UniverseIndex::from_u32( - self.max_universe.as_u32().max(placeholder.universe.as_u32()), - ); - } - - c.super_visit_with(self) - } - - fn visit_region(&mut self, r: ty::Region<'tcx>) -> ControlFlow<Self::BreakTy> { - if let ty::RePlaceholder(placeholder) = *r { - self.max_universe = ty::UniverseIndex::from_u32( - self.max_universe.as_u32().max(placeholder.universe.as_u32()), - ); - } - - ControlFlow::CONTINUE - } -} diff --git a/compiler/rustc_middle/src/ty/instance.rs b/compiler/rustc_middle/src/ty/instance.rs index e8dd179eac1..391abdbe84c 100644 --- a/compiler/rustc_middle/src/ty/instance.rs +++ b/compiler/rustc_middle/src/ty/instance.rs @@ -1,7 +1,9 @@ use crate::middle::codegen_fn_attrs::CodegenFnAttrFlags; use crate::ty::print::{FmtPrinter, Printer}; use crate::ty::subst::{InternalSubsts, Subst}; -use crate::ty::{self, EarlyBinder, SubstsRef, Ty, TyCtxt, TypeFoldable, TypeSuperFoldable}; +use crate::ty::{ + self, EarlyBinder, SubstsRef, Ty, TyCtxt, TypeFoldable, TypeSuperFoldable, TypeVisitable, +}; use rustc_errors::ErrorGuaranteed; use rustc_hir::def::Namespace; use rustc_hir::def_id::{CrateNum, DefId}; @@ -25,7 +27,7 @@ pub struct Instance<'tcx> { } #[derive(Copy, Clone, PartialEq, Eq, PartialOrd, Ord, Hash, Debug)] -#[derive(TyEncodable, TyDecodable, HashStable, TypeFoldable)] +#[derive(TyEncodable, TyDecodable, HashStable, TypeFoldable, TypeVisitable)] pub enum InstanceDef<'tcx> { /// A user-defined callable item. /// @@ -496,12 +498,12 @@ impl<'tcx> Instance<'tcx> { def_id: DefId, substs: ty::SubstsRef<'tcx>, requested_kind: ty::ClosureKind, - ) -> Instance<'tcx> { + ) -> Option<Instance<'tcx>> { let actual_kind = substs.as_closure().kind(); match needs_fn_once_adapter_shim(actual_kind, requested_kind) { Ok(true) => Instance::fn_once_adapter_instance(tcx, def_id, substs), - _ => Instance::new(def_id, substs), + _ => Some(Instance::new(def_id, substs)), } } @@ -515,7 +517,7 @@ impl<'tcx> Instance<'tcx> { tcx: TyCtxt<'tcx>, closure_did: DefId, substs: ty::SubstsRef<'tcx>, - ) -> Instance<'tcx> { + ) -> Option<Instance<'tcx>> { debug!("fn_once_adapter_shim({:?}, {:?})", closure_did, substs); let fn_once = tcx.require_lang_item(LangItem::FnOnce, None); let call_once = tcx @@ -531,12 +533,13 @@ impl<'tcx> Instance<'tcx> { let self_ty = tcx.mk_closure(closure_did, substs); let sig = substs.as_closure().sig(); - let sig = tcx.normalize_erasing_late_bound_regions(ty::ParamEnv::reveal_all(), sig); + let sig = + tcx.try_normalize_erasing_late_bound_regions(ty::ParamEnv::reveal_all(), sig).ok()?; assert_eq!(sig.inputs().len(), 1); let substs = tcx.mk_substs_trait(self_ty, &[sig.inputs()[0].into()]); debug!("fn_once_adapter_shim: self_ty={:?} sig={:?}", self_ty, sig); - Instance { def, substs } + Some(Instance { def, substs }) } /// Depending on the kind of `InstanceDef`, the MIR body associated with an diff --git a/compiler/rustc_middle/src/ty/layout.rs b/compiler/rustc_middle/src/ty/layout.rs index 3b05e42a53e..f87b6e4212d 100644 --- a/compiler/rustc_middle/src/ty/layout.rs +++ b/compiler/rustc_middle/src/ty/layout.rs @@ -2,7 +2,7 @@ use crate::middle::codegen_fn_attrs::CodegenFnAttrFlags; use crate::mir::{GeneratorLayout, GeneratorSavedLocal}; use crate::ty::normalize_erasing_regions::NormalizationError; use crate::ty::subst::Subst; -use crate::ty::{self, subst::SubstsRef, EarlyBinder, ReprOptions, Ty, TyCtxt, TypeFoldable}; +use crate::ty::{self, subst::SubstsRef, EarlyBinder, ReprOptions, Ty, TyCtxt, TypeVisitable}; use rustc_ast as ast; use rustc_attr as attr; use rustc_hir as hir; @@ -235,9 +235,8 @@ fn sanity_check_layout<'tcx>( if cfg!(debug_assertions) { fn check_layout_abi<'tcx>(tcx: TyCtxt<'tcx>, layout: Layout<'tcx>) { match layout.abi() { - Abi::Scalar(_scalar) => { + Abi::Scalar(scalar) => { // No padding in scalars. - /* FIXME(#96185): assert_eq!( layout.align().abi, scalar.align(&tcx).abi, @@ -247,7 +246,7 @@ fn sanity_check_layout<'tcx>( layout.size(), scalar.size(&tcx), "size mismatch between ABI and layout in {layout:#?}" - );*/ + ); } Abi::Vector { count, element } => { // No padding in vectors. Alignment can be strengthened, though. @@ -1418,9 +1417,9 @@ impl<'tcx> LayoutCx<'tcx, TyCtxt<'tcx>> { if layout_variants.iter().all(|v| v.abi.is_uninhabited()) { abi = Abi::Uninhabited; - } else if tag.size(dl) == size || variants.iter().all(|layout| layout.is_empty()) { - // Without latter check aligned enums with custom discriminant values - // Would result in ICE see the issue #92464 for more info + } else if tag.size(dl) == size { + // Make sure we only use scalar layout when the enum is entirely its + // own tag (i.e. it has no padding nor any non-ZST variant fields). abi = Abi::Scalar(tag); } else { // Try to use a ScalarPair for all tagged enums. diff --git a/compiler/rustc_middle/src/ty/mod.rs b/compiler/rustc_middle/src/ty/mod.rs index 00403ff044c..3a795af2121 100644 --- a/compiler/rustc_middle/src/ty/mod.rs +++ b/compiler/rustc_middle/src/ty/mod.rs @@ -9,9 +9,8 @@ //! //! ["The `ty` module: representing types"]: https://rustc-dev-guide.rust-lang.org/ty.html -pub use self::fold::{ - FallibleTypeFolder, TypeFoldable, TypeFolder, TypeSuperFoldable, TypeVisitor, -}; +pub use self::fold::{FallibleTypeFolder, TypeFoldable, TypeFolder, TypeSuperFoldable}; +pub use self::visit::{TypeSuperVisitable, TypeVisitable, TypeVisitor}; pub use self::AssocItemContainer::*; pub use self::BorrowKind::*; pub use self::IntVarValue::*; @@ -110,6 +109,7 @@ pub mod relate; pub mod subst; pub mod trait_def; pub mod util; +pub mod visit; pub mod vtable; pub mod walk; @@ -206,7 +206,7 @@ impl MainDefinition { /// The "header" of an impl is everything outside the body: a Self type, a trait /// ref (in the case of a trait impl), and a set of predicates (from the /// bounds / where-clauses). -#[derive(Clone, Debug, TypeFoldable)] +#[derive(Clone, Debug, TypeFoldable, TypeVisitable)] pub struct ImplHeader<'tcx> { pub impl_def_id: DefId, pub self_ty: Ty<'tcx>, @@ -214,24 +214,14 @@ pub struct ImplHeader<'tcx> { pub predicates: Vec<Predicate<'tcx>>, } -#[derive(Copy, Clone, Debug, TypeFoldable)] +#[derive(Copy, Clone, Debug, TypeFoldable, TypeVisitable)] pub enum ImplSubject<'tcx> { Trait(TraitRef<'tcx>), Inherent(Ty<'tcx>), } -#[derive( - Copy, - Clone, - PartialEq, - Eq, - Hash, - TyEncodable, - TyDecodable, - HashStable, - Debug, - TypeFoldable -)] +#[derive(Copy, Clone, PartialEq, Eq, Hash, TyEncodable, TyDecodable, HashStable, Debug)] +#[derive(TypeFoldable, TypeVisitable)] pub enum ImplPolarity { /// `impl Trait for Type` Positive, @@ -307,18 +297,8 @@ impl fmt::Display for BoundConstness { } } -#[derive( - Clone, - Debug, - PartialEq, - Eq, - Copy, - Hash, - TyEncodable, - TyDecodable, - HashStable, - TypeFoldable -)] +#[derive(Clone, Debug, PartialEq, Eq, Copy, Hash, TyEncodable, TyDecodable, HashStable)] +#[derive(TypeFoldable, TypeVisitable)] pub struct ClosureSizeProfileData<'tcx> { /// Tuple containing the types of closure captures before the feature `capture_disjoint_fields` pub before_feature_tys: Ty<'tcx>, @@ -611,8 +591,14 @@ impl<'a, 'tcx> HashStable<StableHashingContext<'a>> for Predicate<'tcx> { } } +impl rustc_errors::IntoDiagnosticArg for Predicate<'_> { + fn into_diagnostic_arg(self) -> rustc_errors::DiagnosticArgValue<'static> { + rustc_errors::DiagnosticArgValue::Str(std::borrow::Cow::Owned(self.to_string())) + } +} + #[derive(Clone, Copy, PartialEq, Eq, Hash, TyEncodable, TyDecodable)] -#[derive(HashStable, TypeFoldable)] +#[derive(HashStable, TypeFoldable, TypeVisitable)] pub enum PredicateKind<'tcx> { /// Corresponds to `where Foo: Bar<A, B, C>`. `Foo` here would be /// the `Self` type of the trait reference and `A`, `B`, and `C` @@ -784,7 +770,7 @@ impl<'tcx> Predicate<'tcx> { } #[derive(Clone, Copy, PartialEq, Eq, Hash, TyEncodable, TyDecodable)] -#[derive(HashStable, TypeFoldable)] +#[derive(HashStable, TypeFoldable, TypeVisitable)] pub struct TraitPredicate<'tcx> { pub trait_ref: TraitRef<'tcx>, @@ -863,7 +849,7 @@ impl<'tcx> PolyTraitPredicate<'tcx> { } #[derive(Clone, Copy, PartialEq, Eq, PartialOrd, Ord, Hash, Debug, TyEncodable, TyDecodable)] -#[derive(HashStable, TypeFoldable)] +#[derive(HashStable, TypeFoldable, TypeVisitable)] pub struct OutlivesPredicate<A, B>(pub A, pub B); // `A: B` pub type RegionOutlivesPredicate<'tcx> = OutlivesPredicate<ty::Region<'tcx>, ty::Region<'tcx>>; pub type TypeOutlivesPredicate<'tcx> = OutlivesPredicate<Ty<'tcx>, ty::Region<'tcx>>; @@ -874,7 +860,7 @@ pub type PolyTypeOutlivesPredicate<'tcx> = ty::Binder<'tcx, TypeOutlivesPredicat /// whether the `a` type is the type that we should label as "expected" when /// presenting user diagnostics. #[derive(Clone, Copy, PartialEq, Eq, Hash, Debug, TyEncodable, TyDecodable)] -#[derive(HashStable, TypeFoldable)] +#[derive(HashStable, TypeFoldable, TypeVisitable)] pub struct SubtypePredicate<'tcx> { pub a_is_expected: bool, pub a: Ty<'tcx>, @@ -884,7 +870,7 @@ pub type PolySubtypePredicate<'tcx> = ty::Binder<'tcx, SubtypePredicate<'tcx>>; /// Encodes that we have to coerce *from* the `a` type to the `b` type. #[derive(Clone, Copy, PartialEq, Eq, Hash, Debug, TyEncodable, TyDecodable)] -#[derive(HashStable, TypeFoldable)] +#[derive(HashStable, TypeFoldable, TypeVisitable)] pub struct CoercePredicate<'tcx> { pub a: Ty<'tcx>, pub b: Ty<'tcx>, @@ -892,7 +878,7 @@ pub struct CoercePredicate<'tcx> { pub type PolyCoercePredicate<'tcx> = ty::Binder<'tcx, CoercePredicate<'tcx>>; #[derive(Debug, Copy, Clone, PartialEq, Eq, Hash, PartialOrd, Ord, TyEncodable, TyDecodable)] -#[derive(HashStable, TypeFoldable)] +#[derive(HashStable, TypeFoldable, TypeVisitable)] pub enum Term<'tcx> { Ty(Ty<'tcx>), Const(Const<'tcx>), @@ -914,9 +900,17 @@ impl<'tcx> Term<'tcx> { pub fn ty(&self) -> Option<Ty<'tcx>> { if let Term::Ty(ty) = self { Some(*ty) } else { None } } + pub fn ct(&self) -> Option<Const<'tcx>> { if let Term::Const(c) = self { Some(*c) } else { None } } + + pub fn into_arg(self) -> GenericArg<'tcx> { + match self { + Term::Ty(ty) => ty.into(), + Term::Const(c) => c.into(), + } + } } /// This kind of predicate has no *direct* correspondent in the @@ -932,7 +926,7 @@ impl<'tcx> Term<'tcx> { /// Form #2 eventually yields one of these `ProjectionPredicate` /// instances to normalize the LHS. #[derive(Copy, Clone, PartialEq, Eq, Hash, TyEncodable, TyDecodable)] -#[derive(HashStable, TypeFoldable)] +#[derive(HashStable, TypeFoldable, TypeVisitable)] pub struct ProjectionPredicate<'tcx> { pub projection_ty: ProjectionTy<'tcx>, pub term: Term<'tcx>, @@ -1076,7 +1070,7 @@ impl<'tcx> Predicate<'tcx> { /// `[[], [U:Bar<T>]]`. Now if there were some particular reference /// like `Foo<isize,usize>`, then the `InstantiatedPredicates` would be `[[], /// [usize:Bar<isize>]]`. -#[derive(Clone, Debug, TypeFoldable)] +#[derive(Clone, Debug, TypeFoldable, TypeVisitable)] pub struct InstantiatedPredicates<'tcx> { pub predicates: Vec<Predicate<'tcx>>, pub spans: Vec<Span>, @@ -1092,24 +1086,14 @@ impl<'tcx> InstantiatedPredicates<'tcx> { } } -#[derive( - Copy, - Clone, - Debug, - PartialEq, - Eq, - HashStable, - TyEncodable, - TyDecodable, - TypeFoldable, - Lift -)] +#[derive(Copy, Clone, Debug, PartialEq, Eq, HashStable, TyEncodable, TyDecodable, Lift)] +#[derive(TypeFoldable, TypeVisitable)] pub struct OpaqueTypeKey<'tcx> { pub def_id: DefId, pub substs: SubstsRef<'tcx>, } -#[derive(Copy, Clone, Debug, TypeFoldable, HashStable, TyEncodable, TyDecodable)] +#[derive(Copy, Clone, Debug, TypeFoldable, TypeVisitable, HashStable, TyEncodable, TyDecodable)] pub struct OpaqueHiddenType<'tcx> { /// The span of this particular definition of the opaque type. So /// for example: @@ -1245,7 +1229,7 @@ pub type PlaceholderConst<'tcx> = Placeholder<BoundConst<'tcx>>; /// except that instead of a `Ty` we bundle the `DefId` of the const parameter. /// Meaning that we need to use `type_of(const_param_did)` if `const_param_did` is `Some` /// to get the type of `did`. -#[derive(Copy, Clone, Debug, TypeFoldable, Lift, TyEncodable, TyDecodable)] +#[derive(Copy, Clone, Debug, TypeFoldable, TypeVisitable, Lift, TyEncodable, TyDecodable)] #[derive(PartialEq, Eq, PartialOrd, Ord)] #[derive(Hash, HashStable)] pub struct WithOptConstParam<T> { @@ -1401,7 +1385,9 @@ impl<'tcx> TypeFoldable<'tcx> for ParamEnv<'tcx> { self.constness().try_fold_with(folder)?, )) } +} +impl<'tcx> TypeVisitable<'tcx> for ParamEnv<'tcx> { fn visit_with<V: TypeVisitor<'tcx>>(&self, visitor: &mut V) -> ControlFlow<V::BreakTy> { self.caller_bounds().visit_with(visitor)?; self.reveal().visit_with(visitor)?; @@ -1528,7 +1514,7 @@ impl<'tcx> ParamEnv<'tcx> { /// `where Box<u32>: Copy`, which are clearly never /// satisfiable. We generally want to behave as if they were true, /// although the surrounding function is never reachable. - pub fn and<T: TypeFoldable<'tcx>>(self, value: T) -> ParamEnvAnd<'tcx, T> { + pub fn and<T: TypeVisitable<'tcx>>(self, value: T) -> ParamEnvAnd<'tcx, T> { match self.reveal() { Reveal::UserFacing => ParamEnvAnd { param_env: self, value }, @@ -1561,7 +1547,7 @@ impl<'tcx> PolyTraitRef<'tcx> { } } -#[derive(Copy, Clone, Debug, PartialEq, Eq, Hash, TypeFoldable)] +#[derive(Copy, Clone, Debug, PartialEq, Eq, Hash, TypeFoldable, TypeVisitable)] pub struct ParamEnvAnd<'tcx, T> { pub param_env: ParamEnv<'tcx>, pub value: T, diff --git a/compiler/rustc_middle/src/ty/normalize_erasing_regions.rs b/compiler/rustc_middle/src/ty/normalize_erasing_regions.rs index 66a0a192a87..9d8a8116594 100644 --- a/compiler/rustc_middle/src/ty/normalize_erasing_regions.rs +++ b/compiler/rustc_middle/src/ty/normalize_erasing_regions.rs @@ -112,6 +112,26 @@ impl<'tcx> TyCtxt<'tcx> { self.normalize_erasing_regions(param_env, value) } + /// If you have a `Binder<'tcx, T>`, you can do this to strip out the + /// late-bound regions and then normalize the result, yielding up + /// a `T` (with regions erased). This is appropriate when the + /// binder is being instantiated at the call site. + /// + /// N.B., currently, higher-ranked type bounds inhibit + /// normalization. Therefore, each time we erase them in + /// codegen, we need to normalize the contents. + pub fn try_normalize_erasing_late_bound_regions<T>( + self, + param_env: ty::ParamEnv<'tcx>, + value: ty::Binder<'tcx, T>, + ) -> Result<T, NormalizationError<'tcx>> + where + T: TypeFoldable<'tcx>, + { + let value = self.erase_late_bound_regions(value); + self.try_normalize_erasing_regions(param_env, value) + } + /// Monomorphizes a type from the AST by first applying the /// in-scope substitutions and then normalizing any associated /// types. diff --git a/compiler/rustc_middle/src/ty/print/pretty.rs b/compiler/rustc_middle/src/ty/print/pretty.rs index 7f3b0fdccc6..887236c484b 100644 --- a/compiler/rustc_middle/src/ty/print/pretty.rs +++ b/compiler/rustc_middle/src/ty/print/pretty.rs @@ -2,7 +2,7 @@ use crate::mir::interpret::{AllocRange, GlobalAlloc, Pointer, Provenance, Scalar use crate::ty::subst::{GenericArg, GenericArgKind, Subst}; use crate::ty::{ self, ConstInt, DefIdTree, ParamConst, ScalarInt, Term, Ty, TyCtxt, TypeFoldable, - TypeSuperFoldable, + TypeSuperFoldable, TypeSuperVisitable, TypeVisitable, }; use rustc_apfloat::ieee::{Double, Single}; use rustc_data_structures::fx::{FxHashMap, FxIndexMap}; @@ -2277,14 +2277,14 @@ impl<'tcx> FmtPrinter<'_, 'tcx> { fn prepare_late_bound_region_info<T>(&mut self, value: &ty::Binder<'tcx, T>) where - T: TypeFoldable<'tcx>, + T: TypeVisitable<'tcx>, { struct LateBoundRegionNameCollector<'a, 'tcx> { used_region_names: &'a mut FxHashSet<Symbol>, type_collector: SsoHashSet<Ty<'tcx>>, } - impl<'tcx> ty::fold::TypeVisitor<'tcx> for LateBoundRegionNameCollector<'_, 'tcx> { + impl<'tcx> ty::visit::TypeVisitor<'tcx> for LateBoundRegionNameCollector<'_, 'tcx> { type BreakTy = (); fn visit_region(&mut self, r: ty::Region<'tcx>) -> ControlFlow<Self::BreakTy> { @@ -2388,7 +2388,7 @@ macro_rules! define_print_and_forward_display { /// Wrapper type for `ty::TraitRef` which opts-in to pretty printing only /// the trait path. That is, it will print `Trait<U>` instead of /// `<T as Trait<U>>`. -#[derive(Copy, Clone, TypeFoldable, Lift)] +#[derive(Copy, Clone, TypeFoldable, TypeVisitable, Lift)] pub struct TraitRefPrintOnlyTraitPath<'tcx>(ty::TraitRef<'tcx>); impl<'tcx> fmt::Debug for TraitRefPrintOnlyTraitPath<'tcx> { @@ -2400,7 +2400,7 @@ impl<'tcx> fmt::Debug for TraitRefPrintOnlyTraitPath<'tcx> { /// Wrapper type for `ty::TraitRef` which opts-in to pretty printing only /// the trait name. That is, it will print `Trait` instead of /// `<T as Trait<U>>`. -#[derive(Copy, Clone, TypeFoldable, Lift)] +#[derive(Copy, Clone, TypeFoldable, TypeVisitable, Lift)] pub struct TraitRefPrintOnlyTraitName<'tcx>(ty::TraitRef<'tcx>); impl<'tcx> fmt::Debug for TraitRefPrintOnlyTraitName<'tcx> { @@ -2425,7 +2425,7 @@ impl<'tcx> ty::Binder<'tcx, ty::TraitRef<'tcx>> { } } -#[derive(Copy, Clone, TypeFoldable, Lift)] +#[derive(Copy, Clone, TypeFoldable, TypeVisitable, Lift)] pub struct TraitPredPrintModifiersAndPath<'tcx>(ty::TraitPredicate<'tcx>); impl<'tcx> fmt::Debug for TraitPredPrintModifiersAndPath<'tcx> { diff --git a/compiler/rustc_middle/src/ty/relate.rs b/compiler/rustc_middle/src/ty/relate.rs index 51980acd38f..818affa7113 100644 --- a/compiler/rustc_middle/src/ty/relate.rs +++ b/compiler/rustc_middle/src/ty/relate.rs @@ -345,7 +345,7 @@ impl<'tcx> Relate<'tcx> for ty::ExistentialTraitRef<'tcx> { } } -#[derive(Copy, Debug, Clone, TypeFoldable)] +#[derive(Copy, Debug, Clone, TypeFoldable, TypeVisitable)] struct GeneratorWitness<'tcx>(&'tcx ty::List<Ty<'tcx>>); impl<'tcx> Relate<'tcx> for GeneratorWitness<'tcx> { diff --git a/compiler/rustc_middle/src/ty/structural_impls.rs b/compiler/rustc_middle/src/ty/structural_impls.rs index 8ba5b882fdd..1b4008019fb 100644 --- a/compiler/rustc_middle/src/ty/structural_impls.rs +++ b/compiler/rustc_middle/src/ty/structural_impls.rs @@ -4,8 +4,9 @@ use crate::mir::interpret; use crate::mir::ProjectionKind; -use crate::ty::fold::{FallibleTypeFolder, TypeFoldable, TypeSuperFoldable, TypeVisitor}; +use crate::ty::fold::{FallibleTypeFolder, TypeFoldable, TypeSuperFoldable}; use crate::ty::print::{with_no_trimmed_paths, FmtPrinter, Printer}; +use crate::ty::visit::{TypeSuperVisitable, TypeVisitable, TypeVisitor}; use crate::ty::{self, InferConst, Lift, Term, Ty, TyCtxt}; use rustc_data_structures::functor::IdFunctor; use rustc_hir as hir; @@ -183,7 +184,7 @@ impl<'tcx> fmt::Debug for ty::PredicateKind<'tcx> { // For things that don't carry any arena-allocated data (and are // copy...), just add them to this list. -TrivialTypeFoldableAndLiftImpls! { +TrivialTypeTraversalAndLiftImpls! { (), bool, usize, @@ -452,7 +453,7 @@ impl<'a, 'tcx> Lift<'tcx> for ty::PredicateKind<'a> { impl<'a, 'tcx, T: Lift<'tcx>> Lift<'tcx> for ty::Binder<'a, T> where - <T as Lift<'tcx>>::Lifted: TypeFoldable<'tcx>, + <T as Lift<'tcx>>::Lifted: TypeVisitable<'tcx>, { type Lifted = ty::Binder<'tcx, T::Lifted>; fn lift_to_tcx(self, tcx: TyCtxt<'tcx>) -> Option<Self::Lifted> { @@ -651,7 +652,9 @@ impl<'tcx> TypeFoldable<'tcx> for ty::AdtDef<'tcx> { fn try_fold_with<F: FallibleTypeFolder<'tcx>>(self, _folder: &mut F) -> Result<Self, F::Error> { Ok(self) } +} +impl<'tcx> TypeVisitable<'tcx> for ty::AdtDef<'tcx> { fn visit_with<V: TypeVisitor<'tcx>>(&self, _visitor: &mut V) -> ControlFlow<V::BreakTy> { ControlFlow::CONTINUE } @@ -664,7 +667,9 @@ impl<'tcx, T: TypeFoldable<'tcx>, U: TypeFoldable<'tcx>> TypeFoldable<'tcx> for ) -> Result<(T, U), F::Error> { Ok((self.0.try_fold_with(folder)?, self.1.try_fold_with(folder)?)) } +} +impl<'tcx, T: TypeVisitable<'tcx>, U: TypeVisitable<'tcx>> TypeVisitable<'tcx> for (T, U) { fn visit_with<V: TypeVisitor<'tcx>>(&self, visitor: &mut V) -> ControlFlow<V::BreakTy> { self.0.visit_with(visitor)?; self.1.visit_with(visitor) @@ -684,7 +689,11 @@ impl<'tcx, A: TypeFoldable<'tcx>, B: TypeFoldable<'tcx>, C: TypeFoldable<'tcx>> self.2.try_fold_with(folder)?, )) } +} +impl<'tcx, A: TypeVisitable<'tcx>, B: TypeVisitable<'tcx>, C: TypeVisitable<'tcx>> + TypeVisitable<'tcx> for (A, B, C) +{ fn visit_with<V: TypeVisitor<'tcx>>(&self, visitor: &mut V) -> ControlFlow<V::BreakTy> { self.0.visit_with(visitor)?; self.1.visit_with(visitor)?; @@ -692,19 +701,31 @@ impl<'tcx, A: TypeFoldable<'tcx>, B: TypeFoldable<'tcx>, C: TypeFoldable<'tcx>> } } -EnumTypeFoldableImpl! { +EnumTypeTraversalImpl! { impl<'tcx, T> TypeFoldable<'tcx> for Option<T> { (Some)(a), (None), } where T: TypeFoldable<'tcx> } +EnumTypeTraversalImpl! { + impl<'tcx, T> TypeVisitable<'tcx> for Option<T> { + (Some)(a), + (None), + } where T: TypeVisitable<'tcx> +} -EnumTypeFoldableImpl! { +EnumTypeTraversalImpl! { impl<'tcx, T, E> TypeFoldable<'tcx> for Result<T, E> { (Ok)(a), (Err)(a), } where T: TypeFoldable<'tcx>, E: TypeFoldable<'tcx>, } +EnumTypeTraversalImpl! { + impl<'tcx, T, E> TypeVisitable<'tcx> for Result<T, E> { + (Ok)(a), + (Err)(a), + } where T: TypeVisitable<'tcx>, E: TypeVisitable<'tcx>, +} impl<'tcx, T: TypeFoldable<'tcx>> TypeFoldable<'tcx> for Rc<T> { fn try_fold_with<F: FallibleTypeFolder<'tcx>>( @@ -744,7 +765,9 @@ impl<'tcx, T: TypeFoldable<'tcx>> TypeFoldable<'tcx> for Rc<T> { Ok(Rc::from_raw(Rc::into_raw(unique).cast())) } } +} +impl<'tcx, T: TypeVisitable<'tcx>> TypeVisitable<'tcx> for Rc<T> { fn visit_with<V: TypeVisitor<'tcx>>(&self, visitor: &mut V) -> ControlFlow<V::BreakTy> { (**self).visit_with(visitor) } @@ -788,7 +811,9 @@ impl<'tcx, T: TypeFoldable<'tcx>> TypeFoldable<'tcx> for Arc<T> { Ok(Arc::from_raw(Arc::into_raw(unique).cast())) } } +} +impl<'tcx, T: TypeVisitable<'tcx>> TypeVisitable<'tcx> for Arc<T> { fn visit_with<V: TypeVisitor<'tcx>>(&self, visitor: &mut V) -> ControlFlow<V::BreakTy> { (**self).visit_with(visitor) } @@ -798,7 +823,9 @@ impl<'tcx, T: TypeFoldable<'tcx>> TypeFoldable<'tcx> for Box<T> { fn try_fold_with<F: FallibleTypeFolder<'tcx>>(self, folder: &mut F) -> Result<Self, F::Error> { self.try_map_id(|value| value.try_fold_with(folder)) } +} +impl<'tcx, T: TypeVisitable<'tcx>> TypeVisitable<'tcx> for Box<T> { fn visit_with<V: TypeVisitor<'tcx>>(&self, visitor: &mut V) -> ControlFlow<V::BreakTy> { (**self).visit_with(visitor) } @@ -808,7 +835,9 @@ impl<'tcx, T: TypeFoldable<'tcx>> TypeFoldable<'tcx> for Vec<T> { fn try_fold_with<F: FallibleTypeFolder<'tcx>>(self, folder: &mut F) -> Result<Self, F::Error> { self.try_map_id(|t| t.try_fold_with(folder)) } +} +impl<'tcx, T: TypeVisitable<'tcx>> TypeVisitable<'tcx> for Vec<T> { fn visit_with<V: TypeVisitor<'tcx>>(&self, visitor: &mut V) -> ControlFlow<V::BreakTy> { self.iter().try_for_each(|t| t.visit_with(visitor)) } @@ -818,7 +847,9 @@ impl<'tcx, T: TypeFoldable<'tcx>> TypeFoldable<'tcx> for Box<[T]> { fn try_fold_with<F: FallibleTypeFolder<'tcx>>(self, folder: &mut F) -> Result<Self, F::Error> { self.try_map_id(|t| t.try_fold_with(folder)) } +} +impl<'tcx, T: TypeVisitable<'tcx>> TypeVisitable<'tcx> for Box<[T]> { fn visit_with<V: TypeVisitor<'tcx>>(&self, visitor: &mut V) -> ControlFlow<V::BreakTy> { self.iter().try_for_each(|t| t.visit_with(visitor)) } @@ -828,7 +859,9 @@ impl<'tcx, T: TypeFoldable<'tcx>> TypeFoldable<'tcx> for ty::EarlyBinder<T> { fn try_fold_with<F: FallibleTypeFolder<'tcx>>(self, folder: &mut F) -> Result<Self, F::Error> { self.try_map_bound(|ty| ty.try_fold_with(folder)) } +} +impl<'tcx, T: TypeVisitable<'tcx>> TypeVisitable<'tcx> for ty::EarlyBinder<T> { fn visit_with<V: TypeVisitor<'tcx>>(&self, visitor: &mut V) -> ControlFlow<V::BreakTy> { self.as_ref().0.visit_with(visitor) } @@ -838,7 +871,9 @@ impl<'tcx, T: TypeFoldable<'tcx>> TypeFoldable<'tcx> for ty::Binder<'tcx, T> { fn try_fold_with<F: FallibleTypeFolder<'tcx>>(self, folder: &mut F) -> Result<Self, F::Error> { folder.try_fold_binder(self) } +} +impl<'tcx, T: TypeVisitable<'tcx>> TypeVisitable<'tcx> for ty::Binder<'tcx, T> { fn visit_with<V: TypeVisitor<'tcx>>(&self, visitor: &mut V) -> ControlFlow<V::BreakTy> { visitor.visit_binder(self) } @@ -851,7 +886,9 @@ impl<'tcx, T: TypeFoldable<'tcx>> TypeSuperFoldable<'tcx> for ty::Binder<'tcx, T ) -> Result<Self, F::Error> { self.try_map_bound(|ty| ty.try_fold_with(folder)) } +} +impl<'tcx, T: TypeVisitable<'tcx>> TypeSuperVisitable<'tcx> for ty::Binder<'tcx, T> { fn super_visit_with<V: TypeVisitor<'tcx>>(&self, visitor: &mut V) -> ControlFlow<V::BreakTy> { self.as_ref().skip_binder().visit_with(visitor) } @@ -861,7 +898,11 @@ impl<'tcx> TypeFoldable<'tcx> for &'tcx ty::List<ty::Binder<'tcx, ty::Existentia fn try_fold_with<F: FallibleTypeFolder<'tcx>>(self, folder: &mut F) -> Result<Self, F::Error> { ty::util::fold_list(self, folder, |tcx, v| tcx.intern_poly_existential_predicates(v)) } +} +impl<'tcx> TypeVisitable<'tcx> + for &'tcx ty::List<ty::Binder<'tcx, ty::ExistentialPredicate<'tcx>>> +{ fn visit_with<V: TypeVisitor<'tcx>>(&self, visitor: &mut V) -> ControlFlow<V::BreakTy> { self.iter().try_for_each(|p| p.visit_with(visitor)) } @@ -871,7 +912,9 @@ impl<'tcx> TypeFoldable<'tcx> for &'tcx ty::List<ProjectionKind> { fn try_fold_with<F: FallibleTypeFolder<'tcx>>(self, folder: &mut F) -> Result<Self, F::Error> { ty::util::fold_list(self, folder, |tcx, v| tcx.intern_projs(v)) } +} +impl<'tcx> TypeVisitable<'tcx> for &'tcx ty::List<ProjectionKind> { fn visit_with<V: TypeVisitor<'tcx>>(&self, visitor: &mut V) -> ControlFlow<V::BreakTy> { self.iter().try_for_each(|t| t.visit_with(visitor)) } @@ -903,7 +946,9 @@ impl<'tcx> TypeFoldable<'tcx> for ty::instance::Instance<'tcx> { }, }) } +} +impl<'tcx> TypeVisitable<'tcx> for ty::instance::Instance<'tcx> { fn visit_with<V: TypeVisitor<'tcx>>(&self, visitor: &mut V) -> ControlFlow<V::BreakTy> { use crate::ty::InstanceDef::*; self.substs.visit_with(visitor)?; @@ -929,7 +974,9 @@ impl<'tcx> TypeFoldable<'tcx> for interpret::GlobalId<'tcx> { fn try_fold_with<F: FallibleTypeFolder<'tcx>>(self, folder: &mut F) -> Result<Self, F::Error> { Ok(Self { instance: self.instance.try_fold_with(folder)?, promoted: self.promoted }) } +} +impl<'tcx> TypeVisitable<'tcx> for interpret::GlobalId<'tcx> { fn visit_with<V: TypeVisitor<'tcx>>(&self, visitor: &mut V) -> ControlFlow<V::BreakTy> { self.instance.visit_with(visitor) } @@ -939,7 +986,9 @@ impl<'tcx> TypeFoldable<'tcx> for Ty<'tcx> { fn try_fold_with<F: FallibleTypeFolder<'tcx>>(self, folder: &mut F) -> Result<Self, F::Error> { folder.try_fold_ty(self) } +} +impl<'tcx> TypeVisitable<'tcx> for Ty<'tcx> { fn visit_with<V: TypeVisitor<'tcx>>(&self, visitor: &mut V) -> ControlFlow<V::BreakTy> { visitor.visit_ty(*self) } @@ -989,7 +1038,9 @@ impl<'tcx> TypeSuperFoldable<'tcx> for Ty<'tcx> { Ok(if *self.kind() == kind { self } else { folder.tcx().mk_ty(kind) }) } +} +impl<'tcx> TypeSuperVisitable<'tcx> for Ty<'tcx> { fn super_visit_with<V: TypeVisitor<'tcx>>(&self, visitor: &mut V) -> ControlFlow<V::BreakTy> { match self.kind() { ty::RawPtr(ref tm) => tm.visit_with(visitor), @@ -1037,7 +1088,9 @@ impl<'tcx> TypeFoldable<'tcx> for ty::Region<'tcx> { fn try_fold_with<F: FallibleTypeFolder<'tcx>>(self, folder: &mut F) -> Result<Self, F::Error> { folder.try_fold_region(self) } +} +impl<'tcx> TypeVisitable<'tcx> for ty::Region<'tcx> { fn visit_with<V: TypeVisitor<'tcx>>(&self, visitor: &mut V) -> ControlFlow<V::BreakTy> { visitor.visit_region(*self) } @@ -1050,7 +1103,9 @@ impl<'tcx> TypeSuperFoldable<'tcx> for ty::Region<'tcx> { ) -> Result<Self, F::Error> { Ok(self) } +} +impl<'tcx> TypeSuperVisitable<'tcx> for ty::Region<'tcx> { fn super_visit_with<V: TypeVisitor<'tcx>>(&self, _visitor: &mut V) -> ControlFlow<V::BreakTy> { ControlFlow::CONTINUE } @@ -1060,7 +1115,9 @@ impl<'tcx> TypeFoldable<'tcx> for ty::Predicate<'tcx> { fn try_fold_with<F: FallibleTypeFolder<'tcx>>(self, folder: &mut F) -> Result<Self, F::Error> { folder.try_fold_predicate(self) } +} +impl<'tcx> TypeVisitable<'tcx> for ty::Predicate<'tcx> { fn visit_with<V: TypeVisitor<'tcx>>(&self, visitor: &mut V) -> ControlFlow<V::BreakTy> { visitor.visit_predicate(*self) } @@ -1082,7 +1139,9 @@ impl<'tcx> TypeSuperFoldable<'tcx> for ty::Predicate<'tcx> { let new = self.kind().try_fold_with(folder)?; Ok(folder.tcx().reuse_or_mk_predicate(self, new)) } +} +impl<'tcx> TypeSuperVisitable<'tcx> for ty::Predicate<'tcx> { fn super_visit_with<V: TypeVisitor<'tcx>>(&self, visitor: &mut V) -> ControlFlow<V::BreakTy> { self.kind().visit_with(visitor) } @@ -1092,7 +1151,9 @@ impl<'tcx> TypeFoldable<'tcx> for &'tcx ty::List<ty::Predicate<'tcx>> { fn try_fold_with<F: FallibleTypeFolder<'tcx>>(self, folder: &mut F) -> Result<Self, F::Error> { ty::util::fold_list(self, folder, |tcx, v| tcx.intern_predicates(v)) } +} +impl<'tcx> TypeVisitable<'tcx> for &'tcx ty::List<ty::Predicate<'tcx>> { fn visit_with<V: TypeVisitor<'tcx>>(&self, visitor: &mut V) -> ControlFlow<V::BreakTy> { self.iter().try_for_each(|p| p.visit_with(visitor)) } @@ -1102,7 +1163,9 @@ impl<'tcx, T: TypeFoldable<'tcx>, I: Idx> TypeFoldable<'tcx> for IndexVec<I, T> fn try_fold_with<F: FallibleTypeFolder<'tcx>>(self, folder: &mut F) -> Result<Self, F::Error> { self.try_map_id(|x| x.try_fold_with(folder)) } +} +impl<'tcx, T: TypeVisitable<'tcx>, I: Idx> TypeVisitable<'tcx> for IndexVec<I, T> { fn visit_with<V: TypeVisitor<'tcx>>(&self, visitor: &mut V) -> ControlFlow<V::BreakTy> { self.iter().try_for_each(|t| t.visit_with(visitor)) } @@ -1112,7 +1175,9 @@ impl<'tcx> TypeFoldable<'tcx> for ty::Const<'tcx> { fn try_fold_with<F: FallibleTypeFolder<'tcx>>(self, folder: &mut F) -> Result<Self, F::Error> { folder.try_fold_const(self) } +} +impl<'tcx> TypeVisitable<'tcx> for ty::Const<'tcx> { fn visit_with<V: TypeVisitor<'tcx>>(&self, visitor: &mut V) -> ControlFlow<V::BreakTy> { visitor.visit_const(*self) } @@ -1131,7 +1196,9 @@ impl<'tcx> TypeSuperFoldable<'tcx> for ty::Const<'tcx> { Ok(self) } } +} +impl<'tcx> TypeSuperVisitable<'tcx> for ty::Const<'tcx> { fn super_visit_with<V: TypeVisitor<'tcx>>(&self, visitor: &mut V) -> ControlFlow<V::BreakTy> { self.ty().visit_with(visitor)?; self.kind().visit_with(visitor) @@ -1150,7 +1217,9 @@ impl<'tcx> TypeFoldable<'tcx> for ty::ConstKind<'tcx> { | ty::ConstKind::Error(_) => self, }) } +} +impl<'tcx> TypeVisitable<'tcx> for ty::ConstKind<'tcx> { fn visit_with<V: TypeVisitor<'tcx>>(&self, visitor: &mut V) -> ControlFlow<V::BreakTy> { match *self { ty::ConstKind::Infer(ic) => ic.visit_with(visitor), @@ -1168,7 +1237,9 @@ impl<'tcx> TypeFoldable<'tcx> for InferConst<'tcx> { fn try_fold_with<F: FallibleTypeFolder<'tcx>>(self, _folder: &mut F) -> Result<Self, F::Error> { Ok(self) } +} +impl<'tcx> TypeVisitable<'tcx> for InferConst<'tcx> { fn visit_with<V: TypeVisitor<'tcx>>(&self, _visitor: &mut V) -> ControlFlow<V::BreakTy> { ControlFlow::CONTINUE } @@ -1178,7 +1249,9 @@ impl<'tcx> TypeFoldable<'tcx> for ty::Unevaluated<'tcx> { fn try_fold_with<F: FallibleTypeFolder<'tcx>>(self, folder: &mut F) -> Result<Self, F::Error> { folder.try_fold_unevaluated(self) } +} +impl<'tcx> TypeVisitable<'tcx> for ty::Unevaluated<'tcx> { fn visit_with<V: TypeVisitor<'tcx>>(&self, visitor: &mut V) -> ControlFlow<V::BreakTy> { visitor.visit_unevaluated(*self) } @@ -1195,7 +1268,9 @@ impl<'tcx> TypeSuperFoldable<'tcx> for ty::Unevaluated<'tcx> { promoted: self.promoted, }) } +} +impl<'tcx> TypeSuperVisitable<'tcx> for ty::Unevaluated<'tcx> { fn super_visit_with<V: TypeVisitor<'tcx>>(&self, visitor: &mut V) -> ControlFlow<V::BreakTy> { self.substs.visit_with(visitor) } @@ -1205,7 +1280,9 @@ impl<'tcx> TypeFoldable<'tcx> for ty::Unevaluated<'tcx, ()> { fn try_fold_with<F: FallibleTypeFolder<'tcx>>(self, folder: &mut F) -> Result<Self, F::Error> { Ok(self.expand().try_fold_with(folder)?.shrink()) } +} +impl<'tcx> TypeVisitable<'tcx> for ty::Unevaluated<'tcx, ()> { fn visit_with<V: TypeVisitor<'tcx>>(&self, visitor: &mut V) -> ControlFlow<V::BreakTy> { self.expand().visit_with(visitor) } @@ -1215,7 +1292,9 @@ impl<'tcx> TypeFoldable<'tcx> for hir::Constness { fn try_fold_with<F: FallibleTypeFolder<'tcx>>(self, _: &mut F) -> Result<Self, F::Error> { Ok(self) } +} +impl<'tcx> TypeVisitable<'tcx> for hir::Constness { fn visit_with<V: TypeVisitor<'tcx>>(&self, _: &mut V) -> ControlFlow<V::BreakTy> { ControlFlow::CONTINUE } diff --git a/compiler/rustc_middle/src/ty/sty.rs b/compiler/rustc_middle/src/ty/sty.rs index 296442e2436..815e39aab57 100644 --- a/compiler/rustc_middle/src/ty/sty.rs +++ b/compiler/rustc_middle/src/ty/sty.rs @@ -3,11 +3,11 @@ #![allow(rustc::usage_of_ty_tykind)] use crate::infer::canonical::Canonical; -use crate::ty::fold::ValidateBoundVars; use crate::ty::subst::{GenericArg, InternalSubsts, Subst, SubstsRef}; +use crate::ty::visit::ValidateBoundVars; use crate::ty::InferTy::*; use crate::ty::{ - self, AdtDef, DefIdTree, Discr, Term, Ty, TyCtxt, TypeFlags, TypeFoldable, TypeSuperFoldable, + self, AdtDef, DefIdTree, Discr, Term, Ty, TyCtxt, TypeFlags, TypeSuperVisitable, TypeVisitable, TypeVisitor, }; use crate::ty::{List, ParamEnv}; @@ -38,7 +38,7 @@ pub type TyKind<'tcx> = IrTyKind<TyCtxt<'tcx>>; pub type RegionKind<'tcx> = IrRegionKind<TyCtxt<'tcx>>; #[derive(Clone, Copy, PartialEq, Eq, PartialOrd, Ord, Hash, Debug, TyEncodable, TyDecodable)] -#[derive(HashStable, TypeFoldable, Lift)] +#[derive(HashStable, TypeFoldable, TypeVisitable, Lift)] pub struct TypeAndMut<'tcx> { pub ty: Ty<'tcx>, pub mutbl: hir::Mutability, @@ -201,7 +201,7 @@ static_assert_size!(TyKind<'_>, 32); /// * `GR`: The "return type", which is the type of value returned upon /// completion of the generator. /// * `GW`: The "generator witness". -#[derive(Copy, Clone, Debug, TypeFoldable)] +#[derive(Copy, Clone, Debug, TypeFoldable, TypeVisitable)] pub struct ClosureSubsts<'tcx> { /// Lifetime and type parameters from the enclosing function, /// concatenated with a tuple containing the types of the upvars. @@ -328,7 +328,7 @@ impl<'tcx> ClosureSubsts<'tcx> { } /// Similar to `ClosureSubsts`; see the above documentation for more. -#[derive(Copy, Clone, Debug, TypeFoldable)] +#[derive(Copy, Clone, Debug, TypeFoldable, TypeVisitable)] pub struct GeneratorSubsts<'tcx> { pub substs: SubstsRef<'tcx>, } @@ -608,7 +608,7 @@ impl<'tcx> UpvarSubsts<'tcx> { /// type of the constant. The reason that `R` is represented as an extra type parameter /// is the same reason that [`ClosureSubsts`] have `CS` and `U` as type parameters: /// inline const can reference lifetimes that are internal to the creating function. -#[derive(Copy, Clone, Debug, TypeFoldable)] +#[derive(Copy, Clone, Debug, TypeFoldable, TypeVisitable)] pub struct InlineConstSubsts<'tcx> { /// Generic parameters from the enclosing item, /// concatenated with the inferred type of the constant. @@ -655,7 +655,7 @@ impl<'tcx> InlineConstSubsts<'tcx> { } #[derive(Debug, Copy, Clone, PartialEq, PartialOrd, Ord, Eq, Hash, TyEncodable, TyDecodable)] -#[derive(HashStable, TypeFoldable)] +#[derive(HashStable, TypeFoldable, TypeVisitable)] pub enum ExistentialPredicate<'tcx> { /// E.g., `Iterator`. Trait(ExistentialTraitRef<'tcx>), @@ -781,7 +781,7 @@ impl<'tcx> List<ty::Binder<'tcx, ExistentialPredicate<'tcx>>> { /// Trait references also appear in object types like `Foo<U>`, but in /// that case the `Self` parameter is absent from the substitutions. #[derive(Copy, Clone, PartialEq, Eq, PartialOrd, Ord, Hash, TyEncodable, TyDecodable)] -#[derive(HashStable, TypeFoldable)] +#[derive(HashStable, TypeFoldable, TypeVisitable)] pub struct TraitRef<'tcx> { pub def_id: DefId, pub substs: SubstsRef<'tcx>, @@ -853,7 +853,7 @@ impl<'tcx> PolyTraitRef<'tcx> { /// The substitutions don't include the erased `Self`, only trait /// type and lifetime parameters (`[X, Y]` and `['a, 'b]` above). #[derive(Copy, Clone, PartialEq, Eq, PartialOrd, Ord, Hash, TyEncodable, TyDecodable)] -#[derive(HashStable, TypeFoldable)] +#[derive(HashStable, TypeFoldable, TypeVisitable)] pub struct ExistentialTraitRef<'tcx> { pub def_id: DefId, pub substs: SubstsRef<'tcx>, @@ -986,7 +986,7 @@ pub struct Binder<'tcx, T>(T, &'tcx List<BoundVariableKind>); impl<'tcx, T> Binder<'tcx, T> where - T: TypeFoldable<'tcx>, + T: TypeVisitable<'tcx>, { /// Wraps `value` in a binder, asserting that `value` does not /// contain any bound vars that would be bound by the @@ -1050,14 +1050,14 @@ impl<'tcx, T> Binder<'tcx, T> { Binder(value, self.1) } - pub fn map_bound_ref<F, U: TypeFoldable<'tcx>>(&self, f: F) -> Binder<'tcx, U> + pub fn map_bound_ref<F, U: TypeVisitable<'tcx>>(&self, f: F) -> Binder<'tcx, U> where F: FnOnce(&T) -> U, { self.as_ref().map_bound(f) } - pub fn map_bound<F, U: TypeFoldable<'tcx>>(self, f: F) -> Binder<'tcx, U> + pub fn map_bound<F, U: TypeVisitable<'tcx>>(self, f: F) -> Binder<'tcx, U> where F: FnOnce(T) -> U, { @@ -1069,7 +1069,7 @@ impl<'tcx, T> Binder<'tcx, T> { Binder(value, self.1) } - pub fn try_map_bound<F, U: TypeFoldable<'tcx>, E>(self, f: F) -> Result<Binder<'tcx, U>, E> + pub fn try_map_bound<F, U: TypeVisitable<'tcx>, E>(self, f: F) -> Result<Binder<'tcx, U>, E> where F: FnOnce(T) -> Result<U, E>, { @@ -1092,7 +1092,7 @@ impl<'tcx, T> Binder<'tcx, T> { /// in `bind`. This may be (debug) asserted in the future. pub fn rebind<U>(&self, value: U) -> Binder<'tcx, U> where - U: TypeFoldable<'tcx>, + U: TypeVisitable<'tcx>, { if cfg!(debug_assertions) { let mut validator = ValidateBoundVars::new(self.bound_vars()); @@ -1113,7 +1113,7 @@ impl<'tcx, T> Binder<'tcx, T> { /// would not be that useful.) pub fn no_bound_vars(self) -> Option<T> where - T: TypeFoldable<'tcx>, + T: TypeVisitable<'tcx>, { if self.0.has_escaping_bound_vars() { None } else { Some(self.skip_binder()) } } @@ -1143,7 +1143,7 @@ impl<'tcx, T> Binder<'tcx, Option<T>> { /// Represents the projection of an associated type. In explicit UFCS /// form this would be written `<T as Trait<..>>::N`. #[derive(Copy, Clone, PartialEq, Eq, PartialOrd, Ord, Hash, Debug, TyEncodable, TyDecodable)] -#[derive(HashStable, TypeFoldable)] +#[derive(HashStable, TypeFoldable, TypeVisitable)] pub struct ProjectionTy<'tcx> { /// The parameters of the associated item. pub substs: SubstsRef<'tcx>, @@ -1192,7 +1192,7 @@ impl<'tcx> ProjectionTy<'tcx> { } } -#[derive(Copy, Clone, Debug, TypeFoldable)] +#[derive(Copy, Clone, Debug, TypeFoldable, TypeVisitable)] pub struct GenSig<'tcx> { pub resume_ty: Ty<'tcx>, pub yield_ty: Ty<'tcx>, @@ -1208,7 +1208,7 @@ pub type PolyGenSig<'tcx> = Binder<'tcx, GenSig<'tcx>>; /// - `output`: is the return type. /// - `c_variadic`: indicates whether this is a C-variadic function. #[derive(Copy, Clone, PartialEq, Eq, PartialOrd, Ord, Hash, TyEncodable, TyDecodable)] -#[derive(HashStable, TypeFoldable)] +#[derive(HashStable, TypeFoldable, TypeVisitable)] pub struct FnSig<'tcx> { pub inputs_and_output: &'tcx List<Ty<'tcx>>, pub c_variadic: bool, @@ -1385,7 +1385,7 @@ impl From<BoundVar> for BoundTy { /// A `ProjectionPredicate` for an `ExistentialTraitRef`. #[derive(Clone, Copy, PartialEq, Eq, PartialOrd, Ord, Hash, Debug, TyEncodable, TyDecodable)] -#[derive(HashStable, TypeFoldable)] +#[derive(HashStable, TypeFoldable, TypeVisitable)] pub struct ExistentialProjection<'tcx> { pub item_def_id: DefId, pub substs: SubstsRef<'tcx>, diff --git a/compiler/rustc_middle/src/ty/subst.rs b/compiler/rustc_middle/src/ty/subst.rs index 1417c8a511c..3a524d7b0f3 100644 --- a/compiler/rustc_middle/src/ty/subst.rs +++ b/compiler/rustc_middle/src/ty/subst.rs @@ -2,10 +2,9 @@ use crate::mir; use crate::ty::codec::{TyDecoder, TyEncoder}; -use crate::ty::fold::{ - FallibleTypeFolder, TypeFoldable, TypeFolder, TypeSuperFoldable, TypeVisitor, -}; +use crate::ty::fold::{FallibleTypeFolder, TypeFoldable, TypeFolder, TypeSuperFoldable}; use crate::ty::sty::{ClosureSubsts, GeneratorSubsts, InlineConstSubsts}; +use crate::ty::visit::{TypeVisitable, TypeVisitor}; use crate::ty::{self, Lift, List, ParamConst, Ty, TyCtxt}; use rustc_data_structures::intern::{Interned, WithStableHash}; @@ -205,7 +204,9 @@ impl<'tcx> TypeFoldable<'tcx> for GenericArg<'tcx> { GenericArgKind::Const(ct) => ct.try_fold_with(folder).map(Into::into), } } +} +impl<'tcx> TypeVisitable<'tcx> for GenericArg<'tcx> { fn visit_with<V: TypeVisitor<'tcx>>(&self, visitor: &mut V) -> ControlFlow<V::BreakTy> { match self.unpack() { GenericArgKind::Lifetime(lt) => lt.visit_with(visitor), @@ -449,7 +450,9 @@ impl<'tcx> TypeFoldable<'tcx> for SubstsRef<'tcx> { _ => ty::util::fold_list(self, folder, |tcx, v| tcx.intern_substs(v)), } } +} +impl<'tcx> TypeVisitable<'tcx> for SubstsRef<'tcx> { fn visit_with<V: TypeVisitor<'tcx>>(&self, visitor: &mut V) -> ControlFlow<V::BreakTy> { self.iter().try_for_each(|t| t.visit_with(visitor)) } @@ -485,7 +488,9 @@ impl<'tcx> TypeFoldable<'tcx> for &'tcx ty::List<Ty<'tcx>> { _ => ty::util::fold_list(self, folder, |tcx, v| tcx.intern_type_list(v)), } } +} +impl<'tcx> TypeVisitable<'tcx> for &'tcx ty::List<Ty<'tcx>> { fn visit_with<V: TypeVisitor<'tcx>>(&self, visitor: &mut V) -> ControlFlow<V::BreakTy> { self.iter().try_for_each(|t| t.visit_with(visitor)) } @@ -722,7 +727,7 @@ impl<'a, 'tcx> SubstFolder<'a, 'tcx> { /// Stores the user-given substs to reach some fully qualified path /// (e.g., `<T>::Item` or `<T as Trait>::Item`). #[derive(Copy, Clone, Debug, PartialEq, Eq, Hash, TyEncodable, TyDecodable)] -#[derive(HashStable, TypeFoldable, Lift)] +#[derive(HashStable, TypeFoldable, TypeVisitable, Lift)] pub struct UserSubsts<'tcx> { /// The substitutions for the item as given by the user. pub substs: SubstsRef<'tcx>, @@ -749,7 +754,7 @@ pub struct UserSubsts<'tcx> { /// the self type, giving `Foo<?A>`. Finally, we unify that with /// the self type here, which contains `?A` to be `&'static u32` #[derive(Copy, Clone, Debug, PartialEq, Eq, Hash, TyEncodable, TyDecodable)] -#[derive(HashStable, TypeFoldable, Lift)] +#[derive(HashStable, TypeFoldable, TypeVisitable, Lift)] pub struct UserSelfTy<'tcx> { pub impl_def_id: DefId, pub self_ty: Ty<'tcx>, diff --git a/compiler/rustc_middle/src/ty/trait_def.rs b/compiler/rustc_middle/src/ty/trait_def.rs index cb34b64660d..826c16dda4a 100644 --- a/compiler/rustc_middle/src/ty/trait_def.rs +++ b/compiler/rustc_middle/src/ty/trait_def.rs @@ -1,6 +1,6 @@ use crate::traits::specialization_graph; use crate::ty::fast_reject::{self, SimplifiedType, TreatParams}; -use crate::ty::fold::TypeFoldable; +use crate::ty::visit::TypeVisitable; use crate::ty::{Ident, Ty, TyCtxt}; use hir::def_id::LOCAL_CRATE; use rustc_hir as hir; diff --git a/compiler/rustc_middle/src/ty/util.rs b/compiler/rustc_middle/src/ty/util.rs index 38846031bad..3a876df84c2 100644 --- a/compiler/rustc_middle/src/ty/util.rs +++ b/compiler/rustc_middle/src/ty/util.rs @@ -6,6 +6,7 @@ use crate::ty::query::TyCtxtAt; use crate::ty::subst::{GenericArgKind, Subst, SubstsRef}; use crate::ty::{ self, DefIdTree, FallibleTypeFolder, Ty, TyCtxt, TypeFoldable, TypeFolder, TypeSuperFoldable, + TypeVisitable, }; use rustc_apfloat::Float as _; use rustc_ast as ast; diff --git a/compiler/rustc_middle/src/ty/visit.rs b/compiler/rustc_middle/src/ty/visit.rs new file mode 100644 index 00000000000..5365067209a --- /dev/null +++ b/compiler/rustc_middle/src/ty/visit.rs @@ -0,0 +1,745 @@ +//! A visiting traversal mechanism for complex data structures that contain type +//! information. +//! +//! This is a read-only traversal of the data structure. +//! +//! This traversal has limited flexibility. Only a small number of "types of +//! interest" within the complex data structures can receive custom +//! visitation. These are the ones containing the most important type-related +//! information, such as `Ty`, `Predicate`, `Region`, and `Const`. +//! +//! There are three groups of traits involved in each traversal. +//! - `TypeVisitable`. This is implemented once for many types, including: +//! - Types of interest, for which the the methods delegate to the +//! visitor. +//! - All other types, including generic containers like `Vec` and `Option`. +//! It defines a "skeleton" of how they should be visited. +//! - `TypeSuperVisitable`. This is implemented only for each type of interest, +//! and defines the visiting "skeleton" for these types. +//! - `TypeVisitor`. This is implemented for each visitor. This defines how +//! types of interest are visited. +//! +//! This means each visit is a mixture of (a) generic visiting operations, and (b) +//! custom visit operations that are specific to the visitor. +//! - The `TypeVisitable` impls handle most of the traversal, and call into +//! `TypeVisitor` when they encounter a type of interest. +//! - A `TypeVisitor` may call into another `TypeVisitable` impl, because some of +//! the types of interest are recursive and can contain other types of interest. +//! - A `TypeVisitor` may also call into a `TypeSuperVisitable` impl, because each +//! visitor might provide custom handling only for some types of interest, or +//! only for some variants of each type of interest, and then use default +//! traversal for the remaining cases. +//! +//! For example, if you have `struct S(Ty, U)` where `S: TypeVisitable` and `U: +//! TypeVisitable`, and an instance `s = S(ty, u)`, it would be visited like so: +//! ```text +//! s.visit_with(visitor) calls +//! - ty.visit_with(visitor) calls +//! - visitor.visit_ty(ty) may call +//! - ty.super_visit_with(visitor) +//! - u.visit_with(visitor) +//! ``` +use crate::mir; +use crate::ty::{self, flags::FlagComputation, Binder, Ty, TyCtxt, TypeFlags}; +use rustc_errors::ErrorGuaranteed; + +use rustc_data_structures::fx::FxHashSet; +use rustc_data_structures::sso::SsoHashSet; +use std::fmt; +use std::ops::ControlFlow; + +/// This trait is implemented for every type that can be visited, +/// providing the skeleton of the traversal. +/// +/// To implement this conveniently, use the derive macro located in +/// `rustc_macros`. +pub trait TypeVisitable<'tcx>: fmt::Debug + Clone { + /// The entry point for visiting. To visit a value `t` with a visitor `v` + /// call: `t.visit_with(v)`. + /// + /// For most types, this just traverses the value, calling `visit_with` on + /// each field/element. + /// + /// For types of interest (such as `Ty`), the implementation of this method + /// that calls a visitor method specifically for that type (such as + /// `V::visit_ty`). This is where control transfers from `TypeFoldable` to + /// `TypeVisitor`. + fn visit_with<V: TypeVisitor<'tcx>>(&self, visitor: &mut V) -> ControlFlow<V::BreakTy>; + + /// Returns `true` if `self` has any late-bound regions that are either + /// bound by `binder` or bound by some binder outside of `binder`. + /// If `binder` is `ty::INNERMOST`, this indicates whether + /// there are any late-bound regions that appear free. + fn has_vars_bound_at_or_above(&self, binder: ty::DebruijnIndex) -> bool { + self.visit_with(&mut HasEscapingVarsVisitor { outer_index: binder }).is_break() + } + + /// Returns `true` if this `self` has any regions that escape `binder` (and + /// hence are not bound by it). + fn has_vars_bound_above(&self, binder: ty::DebruijnIndex) -> bool { + self.has_vars_bound_at_or_above(binder.shifted_in(1)) + } + + fn has_escaping_bound_vars(&self) -> bool { + self.has_vars_bound_at_or_above(ty::INNERMOST) + } + + #[instrument(level = "trace")] + fn has_type_flags(&self, flags: TypeFlags) -> bool { + self.visit_with(&mut HasTypeFlagsVisitor { flags }).break_value() == Some(FoundFlags) + } + fn has_projections(&self) -> bool { + self.has_type_flags(TypeFlags::HAS_PROJECTION) + } + fn has_opaque_types(&self) -> bool { + self.has_type_flags(TypeFlags::HAS_TY_OPAQUE) + } + fn references_error(&self) -> bool { + self.has_type_flags(TypeFlags::HAS_ERROR) + } + fn error_reported(&self) -> Option<ErrorGuaranteed> { + if self.references_error() { + Some(ErrorGuaranteed::unchecked_claim_error_was_emitted()) + } else { + None + } + } + fn has_param_types_or_consts(&self) -> bool { + self.has_type_flags(TypeFlags::HAS_TY_PARAM | TypeFlags::HAS_CT_PARAM) + } + fn has_infer_regions(&self) -> bool { + self.has_type_flags(TypeFlags::HAS_RE_INFER) + } + fn has_infer_types(&self) -> bool { + self.has_type_flags(TypeFlags::HAS_TY_INFER) + } + fn has_infer_types_or_consts(&self) -> bool { + self.has_type_flags(TypeFlags::HAS_TY_INFER | TypeFlags::HAS_CT_INFER) + } + fn needs_infer(&self) -> bool { + self.has_type_flags(TypeFlags::NEEDS_INFER) + } + fn has_placeholders(&self) -> bool { + self.has_type_flags( + TypeFlags::HAS_RE_PLACEHOLDER + | TypeFlags::HAS_TY_PLACEHOLDER + | TypeFlags::HAS_CT_PLACEHOLDER, + ) + } + fn needs_subst(&self) -> bool { + self.has_type_flags(TypeFlags::NEEDS_SUBST) + } + /// "Free" regions in this context means that it has any region + /// that is not (a) erased or (b) late-bound. + fn has_free_regions(&self) -> bool { + self.has_type_flags(TypeFlags::HAS_FREE_REGIONS) + } + + fn has_erased_regions(&self) -> bool { + self.has_type_flags(TypeFlags::HAS_RE_ERASED) + } + + /// True if there are any un-erased free regions. + fn has_erasable_regions(&self) -> bool { + self.has_type_flags(TypeFlags::HAS_FREE_REGIONS) + } + + /// Indicates whether this value references only 'global' + /// generic parameters that are the same regardless of what fn we are + /// in. This is used for caching. + fn is_global(&self) -> bool { + !self.has_type_flags(TypeFlags::HAS_FREE_LOCAL_NAMES) + } + + /// True if there are any late-bound regions + fn has_late_bound_regions(&self) -> bool { + self.has_type_flags(TypeFlags::HAS_RE_LATE_BOUND) + } + + /// Indicates whether this value still has parameters/placeholders/inference variables + /// which could be replaced later, in a way that would change the results of `impl` + /// specialization. + fn still_further_specializable(&self) -> bool { + self.has_type_flags(TypeFlags::STILL_FURTHER_SPECIALIZABLE) + } +} + +pub trait TypeSuperVisitable<'tcx>: TypeVisitable<'tcx> { + /// Provides a default visit for a type of interest. This should only be + /// called within `TypeVisitor` methods, when a non-custom traversal is + /// desired for the value of the type of interest passed to that method. + /// For example, in `MyVisitor::visit_ty(ty)`, it is valid to call + /// `ty.super_visit_with(self)`, but any other visiting should be done + /// with `xyz.visit_with(self)`. + fn super_visit_with<V: TypeVisitor<'tcx>>(&self, visitor: &mut V) -> ControlFlow<V::BreakTy>; +} + +/// This trait is implemented for every visiting traversal. There is a visit +/// method defined for every type of interest. Each such method has a default +/// that recurses into the type's fields in a non-custom fashion. +pub trait TypeVisitor<'tcx>: Sized { + type BreakTy = !; + + fn visit_binder<T: TypeVisitable<'tcx>>( + &mut self, + t: &Binder<'tcx, T>, + ) -> ControlFlow<Self::BreakTy> { + t.super_visit_with(self) + } + + fn visit_ty(&mut self, t: Ty<'tcx>) -> ControlFlow<Self::BreakTy> { + t.super_visit_with(self) + } + + fn visit_region(&mut self, r: ty::Region<'tcx>) -> ControlFlow<Self::BreakTy> { + r.super_visit_with(self) + } + + fn visit_const(&mut self, c: ty::Const<'tcx>) -> ControlFlow<Self::BreakTy> { + c.super_visit_with(self) + } + + fn visit_unevaluated(&mut self, uv: ty::Unevaluated<'tcx>) -> ControlFlow<Self::BreakTy> { + uv.super_visit_with(self) + } + + fn visit_predicate(&mut self, p: ty::Predicate<'tcx>) -> ControlFlow<Self::BreakTy> { + p.super_visit_with(self) + } + + fn visit_mir_const(&mut self, c: mir::ConstantKind<'tcx>) -> ControlFlow<Self::BreakTy> { + c.super_visit_with(self) + } +} + +/////////////////////////////////////////////////////////////////////////// +// Region folder + +impl<'tcx> TyCtxt<'tcx> { + /// Invoke `callback` on every region appearing free in `value`. + pub fn for_each_free_region( + self, + value: &impl TypeVisitable<'tcx>, + mut callback: impl FnMut(ty::Region<'tcx>), + ) { + self.any_free_region_meets(value, |r| { + callback(r); + false + }); + } + + /// Returns `true` if `callback` returns true for every region appearing free in `value`. + pub fn all_free_regions_meet( + self, + value: &impl TypeVisitable<'tcx>, + mut callback: impl FnMut(ty::Region<'tcx>) -> bool, + ) -> bool { + !self.any_free_region_meets(value, |r| !callback(r)) + } + + /// Returns `true` if `callback` returns true for some region appearing free in `value`. + pub fn any_free_region_meets( + self, + value: &impl TypeVisitable<'tcx>, + callback: impl FnMut(ty::Region<'tcx>) -> bool, + ) -> bool { + struct RegionVisitor<F> { + /// The index of a binder *just outside* the things we have + /// traversed. If we encounter a bound region bound by this + /// binder or one outer to it, it appears free. Example: + /// + /// ```ignore (illustrative) + /// for<'a> fn(for<'b> fn(), T) + /// // ^ ^ ^ ^ + /// // | | | | here, would be shifted in 1 + /// // | | | here, would be shifted in 2 + /// // | | here, would be `INNERMOST` shifted in by 1 + /// // | here, initially, binder would be `INNERMOST` + /// ``` + /// + /// You see that, initially, *any* bound value is free, + /// because we've not traversed any binders. As we pass + /// through a binder, we shift the `outer_index` by 1 to + /// account for the new binder that encloses us. + outer_index: ty::DebruijnIndex, + callback: F, + } + + impl<'tcx, F> TypeVisitor<'tcx> for RegionVisitor<F> + where + F: FnMut(ty::Region<'tcx>) -> bool, + { + type BreakTy = (); + + fn visit_binder<T: TypeVisitable<'tcx>>( + &mut self, + t: &Binder<'tcx, T>, + ) -> ControlFlow<Self::BreakTy> { + self.outer_index.shift_in(1); + let result = t.super_visit_with(self); + self.outer_index.shift_out(1); + result + } + + fn visit_region(&mut self, r: ty::Region<'tcx>) -> ControlFlow<Self::BreakTy> { + match *r { + ty::ReLateBound(debruijn, _) if debruijn < self.outer_index => { + ControlFlow::CONTINUE + } + _ => { + if (self.callback)(r) { + ControlFlow::BREAK + } else { + ControlFlow::CONTINUE + } + } + } + } + + fn visit_ty(&mut self, ty: Ty<'tcx>) -> ControlFlow<Self::BreakTy> { + // We're only interested in types involving regions + if ty.flags().intersects(TypeFlags::HAS_FREE_REGIONS) { + ty.super_visit_with(self) + } else { + ControlFlow::CONTINUE + } + } + } + + value.visit_with(&mut RegionVisitor { outer_index: ty::INNERMOST, callback }).is_break() + } + + /// Returns a set of all late-bound regions that are constrained + /// by `value`, meaning that if we instantiate those LBR with + /// variables and equate `value` with something else, those + /// variables will also be equated. + pub fn collect_constrained_late_bound_regions<T>( + self, + value: &Binder<'tcx, T>, + ) -> FxHashSet<ty::BoundRegionKind> + where + T: TypeVisitable<'tcx>, + { + self.collect_late_bound_regions(value, true) + } + + /// Returns a set of all late-bound regions that appear in `value` anywhere. + pub fn collect_referenced_late_bound_regions<T>( + self, + value: &Binder<'tcx, T>, + ) -> FxHashSet<ty::BoundRegionKind> + where + T: TypeVisitable<'tcx>, + { + self.collect_late_bound_regions(value, false) + } + + fn collect_late_bound_regions<T>( + self, + value: &Binder<'tcx, T>, + just_constraint: bool, + ) -> FxHashSet<ty::BoundRegionKind> + where + T: TypeVisitable<'tcx>, + { + let mut collector = LateBoundRegionsCollector::new(just_constraint); + let result = value.as_ref().skip_binder().visit_with(&mut collector); + assert!(result.is_continue()); // should never have stopped early + collector.regions + } +} + +pub struct ValidateBoundVars<'tcx> { + bound_vars: &'tcx ty::List<ty::BoundVariableKind>, + binder_index: ty::DebruijnIndex, + // We may encounter the same variable at different levels of binding, so + // this can't just be `Ty` + visited: SsoHashSet<(ty::DebruijnIndex, Ty<'tcx>)>, +} + +impl<'tcx> ValidateBoundVars<'tcx> { + pub fn new(bound_vars: &'tcx ty::List<ty::BoundVariableKind>) -> Self { + ValidateBoundVars { + bound_vars, + binder_index: ty::INNERMOST, + visited: SsoHashSet::default(), + } + } +} + +impl<'tcx> TypeVisitor<'tcx> for ValidateBoundVars<'tcx> { + type BreakTy = (); + + fn visit_binder<T: TypeVisitable<'tcx>>( + &mut self, + t: &Binder<'tcx, T>, + ) -> ControlFlow<Self::BreakTy> { + self.binder_index.shift_in(1); + let result = t.super_visit_with(self); + self.binder_index.shift_out(1); + result + } + + fn visit_ty(&mut self, t: Ty<'tcx>) -> ControlFlow<Self::BreakTy> { + if t.outer_exclusive_binder() < self.binder_index + || !self.visited.insert((self.binder_index, t)) + { + return ControlFlow::BREAK; + } + match *t.kind() { + ty::Bound(debruijn, bound_ty) if debruijn == self.binder_index => { + if self.bound_vars.len() <= bound_ty.var.as_usize() { + bug!("Not enough bound vars: {:?} not found in {:?}", t, self.bound_vars); + } + let list_var = self.bound_vars[bound_ty.var.as_usize()]; + match list_var { + ty::BoundVariableKind::Ty(kind) => { + if kind != bound_ty.kind { + bug!( + "Mismatched type kinds: {:?} doesn't var in list {:?}", + bound_ty.kind, + list_var + ); + } + } + _ => { + bug!("Mismatched bound variable kinds! Expected type, found {:?}", list_var) + } + } + } + + _ => (), + }; + + t.super_visit_with(self) + } + + fn visit_region(&mut self, r: ty::Region<'tcx>) -> ControlFlow<Self::BreakTy> { + match *r { + ty::ReLateBound(index, br) if index == self.binder_index => { + if self.bound_vars.len() <= br.var.as_usize() { + bug!("Not enough bound vars: {:?} not found in {:?}", br, self.bound_vars); + } + let list_var = self.bound_vars[br.var.as_usize()]; + match list_var { + ty::BoundVariableKind::Region(kind) => { + if kind != br.kind { + bug!( + "Mismatched region kinds: {:?} doesn't match var ({:?}) in list ({:?})", + br.kind, + list_var, + self.bound_vars + ); + } + } + _ => bug!( + "Mismatched bound variable kinds! Expected region, found {:?}", + list_var + ), + } + } + + _ => (), + }; + + r.super_visit_with(self) + } +} + +#[derive(Debug, PartialEq, Eq, Copy, Clone)] +struct FoundEscapingVars; + +/// An "escaping var" is a bound var whose binder is not part of `t`. A bound var can be a +/// bound region or a bound type. +/// +/// So, for example, consider a type like the following, which has two binders: +/// +/// for<'a> fn(x: for<'b> fn(&'a isize, &'b isize)) +/// ^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ outer scope +/// ^~~~~~~~~~~~~~~~~~~~~~~~~~~~ inner scope +/// +/// This type has *bound regions* (`'a`, `'b`), but it does not have escaping regions, because the +/// binders of both `'a` and `'b` are part of the type itself. However, if we consider the *inner +/// fn type*, that type has an escaping region: `'a`. +/// +/// Note that what I'm calling an "escaping var" is often just called a "free var". However, +/// we already use the term "free var". It refers to the regions or types that we use to represent +/// bound regions or type params on a fn definition while we are type checking its body. +/// +/// To clarify, conceptually there is no particular difference between +/// an "escaping" var and a "free" var. However, there is a big +/// difference in practice. Basically, when "entering" a binding +/// level, one is generally required to do some sort of processing to +/// a bound var, such as replacing it with a fresh/placeholder +/// var, or making an entry in the environment to represent the +/// scope to which it is attached, etc. An escaping var represents +/// a bound var for which this processing has not yet been done. +struct HasEscapingVarsVisitor { + /// Anything bound by `outer_index` or "above" is escaping. + outer_index: ty::DebruijnIndex, +} + +impl<'tcx> TypeVisitor<'tcx> for HasEscapingVarsVisitor { + type BreakTy = FoundEscapingVars; + + fn visit_binder<T: TypeVisitable<'tcx>>( + &mut self, + t: &Binder<'tcx, T>, + ) -> ControlFlow<Self::BreakTy> { + self.outer_index.shift_in(1); + let result = t.super_visit_with(self); + self.outer_index.shift_out(1); + result + } + + #[inline] + fn visit_ty(&mut self, t: Ty<'tcx>) -> ControlFlow<Self::BreakTy> { + // If the outer-exclusive-binder is *strictly greater* than + // `outer_index`, that means that `t` contains some content + // bound at `outer_index` or above (because + // `outer_exclusive_binder` is always 1 higher than the + // content in `t`). Therefore, `t` has some escaping vars. + if t.outer_exclusive_binder() > self.outer_index { + ControlFlow::Break(FoundEscapingVars) + } else { + ControlFlow::CONTINUE + } + } + + #[inline] + fn visit_region(&mut self, r: ty::Region<'tcx>) -> ControlFlow<Self::BreakTy> { + // If the region is bound by `outer_index` or anything outside + // of outer index, then it escapes the binders we have + // visited. + if r.bound_at_or_above_binder(self.outer_index) { + ControlFlow::Break(FoundEscapingVars) + } else { + ControlFlow::CONTINUE + } + } + + fn visit_const(&mut self, ct: ty::Const<'tcx>) -> ControlFlow<Self::BreakTy> { + // we don't have a `visit_infer_const` callback, so we have to + // hook in here to catch this case (annoying...), but + // otherwise we do want to remember to visit the rest of the + // const, as it has types/regions embedded in a lot of other + // places. + match ct.kind() { + ty::ConstKind::Bound(debruijn, _) if debruijn >= self.outer_index => { + ControlFlow::Break(FoundEscapingVars) + } + _ => ct.super_visit_with(self), + } + } + + #[inline] + fn visit_predicate(&mut self, predicate: ty::Predicate<'tcx>) -> ControlFlow<Self::BreakTy> { + if predicate.outer_exclusive_binder() > self.outer_index { + ControlFlow::Break(FoundEscapingVars) + } else { + ControlFlow::CONTINUE + } + } +} + +#[derive(Debug, PartialEq, Eq, Copy, Clone)] +struct FoundFlags; + +// FIXME: Optimize for checking for infer flags +struct HasTypeFlagsVisitor { + flags: ty::TypeFlags, +} + +impl std::fmt::Debug for HasTypeFlagsVisitor { + fn fmt(&self, fmt: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { + self.flags.fmt(fmt) + } +} + +impl<'tcx> TypeVisitor<'tcx> for HasTypeFlagsVisitor { + type BreakTy = FoundFlags; + + #[inline] + #[instrument(skip(self), level = "trace")] + fn visit_ty(&mut self, t: Ty<'tcx>) -> ControlFlow<Self::BreakTy> { + let flags = t.flags(); + trace!(t.flags=?t.flags()); + if flags.intersects(self.flags) { + ControlFlow::Break(FoundFlags) + } else { + ControlFlow::CONTINUE + } + } + + #[inline] + #[instrument(skip(self), level = "trace")] + fn visit_region(&mut self, r: ty::Region<'tcx>) -> ControlFlow<Self::BreakTy> { + let flags = r.type_flags(); + trace!(r.flags=?flags); + if flags.intersects(self.flags) { + ControlFlow::Break(FoundFlags) + } else { + ControlFlow::CONTINUE + } + } + + #[inline] + #[instrument(level = "trace")] + fn visit_const(&mut self, c: ty::Const<'tcx>) -> ControlFlow<Self::BreakTy> { + let flags = FlagComputation::for_const(c); + trace!(r.flags=?flags); + if flags.intersects(self.flags) { + ControlFlow::Break(FoundFlags) + } else { + ControlFlow::CONTINUE + } + } + + #[inline] + #[instrument(level = "trace")] + fn visit_unevaluated(&mut self, uv: ty::Unevaluated<'tcx>) -> ControlFlow<Self::BreakTy> { + let flags = FlagComputation::for_unevaluated_const(uv); + trace!(r.flags=?flags); + if flags.intersects(self.flags) { + ControlFlow::Break(FoundFlags) + } else { + ControlFlow::CONTINUE + } + } + + #[inline] + #[instrument(level = "trace")] + fn visit_predicate(&mut self, predicate: ty::Predicate<'tcx>) -> ControlFlow<Self::BreakTy> { + debug!( + "HasTypeFlagsVisitor: predicate={:?} predicate.flags={:?} self.flags={:?}", + predicate, + predicate.flags(), + self.flags + ); + if predicate.flags().intersects(self.flags) { + ControlFlow::Break(FoundFlags) + } else { + ControlFlow::CONTINUE + } + } +} + +/// Collects all the late-bound regions at the innermost binding level +/// into a hash set. +struct LateBoundRegionsCollector { + current_index: ty::DebruijnIndex, + regions: FxHashSet<ty::BoundRegionKind>, + + /// `true` if we only want regions that are known to be + /// "constrained" when you equate this type with another type. In + /// particular, if you have e.g., `&'a u32` and `&'b u32`, equating + /// them constraints `'a == 'b`. But if you have `<&'a u32 as + /// Trait>::Foo` and `<&'b u32 as Trait>::Foo`, normalizing those + /// types may mean that `'a` and `'b` don't appear in the results, + /// so they are not considered *constrained*. + just_constrained: bool, +} + +impl LateBoundRegionsCollector { + fn new(just_constrained: bool) -> Self { + LateBoundRegionsCollector { + current_index: ty::INNERMOST, + regions: Default::default(), + just_constrained, + } + } +} + +impl<'tcx> TypeVisitor<'tcx> for LateBoundRegionsCollector { + fn visit_binder<T: TypeVisitable<'tcx>>( + &mut self, + t: &Binder<'tcx, T>, + ) -> ControlFlow<Self::BreakTy> { + self.current_index.shift_in(1); + let result = t.super_visit_with(self); + self.current_index.shift_out(1); + result + } + + fn visit_ty(&mut self, t: Ty<'tcx>) -> ControlFlow<Self::BreakTy> { + // if we are only looking for "constrained" region, we have to + // ignore the inputs to a projection, as they may not appear + // in the normalized form + if self.just_constrained { + if let ty::Projection(..) = t.kind() { + return ControlFlow::CONTINUE; + } + } + + t.super_visit_with(self) + } + + fn visit_const(&mut self, c: ty::Const<'tcx>) -> ControlFlow<Self::BreakTy> { + // if we are only looking for "constrained" region, we have to + // ignore the inputs of an unevaluated const, as they may not appear + // in the normalized form + if self.just_constrained { + if let ty::ConstKind::Unevaluated(..) = c.kind() { + return ControlFlow::CONTINUE; + } + } + + c.super_visit_with(self) + } + + fn visit_region(&mut self, r: ty::Region<'tcx>) -> ControlFlow<Self::BreakTy> { + if let ty::ReLateBound(debruijn, br) = *r { + if debruijn == self.current_index { + self.regions.insert(br.kind); + } + } + ControlFlow::CONTINUE + } +} + +/// Finds the max universe present +pub struct MaxUniverse { + max_universe: ty::UniverseIndex, +} + +impl MaxUniverse { + pub fn new() -> Self { + MaxUniverse { max_universe: ty::UniverseIndex::ROOT } + } + + pub fn max_universe(self) -> ty::UniverseIndex { + self.max_universe + } +} + +impl<'tcx> TypeVisitor<'tcx> for MaxUniverse { + fn visit_ty(&mut self, t: Ty<'tcx>) -> ControlFlow<Self::BreakTy> { + if let ty::Placeholder(placeholder) = t.kind() { + self.max_universe = ty::UniverseIndex::from_u32( + self.max_universe.as_u32().max(placeholder.universe.as_u32()), + ); + } + + t.super_visit_with(self) + } + + fn visit_const(&mut self, c: ty::consts::Const<'tcx>) -> ControlFlow<Self::BreakTy> { + if let ty::ConstKind::Placeholder(placeholder) = c.kind() { + self.max_universe = ty::UniverseIndex::from_u32( + self.max_universe.as_u32().max(placeholder.universe.as_u32()), + ); + } + + c.super_visit_with(self) + } + + fn visit_region(&mut self, r: ty::Region<'tcx>) -> ControlFlow<Self::BreakTy> { + if let ty::RePlaceholder(placeholder) = *r { + self.max_universe = ty::UniverseIndex::from_u32( + self.max_universe.as_u32().max(placeholder.universe.as_u32()), + ); + } + + ControlFlow::CONTINUE + } +} diff --git a/compiler/rustc_mir_build/src/build/expr/as_rvalue.rs b/compiler/rustc_mir_build/src/build/expr/as_rvalue.rs index 8e87ecd27d2..e3a383f86a7 100644 --- a/compiler/rustc_mir_build/src/build/expr/as_rvalue.rs +++ b/compiler/rustc_mir_build/src/build/expr/as_rvalue.rs @@ -1,6 +1,7 @@ //! See docs in `build/expr/mod.rs`. use rustc_index::vec::Idx; +use rustc_middle::ty::util::IntTypeExt; use crate::build::expr::as_place::PlaceBase; use crate::build::expr::category::{Category, RvalueFunc}; @@ -190,7 +191,30 @@ impl<'a, 'tcx> Builder<'a, 'tcx> { } ExprKind::Cast { source } => { let source = &this.thir[source]; - let from_ty = CastTy::from_ty(source.ty); + + // Casting an enum to an integer is equivalent to computing the discriminant and casting the + // discriminant. Previously every backend had to repeat the logic for this operation. Now we + // create all the steps directly in MIR with operations all backends need to support anyway. + let (source, ty) = if let ty::Adt(adt_def, ..) = source.ty.kind() && adt_def.is_enum() { + let discr_ty = adt_def.repr().discr_type().to_ty(this.tcx); + let place = unpack!(block = this.as_place(block, source)); + let discr = this.temp(discr_ty, source.span); + this.cfg.push_assign( + block, + source_info, + discr, + Rvalue::Discriminant(place), + ); + + (Operand::Move(discr), discr_ty) + } else { + let ty = source.ty; + let source = unpack!( + block = this.as_operand(block, scope, source, None, NeedsTemporary::No) + ); + (source, ty) + }; + let from_ty = CastTy::from_ty(ty); let cast_ty = CastTy::from_ty(expr.ty); let cast_kind = match (from_ty, cast_ty) { (Some(CastTy::Ptr(_) | CastTy::FnPtr), Some(CastTy::Int(_))) => { @@ -201,9 +225,6 @@ impl<'a, 'tcx> Builder<'a, 'tcx> { } (_, _) => CastKind::Misc, }; - let source = unpack!( - block = this.as_operand(block, scope, source, None, NeedsTemporary::No) - ); block.and(Rvalue::Cast(cast_kind, source, expr.ty)) } ExprKind::Pointer { cast, source } => { diff --git a/compiler/rustc_mir_build/src/build/mod.rs b/compiler/rustc_mir_build/src/build/mod.rs index cdacf3ad892..e6d42af9817 100644 --- a/compiler/rustc_mir_build/src/build/mod.rs +++ b/compiler/rustc_mir_build/src/build/mod.rs @@ -20,7 +20,7 @@ use rustc_middle::mir::interpret::Scalar; use rustc_middle::mir::*; use rustc_middle::thir::{BindingMode, Expr, ExprId, LintLevel, LocalVarId, PatKind, Thir}; use rustc_middle::ty::subst::Subst; -use rustc_middle::ty::{self, Ty, TyCtxt, TypeFoldable, TypeckResults}; +use rustc_middle::ty::{self, Ty, TyCtxt, TypeVisitable, TypeckResults}; use rustc_span::symbol::sym; use rustc_span::Span; use rustc_span::Symbol; @@ -997,7 +997,7 @@ impl<'a, 'tcx> Builder<'a, 'tcx> { continue; }; let pat = match tcx.hir().get(arg.pat.hir_id) { - Node::Pat(pat) | Node::Binding(pat) => pat, + Node::Pat(pat) => pat, node => bug!("pattern became {:?}", node), }; let pattern = pat_from_hir(tcx, self.param_env, self.typeck_results, pat); diff --git a/compiler/rustc_mir_build/src/thir/cx/expr.rs b/compiler/rustc_mir_build/src/thir/cx/expr.rs index 08b66d0abc7..4bc3d216a40 100644 --- a/compiler/rustc_mir_build/src/thir/cx/expr.rs +++ b/compiler/rustc_mir_build/src/thir/cx/expr.rs @@ -32,13 +32,14 @@ impl<'tcx> Cx<'tcx> { exprs.iter().map(|expr| self.mirror_expr_inner(expr)).collect() } + #[instrument(level = "trace", skip(self, hir_expr))] pub(super) fn mirror_expr_inner(&mut self, hir_expr: &'tcx hir::Expr<'tcx>) -> ExprId { let temp_lifetime = self.rvalue_scopes.temporary_scope(self.region_scope_tree, hir_expr.hir_id.local_id); let expr_scope = region::Scope { id: hir_expr.hir_id.local_id, data: region::ScopeData::Node }; - debug!("Expr::make_mirror(): id={}, span={:?}", hir_expr.hir_id, hir_expr.span); + trace!(?hir_expr.hir_id, ?hir_expr.span); let mut expr = self.make_mirror_unadjusted(hir_expr); @@ -49,7 +50,7 @@ impl<'tcx> Cx<'tcx> { // Now apply adjustments, if any. for adjustment in self.typeck_results.expr_adjustments(hir_expr) { - debug!("make_mirror: expr={:?} applying adjustment={:?}", expr, adjustment); + trace!(?expr, ?adjustment); let span = expr.span; expr = self.apply_adjustment(hir_expr, expr, adjustment, adjustment_span.unwrap_or(span)); diff --git a/compiler/rustc_mir_build/src/thir/cx/mod.rs b/compiler/rustc_mir_build/src/thir/cx/mod.rs index d853a5e9ee7..35a0afd6813 100644 --- a/compiler/rustc_mir_build/src/thir/cx/mod.rs +++ b/compiler/rustc_mir_build/src/thir/cx/mod.rs @@ -5,7 +5,6 @@ use crate::thir::pattern::pat_from_hir; use crate::thir::util::UserAnnotatedTyHelpers; -use rustc_ast as ast; use rustc_data_structures::steal::Steal; use rustc_errors::ErrorGuaranteed; use rustc_hir as hir; @@ -13,10 +12,8 @@ use rustc_hir::def_id::{DefId, LocalDefId}; use rustc_hir::HirId; use rustc_hir::Node; use rustc_middle::middle::region; -use rustc_middle::mir::interpret::{LitToConstError, LitToConstInput}; -use rustc_middle::mir::ConstantKind; use rustc_middle::thir::*; -use rustc_middle::ty::{self, RvalueScopes, Ty, TyCtxt}; +use rustc_middle::ty::{self, RvalueScopes, TyCtxt}; use rustc_span::Span; pub(crate) fn thir_body<'tcx>( @@ -80,28 +77,10 @@ impl<'tcx> Cx<'tcx> { } } - #[instrument(skip(self), level = "debug")] - pub(crate) fn const_eval_literal( - &mut self, - lit: &'tcx ast::LitKind, - ty: Ty<'tcx>, - sp: Span, - neg: bool, - ) -> ConstantKind<'tcx> { - match self.tcx.at(sp).lit_to_mir_constant(LitToConstInput { lit, ty, neg }) { - Ok(c) => c, - Err(LitToConstError::Reported) => { - // create a dummy value and continue compiling - ConstantKind::Ty(self.tcx.const_error(ty)) - } - Err(LitToConstError::TypeError) => bug!("const_eval_literal: had type error"), - } - } - #[tracing::instrument(level = "debug", skip(self))] pub(crate) fn pattern_from_hir(&mut self, p: &hir::Pat<'_>) -> Pat<'tcx> { let p = match self.tcx.hir().get(p.hir_id) { - Node::Pat(p) | Node::Binding(p) => p, + Node::Pat(p) => p, node => bug!("pattern became {:?}", node), }; pat_from_hir(self.tcx, self.param_env, self.typeck_results(), p) diff --git a/compiler/rustc_mir_build/src/thir/pattern/const_to_pat.rs b/compiler/rustc_mir_build/src/thir/pattern/const_to_pat.rs index 845be2ab264..f22f3f61a01 100644 --- a/compiler/rustc_mir_build/src/thir/pattern/const_to_pat.rs +++ b/compiler/rustc_mir_build/src/thir/pattern/const_to_pat.rs @@ -550,7 +550,7 @@ impl<'a, 'tcx> ConstToPat<'a, 'tcx> { id, span, |lint| { - lint.build(&msg).emit(); + lint.build(msg).emit(); }, ); } diff --git a/compiler/rustc_mir_dataflow/src/framework/lattice.rs b/compiler/rustc_mir_dataflow/src/framework/lattice.rs index 9a462f6e1a4..d6b89eb8227 100644 --- a/compiler/rustc_mir_dataflow/src/framework/lattice.rs +++ b/compiler/rustc_mir_dataflow/src/framework/lattice.rs @@ -199,14 +199,16 @@ impl<T: JoinSemiLattice> MeetSemiLattice for Dual<T> { } /// Extends a type `T` with top and bottom elements to make it a partially ordered set in which no -/// value of `T` is comparable with any other. A flat set has the following [Hasse diagram]: +/// value of `T` is comparable with any other. +/// +/// A flat set has the following [Hasse diagram]: /// /// ```text -/// top -/// / / \ \ +/// top +/// / ... / / \ \ ... \ /// all possible values of `T` -/// \ \ / / -/// bottom +/// \ ... \ \ / / ... / +/// bottom /// ``` /// /// [Hasse diagram]: https://en.wikipedia.org/wiki/Hasse_diagram diff --git a/compiler/rustc_mir_dataflow/src/impls/init_locals.rs b/compiler/rustc_mir_dataflow/src/impls/init_locals.rs index 584ab9718ed..83ce4c44b71 100644 --- a/compiler/rustc_mir_dataflow/src/impls/init_locals.rs +++ b/compiler/rustc_mir_dataflow/src/impls/init_locals.rs @@ -81,7 +81,7 @@ where // deinitialized, although clearly it is only partially deinitialized. This analysis is not // actually used anywhere at the moment, so this is not critical, but this does need to be fixed // before it starts being used again. - fn visit_local(&mut self, &local: &Local, context: PlaceContext, _: Location) { + fn visit_local(&mut self, local: Local, context: PlaceContext, _: Location) { use rustc_middle::mir::visit::{MutatingUseContext, NonMutatingUseContext, NonUseContext}; match context { // These are handled specially in `call_return_effect` and `yield_resume_effect`. diff --git a/compiler/rustc_mir_dataflow/src/impls/liveness.rs b/compiler/rustc_mir_dataflow/src/impls/liveness.rs index 35febb5d330..e64136928cc 100644 --- a/compiler/rustc_mir_dataflow/src/impls/liveness.rs +++ b/compiler/rustc_mir_dataflow/src/impls/liveness.rs @@ -111,7 +111,7 @@ where } } - fn visit_local(&mut self, &local: &Local, context: PlaceContext, _: Location) { + fn visit_local(&mut self, local: Local, context: PlaceContext, _: Location) { // Because we do not call `super_place` above, `visit_local` is only called for locals that // do not appear as part of a `Place` in the MIR. This handles cases like the implicit use // of the return place in a `Return` terminator or the index in an `Index` projection. diff --git a/compiler/rustc_mir_dataflow/src/impls/storage_liveness.rs b/compiler/rustc_mir_dataflow/src/impls/storage_liveness.rs index 33d29418147..eae9313b771 100644 --- a/compiler/rustc_mir_dataflow/src/impls/storage_liveness.rs +++ b/compiler/rustc_mir_dataflow/src/impls/storage_liveness.rs @@ -288,12 +288,12 @@ impl<'a, 'mir, 'tcx, T> Visitor<'tcx> for MoveVisitor<'a, 'mir, 'tcx, T> where T: GenKill<Local>, { - fn visit_local(&mut self, local: &Local, context: PlaceContext, loc: Location) { + fn visit_local(&mut self, local: Local, context: PlaceContext, loc: Location) { if PlaceContext::NonMutatingUse(NonMutatingUseContext::Move) == context { let mut borrowed_locals = self.borrowed_locals.borrow_mut(); borrowed_locals.seek_before_primary_effect(loc); - if !borrowed_locals.contains(*local) { - self.trans.kill(*local); + if !borrowed_locals.contains(local) { + self.trans.kill(local); } } } diff --git a/compiler/rustc_mir_transform/src/abort_unwinding_calls.rs b/compiler/rustc_mir_transform/src/abort_unwinding_calls.rs index 11980382ffd..2c8389e532d 100644 --- a/compiler/rustc_mir_transform/src/abort_unwinding_calls.rs +++ b/compiler/rustc_mir_transform/src/abort_unwinding_calls.rs @@ -1,6 +1,5 @@ use crate::MirPass; use rustc_ast::InlineAsmOptions; -use rustc_hir::def::DefKind; use rustc_middle::mir::*; use rustc_middle::ty::layout; use rustc_middle::ty::{self, TyCtxt}; @@ -31,11 +30,7 @@ impl<'tcx> MirPass<'tcx> for AbortUnwindingCalls { // We don't simplify the MIR of constants at this time because that // namely results in a cyclic query when we call `tcx.type_of` below. - let is_function = match kind { - DefKind::Fn | DefKind::AssocFn | DefKind::Ctor(..) => true, - _ => tcx.is_closure(def_id), - }; - if !is_function { + if !kind.is_fn_like() { return; } diff --git a/compiler/rustc_mir_transform/src/check_const_item_mutation.rs b/compiler/rustc_mir_transform/src/check_const_item_mutation.rs index 097a6186cd5..8838b14c53a 100644 --- a/compiler/rustc_mir_transform/src/check_const_item_mutation.rs +++ b/compiler/rustc_mir_transform/src/check_const_item_mutation.rs @@ -1,5 +1,4 @@ -use rustc_errors::DiagnosticBuilder; -use rustc_middle::lint::LintDiagnosticBuilder; +use rustc_errors::{DiagnosticBuilder, LintDiagnosticBuilder}; use rustc_middle::mir::visit::Visitor; use rustc_middle::mir::*; use rustc_middle::ty::TyCtxt; diff --git a/compiler/rustc_mir_transform/src/const_debuginfo.rs b/compiler/rustc_mir_transform/src/const_debuginfo.rs index 8944ebed9a7..48aea61b191 100644 --- a/compiler/rustc_mir_transform/src/const_debuginfo.rs +++ b/compiler/rustc_mir_transform/src/const_debuginfo.rs @@ -88,12 +88,12 @@ fn find_optimization_oportunities<'tcx>(body: &Body<'tcx>) -> Vec<(Local, Consta } impl Visitor<'_> for LocalUseVisitor { - fn visit_local(&mut self, local: &Local, context: PlaceContext, location: Location) { + fn visit_local(&mut self, local: Local, context: PlaceContext, location: Location) { if context.is_mutating_use() { - self.local_mutating_uses[*local] = self.local_mutating_uses[*local].saturating_add(1); + self.local_mutating_uses[local] = self.local_mutating_uses[local].saturating_add(1); if context.is_place_assignment() { - self.local_assignment_locations[*local] = Some(location); + self.local_assignment_locations[local] = Some(location); } } } diff --git a/compiler/rustc_mir_transform/src/const_prop.rs b/compiler/rustc_mir_transform/src/const_prop.rs index 412a5b4fc91..070e563f396 100644 --- a/compiler/rustc_mir_transform/src/const_prop.rs +++ b/compiler/rustc_mir_transform/src/const_prop.rs @@ -19,7 +19,7 @@ use rustc_middle::mir::{ use rustc_middle::ty::layout::{LayoutError, LayoutOf, LayoutOfHelpers, TyAndLayout}; use rustc_middle::ty::subst::{InternalSubsts, Subst}; use rustc_middle::ty::{ - self, ConstKind, EarlyBinder, Instance, ParamEnv, Ty, TyCtxt, TypeFoldable, + self, ConstKind, EarlyBinder, Instance, ParamEnv, Ty, TyCtxt, TypeVisitable, }; use rustc_span::{def_id::DefId, Span}; use rustc_target::abi::{HasDataLayout, Size, TargetDataLayout}; @@ -882,7 +882,7 @@ impl CanConstProp { } impl Visitor<'_> for CanConstProp { - fn visit_local(&mut self, &local: &Local, context: PlaceContext, _: Location) { + fn visit_local(&mut self, local: Local, context: PlaceContext, _: Location) { use rustc_middle::mir::visit::PlaceContext::*; match context { // Projections are fine, because `&mut foo.x` will be caught by diff --git a/compiler/rustc_mir_transform/src/const_prop_lint.rs b/compiler/rustc_mir_transform/src/const_prop_lint.rs index 15ad13009e5..e3ab42d09ef 100644 --- a/compiler/rustc_mir_transform/src/const_prop_lint.rs +++ b/compiler/rustc_mir_transform/src/const_prop_lint.rs @@ -18,7 +18,8 @@ use rustc_middle::mir::{ use rustc_middle::ty::layout::{LayoutError, LayoutOf, LayoutOfHelpers, TyAndLayout}; use rustc_middle::ty::subst::{InternalSubsts, Subst}; use rustc_middle::ty::{ - self, ConstInt, ConstKind, EarlyBinder, Instance, ParamEnv, ScalarInt, Ty, TyCtxt, TypeFoldable, + self, ConstInt, ConstKind, EarlyBinder, Instance, ParamEnv, ScalarInt, Ty, TyCtxt, + TypeVisitable, }; use rustc_session::lint; use rustc_span::{def_id::DefId, Span}; @@ -773,7 +774,7 @@ impl CanConstProp { } impl Visitor<'_> for CanConstProp { - fn visit_local(&mut self, &local: &Local, context: PlaceContext, _: Location) { + fn visit_local(&mut self, local: Local, context: PlaceContext, _: Location) { use rustc_middle::mir::visit::PlaceContext::*; match context { // Projections are fine, because `&mut foo.x` will be caught by diff --git a/compiler/rustc_mir_transform/src/dead_store_elimination.rs b/compiler/rustc_mir_transform/src/dead_store_elimination.rs index 28f3790914b..c96497abf8f 100644 --- a/compiler/rustc_mir_transform/src/dead_store_elimination.rs +++ b/compiler/rustc_mir_transform/src/dead_store_elimination.rs @@ -66,7 +66,7 @@ pub fn eliminate<'tcx>(tcx: TyCtxt<'tcx>, body: &mut Body<'tcx>, borrowed: &BitS return; } - let bbs = body.basic_blocks_mut(); + let bbs = body.basic_blocks_local_decls_mut_and_var_debug_info_no_invalidate().0; for Location { block, statement_index } in patch { bbs[block].statements[statement_index].make_nop(); } diff --git a/compiler/rustc_mir_transform/src/deaggregator.rs b/compiler/rustc_mir_transform/src/deaggregator.rs index 616ba819982..01f490e23bf 100644 --- a/compiler/rustc_mir_transform/src/deaggregator.rs +++ b/compiler/rustc_mir_transform/src/deaggregator.rs @@ -11,7 +11,8 @@ impl<'tcx> MirPass<'tcx> for Deaggregator { } fn run_pass(&self, tcx: TyCtxt<'tcx>, body: &mut Body<'tcx>) { - let (basic_blocks, local_decls) = body.basic_blocks_and_local_decls_mut(); + let (basic_blocks, local_decls, _) = + body.basic_blocks_local_decls_mut_and_var_debug_info_no_invalidate(); let local_decls = &*local_decls; for bb in basic_blocks { bb.expand_statements(|stmt| { diff --git a/compiler/rustc_mir_transform/src/ffi_unwind_calls.rs b/compiler/rustc_mir_transform/src/ffi_unwind_calls.rs new file mode 100644 index 00000000000..7728fdaffb0 --- /dev/null +++ b/compiler/rustc_mir_transform/src/ffi_unwind_calls.rs @@ -0,0 +1,170 @@ +use rustc_hir::def_id::{CrateNum, LocalDefId, LOCAL_CRATE}; +use rustc_middle::mir::*; +use rustc_middle::ty::layout; +use rustc_middle::ty::query::Providers; +use rustc_middle::ty::{self, TyCtxt}; +use rustc_session::lint::builtin::FFI_UNWIND_CALLS; +use rustc_target::spec::abi::Abi; +use rustc_target::spec::PanicStrategy; + +fn abi_can_unwind(abi: Abi) -> bool { + use Abi::*; + match abi { + C { unwind } + | System { unwind } + | Cdecl { unwind } + | Stdcall { unwind } + | Fastcall { unwind } + | Vectorcall { unwind } + | Thiscall { unwind } + | Aapcs { unwind } + | Win64 { unwind } + | SysV64 { unwind } => unwind, + PtxKernel + | Msp430Interrupt + | X86Interrupt + | AmdGpuKernel + | EfiApi + | AvrInterrupt + | AvrNonBlockingInterrupt + | CCmseNonSecureCall + | Wasm + | RustIntrinsic + | PlatformIntrinsic + | Unadjusted => false, + Rust | RustCall | RustCold => true, + } +} + +// Check if the body of this def_id can possibly leak a foreign unwind into Rust code. +fn has_ffi_unwind_calls(tcx: TyCtxt<'_>, local_def_id: LocalDefId) -> bool { + debug!("has_ffi_unwind_calls({local_def_id:?})"); + + // Only perform check on functions because constants cannot call FFI functions. + let def_id = local_def_id.to_def_id(); + let kind = tcx.def_kind(def_id); + if !kind.is_fn_like() { + return false; + } + + let body = &*tcx.mir_built(ty::WithOptConstParam::unknown(local_def_id)).borrow(); + + let body_ty = tcx.type_of(def_id); + let body_abi = match body_ty.kind() { + ty::FnDef(..) => body_ty.fn_sig(tcx).abi(), + ty::Closure(..) => Abi::RustCall, + ty::Generator(..) => Abi::Rust, + _ => span_bug!(body.span, "unexpected body ty: {:?}", body_ty), + }; + let body_can_unwind = layout::fn_can_unwind(tcx, Some(def_id), body_abi); + + // Foreign unwinds cannot leak past functions that themselves cannot unwind. + if !body_can_unwind { + return false; + } + + let mut tainted = false; + + for block in body.basic_blocks() { + if block.is_cleanup { + continue; + } + let Some(terminator) = &block.terminator else { continue }; + let TerminatorKind::Call { func, .. } = &terminator.kind else { continue }; + + let ty = func.ty(body, tcx); + let sig = ty.fn_sig(tcx); + + // Rust calls cannot themselves create foreign unwinds. + if let Abi::Rust | Abi::RustCall | Abi::RustCold = sig.abi() { + continue; + }; + + let fn_def_id = match ty.kind() { + ty::FnPtr(_) => None, + &ty::FnDef(def_id, _) => { + // Rust calls cannot themselves create foreign unwinds. + if !tcx.is_foreign_item(def_id) { + continue; + } + Some(def_id) + } + _ => bug!("invalid callee of type {:?}", ty), + }; + + if layout::fn_can_unwind(tcx, fn_def_id, sig.abi()) && abi_can_unwind(sig.abi()) { + // We have detected a call that can possibly leak foreign unwind. + // + // Because the function body itself can unwind, we are not aborting this function call + // upon unwind, so this call can possibly leak foreign unwind into Rust code if the + // panic runtime linked is panic-abort. + + let lint_root = body.source_scopes[terminator.source_info.scope] + .local_data + .as_ref() + .assert_crate_local() + .lint_root; + let span = terminator.source_info.span; + + tcx.struct_span_lint_hir(FFI_UNWIND_CALLS, lint_root, span, |lint| { + let msg = match fn_def_id { + Some(_) => "call to foreign function with FFI-unwind ABI", + None => "call to function pointer with FFI-unwind ABI", + }; + let mut db = lint.build(msg); + db.span_label(span, msg); + db.emit(); + }); + + tainted = true; + } + } + + tainted +} + +fn required_panic_strategy(tcx: TyCtxt<'_>, cnum: CrateNum) -> Option<PanicStrategy> { + assert_eq!(cnum, LOCAL_CRATE); + + if tcx.is_panic_runtime(LOCAL_CRATE) { + return Some(tcx.sess.panic_strategy()); + } + + if tcx.sess.panic_strategy() == PanicStrategy::Abort { + return Some(PanicStrategy::Abort); + } + + for def_id in tcx.hir().body_owners() { + if tcx.has_ffi_unwind_calls(def_id) { + // Given that this crate is compiled in `-C panic=unwind`, the `AbortUnwindingCalls` + // MIR pass will not be run on FFI-unwind call sites, therefore a foreign exception + // can enter Rust through these sites. + // + // On the other hand, crates compiled with `-C panic=abort` expects that all Rust + // functions cannot unwind (whether it's caused by Rust panic or foreign exception), + // and this expectation mismatch can cause unsoundness (#96926). + // + // To address this issue, we enforce that if FFI-unwind calls are used in a crate + // compiled with `panic=unwind`, then the final panic strategy must be `panic=unwind`. + // This will ensure that no crates will have wrong unwindability assumption. + // + // It should be noted that it is okay to link `panic=unwind` into a `panic=abort` + // program if it contains no FFI-unwind calls. In such case foreign exception can only + // enter Rust in a `panic=abort` crate, which will lead to an abort. There will also + // be no exceptions generated from Rust, so the assumption which `panic=abort` crates + // make, that no Rust function can unwind, indeed holds for crates compiled with + // `panic=unwind` as well. In such case this function returns `None`, indicating that + // the crate does not require a particular final panic strategy, and can be freely + // linked to crates with either strategy (we need such ability for libstd and its + // dependencies). + return Some(PanicStrategy::Unwind); + } + } + + // This crate can be linked with either runtime. + None +} + +pub(crate) fn provide(providers: &mut Providers) { + *providers = Providers { has_ffi_unwind_calls, required_panic_strategy, ..*providers }; +} diff --git a/compiler/rustc_mir_transform/src/inline.rs b/compiler/rustc_mir_transform/src/inline.rs index 49403ba03a4..12f5764152e 100644 --- a/compiler/rustc_mir_transform/src/inline.rs +++ b/compiler/rustc_mir_transform/src/inline.rs @@ -1,14 +1,15 @@ //! Inlining pass for MIR functions use crate::deref_separator::deref_finder; use rustc_attr::InlineAttr; +use rustc_const_eval::transform::validate::equal_up_to_regions; use rustc_index::bit_set::BitSet; use rustc_index::vec::Idx; use rustc_middle::middle::codegen_fn_attrs::{CodegenFnAttrFlags, CodegenFnAttrs}; use rustc_middle::mir::visit::*; use rustc_middle::mir::*; -use rustc_middle::traits::ObligationCause; use rustc_middle::ty::subst::Subst; use rustc_middle::ty::{self, ConstKind, Instance, InstanceDef, ParamEnv, Ty, TyCtxt}; +use rustc_session::config::OptLevel; use rustc_span::{hygiene::ExpnKind, ExpnData, LocalExpnId, Span}; use rustc_target::spec::abi::Abi; @@ -43,7 +44,15 @@ impl<'tcx> MirPass<'tcx> for Inline { return enabled; } - sess.opts.mir_opt_level() >= 3 + match sess.mir_opt_level() { + 0 | 1 => false, + 2 => { + (sess.opts.optimize == OptLevel::Default + || sess.opts.optimize == OptLevel::Aggressive) + && sess.opts.incremental == None + } + _ => true, + } } fn run_pass(&self, tcx: TyCtxt<'tcx>, body: &mut Body<'tcx>) { @@ -76,13 +85,6 @@ fn inline<'tcx>(tcx: TyCtxt<'tcx>, body: &mut Body<'tcx>) -> bool { } let param_env = tcx.param_env_reveal_all_normalized(def_id); - let hir_id = tcx.hir().local_def_id_to_hir_id(def_id); - let param_env = rustc_trait_selection::traits::normalize_param_env_or_error( - tcx, - def_id.to_def_id(), - param_env, - ObligationCause::misc(body.span, hir_id), - ); let mut this = Inliner { tcx, @@ -166,6 +168,49 @@ impl<'tcx> Inliner<'tcx> { return Err("failed to normalize callee body"); }; + // Check call signature compatibility. + // Normally, this shouldn't be required, but trait normalization failure can create a + // validation ICE. + let terminator = caller_body[callsite.block].terminator.as_ref().unwrap(); + let TerminatorKind::Call { args, destination, .. } = &terminator.kind else { bug!() }; + let destination_ty = destination.ty(&caller_body.local_decls, self.tcx).ty; + let output_type = callee_body.return_ty(); + if !equal_up_to_regions(self.tcx, self.param_env, output_type, destination_ty) { + trace!(?output_type, ?destination_ty); + return Err("failed to normalize return type"); + } + if callsite.fn_sig.abi() == Abi::RustCall { + let (arg_tuple, skipped_args) = match &args[..] { + [arg_tuple] => (arg_tuple, 0), + [_, arg_tuple] => (arg_tuple, 1), + _ => bug!("Expected `rust-call` to have 1 or 2 args"), + }; + + let arg_tuple_ty = arg_tuple.ty(&caller_body.local_decls, self.tcx); + let ty::Tuple(arg_tuple_tys) = arg_tuple_ty.kind() else { + bug!("Closure arguments are not passed as a tuple"); + }; + + for (arg_ty, input) in + arg_tuple_tys.iter().zip(callee_body.args_iter().skip(skipped_args)) + { + let input_type = callee_body.local_decls[input].ty; + if !equal_up_to_regions(self.tcx, self.param_env, arg_ty, input_type) { + trace!(?arg_ty, ?input_type); + return Err("failed to normalize tuple argument type"); + } + } + } else { + for (arg, input) in args.iter().zip(callee_body.args_iter()) { + let input_type = callee_body.local_decls[input].ty; + let arg_ty = arg.ty(&caller_body.local_decls, self.tcx); + if !equal_up_to_regions(self.tcx, self.param_env, arg_ty, input_type) { + trace!(?arg_ty, ?input_type); + return Err("failed to normalize argument type"); + } + } + } + let old_blocks = caller_body.basic_blocks().next_index(); self.inline_call(caller_body, &callsite, callee_body); let new_blocks = old_blocks..caller_body.basic_blocks().next_index(); @@ -263,6 +308,10 @@ impl<'tcx> Inliner<'tcx> { return None; } + if self.history.contains(&callee) { + return None; + } + let fn_sig = self.tcx.bound_fn_sig(def_id).subst(self.tcx, substs); return Some(CallSite { @@ -285,8 +334,14 @@ impl<'tcx> Inliner<'tcx> { callsite: &CallSite<'tcx>, callee_attrs: &CodegenFnAttrs, ) -> Result<(), &'static str> { - if let InlineAttr::Never = callee_attrs.inline { - return Err("never inline hint"); + match callee_attrs.inline { + InlineAttr::Never => return Err("never inline hint"), + InlineAttr::Always | InlineAttr::Hint => {} + InlineAttr::None => { + if self.tcx.sess.mir_opt_level() <= 2 { + return Err("at mir-opt-level=2, only #[inline] is inlined"); + } + } } // Only inline local functions if they would be eligible for cross-crate @@ -407,22 +462,9 @@ impl<'tcx> Inliner<'tcx> { } TerminatorKind::Call { func: Operand::Constant(ref f), cleanup, .. } => { - if let ty::FnDef(def_id, substs) = + if let ty::FnDef(def_id, _) = *callsite.callee.subst_mir(self.tcx, &f.literal.ty()).kind() { - if let Ok(substs) = - self.tcx.try_normalize_erasing_regions(self.param_env, substs) - { - if let Ok(Some(instance)) = - Instance::resolve(self.tcx, self.param_env, def_id, substs) - { - if callsite.callee.def_id() == instance.def_id() { - return Err("self-recursion"); - } else if self.history.contains(&instance) { - return Err("already inlined"); - } - } - } // Don't give intrinsics the extra penalty for calls if tcx.is_intrinsic(def_id) { cost += INSTR_COST; @@ -482,14 +524,12 @@ impl<'tcx> Inliner<'tcx> { if let InlineAttr::Always = callee_attrs.inline { debug!("INLINING {:?} because inline(always) [cost={}]", callsite, cost); Ok(()) + } else if cost <= threshold { + debug!("INLINING {:?} [cost={} <= threshold={}]", callsite, cost, threshold); + Ok(()) } else { - if cost <= threshold { - debug!("INLINING {:?} [cost={} <= threshold={}]", callsite, cost, threshold); - Ok(()) - } else { - debug!("NOT inlining {:?} [cost={} > threshold={}]", callsite, cost, threshold); - Err("cost above threshold") - } + debug!("NOT inlining {:?} [cost={} > threshold={}]", callsite, cost, threshold); + Err("cost above threshold") } } diff --git a/compiler/rustc_mir_transform/src/inline/cycle.rs b/compiler/rustc_mir_transform/src/inline/cycle.rs index fd7de2bd1dc..a3a35f95071 100644 --- a/compiler/rustc_mir_transform/src/inline/cycle.rs +++ b/compiler/rustc_mir_transform/src/inline/cycle.rs @@ -2,7 +2,7 @@ use rustc_data_structures::fx::{FxHashMap, FxHashSet, FxIndexSet}; use rustc_data_structures::stack::ensure_sufficient_stack; use rustc_hir::def_id::{DefId, LocalDefId}; use rustc_middle::mir::TerminatorKind; -use rustc_middle::ty::TypeFoldable; +use rustc_middle::ty::TypeVisitable; use rustc_middle::ty::{self, subst::SubstsRef, InstanceDef, TyCtxt}; use rustc_session::Limit; @@ -48,7 +48,7 @@ pub(crate) fn mir_callgraph_reachable<'tcx>( trace!(?caller, ?param_env, ?substs, "cannot normalize, skipping"); continue; }; - let Some(callee) = ty::Instance::resolve(tcx, param_env, callee, substs).unwrap() else { + let Ok(Some(callee)) = ty::Instance::resolve(tcx, param_env, callee, substs) else { trace!(?callee, "cannot resolve, skipping"); continue; }; diff --git a/compiler/rustc_mir_transform/src/lib.rs b/compiler/rustc_mir_transform/src/lib.rs index b7caa61ef07..9776cd0ab8b 100644 --- a/compiler/rustc_mir_transform/src/lib.rs +++ b/compiler/rustc_mir_transform/src/lib.rs @@ -28,7 +28,7 @@ use rustc_index::vec::IndexVec; use rustc_middle::mir::visit::Visitor as _; use rustc_middle::mir::{traversal, Body, ConstQualifs, MirPass, MirPhase, Promoted}; use rustc_middle::ty::query::Providers; -use rustc_middle::ty::{self, TyCtxt, TypeFoldable}; +use rustc_middle::ty::{self, TyCtxt, TypeVisitable}; use rustc_span::{Span, Symbol}; #[macro_use] @@ -59,6 +59,7 @@ pub mod dump_mir; mod early_otherwise_branch; mod elaborate_box_derefs; mod elaborate_drops; +mod ffi_unwind_calls; mod function_item_references; mod generator; mod inline; @@ -98,6 +99,7 @@ pub fn provide(providers: &mut Providers) { check_unsafety::provide(providers); check_packed_ref::provide(providers); coverage::query::provide(providers); + ffi_unwind_calls::provide(providers); shim::provide(providers); *providers = Providers { mir_keys, @@ -223,6 +225,9 @@ fn mir_const<'tcx>( } } + // has_ffi_unwind_calls query uses the raw mir, so make sure it is run. + tcx.ensure().has_ffi_unwind_calls(def.did); + let mut body = tcx.mir_built(def).steal(); rustc_middle::mir::dump_mir(tcx, None, "mir_map", &0, &body, |_, _| Ok(())); diff --git a/compiler/rustc_mir_transform/src/lower_slice_len.rs b/compiler/rustc_mir_transform/src/lower_slice_len.rs index 07163cfe575..813ab4001a7 100644 --- a/compiler/rustc_mir_transform/src/lower_slice_len.rs +++ b/compiler/rustc_mir_transform/src/lower_slice_len.rs @@ -26,7 +26,9 @@ pub fn lower_slice_len_calls<'tcx>(tcx: TyCtxt<'tcx>, body: &mut Body<'tcx>) { return; }; - let (basic_blocks, local_decls) = body.basic_blocks_and_local_decls_mut(); + // The one successor remains unchanged, so no need to invalidate + let (basic_blocks, local_decls, _) = + body.basic_blocks_local_decls_mut_and_var_debug_info_no_invalidate(); for block in basic_blocks { // lower `<[_]>::len` calls diff --git a/compiler/rustc_mir_transform/src/normalize_array_len.rs b/compiler/rustc_mir_transform/src/normalize_array_len.rs index 0f45711baa3..3396a446df2 100644 --- a/compiler/rustc_mir_transform/src/normalize_array_len.rs +++ b/compiler/rustc_mir_transform/src/normalize_array_len.rs @@ -32,7 +32,9 @@ impl<'tcx> MirPass<'tcx> for NormalizeArrayLen { } pub fn normalize_array_len_calls<'tcx>(tcx: TyCtxt<'tcx>, body: &mut Body<'tcx>) { - let (basic_blocks, local_decls) = body.basic_blocks_and_local_decls_mut(); + // We don't ever touch terminators, so no need to invalidate the CFG cache + let (basic_blocks, local_decls, _) = + body.basic_blocks_local_decls_mut_and_var_debug_info_no_invalidate(); // do a preliminary analysis to see if we ever have locals of type `[T;N]` or `&[T;N]` let mut interesting_locals = BitSet::new_empty(local_decls.len()); diff --git a/compiler/rustc_mir_transform/src/nrvo.rs b/compiler/rustc_mir_transform/src/nrvo.rs index 444b4126e88..d29d17399af 100644 --- a/compiler/rustc_mir_transform/src/nrvo.rs +++ b/compiler/rustc_mir_transform/src/nrvo.rs @@ -219,7 +219,7 @@ impl IsReturnPlaceRead { } impl<'tcx> Visitor<'tcx> for IsReturnPlaceRead { - fn visit_local(&mut self, &l: &Local, ctxt: PlaceContext, _: Location) { + fn visit_local(&mut self, l: Local, ctxt: PlaceContext, _: Location) { if l == mir::RETURN_PLACE && ctxt.is_use() && !ctxt.is_place_assignment() { self.0 = true; } diff --git a/compiler/rustc_mir_transform/src/remove_storage_markers.rs b/compiler/rustc_mir_transform/src/remove_storage_markers.rs index c9b6e1459d3..5bb4f8bb9b3 100644 --- a/compiler/rustc_mir_transform/src/remove_storage_markers.rs +++ b/compiler/rustc_mir_transform/src/remove_storage_markers.rs @@ -17,7 +17,7 @@ impl<'tcx> MirPass<'tcx> for RemoveStorageMarkers { } trace!("Running RemoveStorageMarkers on {:?}", body.source); - for data in body.basic_blocks_mut() { + for data in body.basic_blocks_local_decls_mut_and_var_debug_info_no_invalidate().0 { data.statements.retain(|statement| match statement.kind { StatementKind::StorageLive(..) | StatementKind::StorageDead(..) diff --git a/compiler/rustc_mir_transform/src/remove_zsts.rs b/compiler/rustc_mir_transform/src/remove_zsts.rs index aaee6f491cd..34941c1907d 100644 --- a/compiler/rustc_mir_transform/src/remove_zsts.rs +++ b/compiler/rustc_mir_transform/src/remove_zsts.rs @@ -18,7 +18,8 @@ impl<'tcx> MirPass<'tcx> for RemoveZsts { return; } let param_env = tcx.param_env(body.source.def_id()); - let (basic_blocks, local_decls) = body.basic_blocks_and_local_decls_mut(); + let (basic_blocks, local_decls, _) = + body.basic_blocks_local_decls_mut_and_var_debug_info_no_invalidate(); for block in basic_blocks.iter_mut() { for statement in block.statements.iter_mut() { if let StatementKind::Assign(box (place, _)) | StatementKind::Deinit(box place) = diff --git a/compiler/rustc_mir_transform/src/simplify.rs b/compiler/rustc_mir_transform/src/simplify.rs index 8a78ea5c82b..980af984362 100644 --- a/compiler/rustc_mir_transform/src/simplify.rs +++ b/compiler/rustc_mir_transform/src/simplify.rs @@ -509,12 +509,12 @@ impl<'tcx> Visitor<'tcx> for UsedLocals { } } - fn visit_local(&mut self, local: &Local, _ctx: PlaceContext, _location: Location) { + fn visit_local(&mut self, local: Local, _ctx: PlaceContext, _location: Location) { if self.increment { - self.use_count[*local] += 1; + self.use_count[local] += 1; } else { - assert_ne!(self.use_count[*local], 0); - self.use_count[*local] -= 1; + assert_ne!(self.use_count[local], 0); + self.use_count[local] -= 1; } } } diff --git a/compiler/rustc_mir_transform/src/simplify_try.rs b/compiler/rustc_mir_transform/src/simplify_try.rs index b3d45c7a221..6902213ddad 100644 --- a/compiler/rustc_mir_transform/src/simplify_try.rs +++ b/compiler/rustc_mir_transform/src/simplify_try.rs @@ -462,14 +462,14 @@ impl LocalUseCounter { } impl Visitor<'_> for LocalUseCounter { - fn visit_local(&mut self, local: &Local, context: PlaceContext, _location: Location) { + fn visit_local(&mut self, local: Local, context: PlaceContext, _location: Location) { if context.is_storage_marker() || context == PlaceContext::NonUse(NonUseContext::VarDebugInfo) { return; } - self.local_uses[*local] += 1; + self.local_uses[local] += 1; } } diff --git a/compiler/rustc_monomorphize/src/collector.rs b/compiler/rustc_monomorphize/src/collector.rs index 2af22e129a5..b3ac0f4cbea 100644 --- a/compiler/rustc_monomorphize/src/collector.rs +++ b/compiler/rustc_monomorphize/src/collector.rs @@ -194,7 +194,9 @@ use rustc_middle::mir::{self, Local, Location}; use rustc_middle::ty::adjustment::{CustomCoerceUnsized, PointerCast}; use rustc_middle::ty::print::with_no_trimmed_paths; use rustc_middle::ty::subst::{GenericArgKind, InternalSubsts}; -use rustc_middle::ty::{self, GenericParamDefKind, Instance, Ty, TyCtxt, TypeFoldable, VtblEntry}; +use rustc_middle::ty::{ + self, GenericParamDefKind, Instance, Ty, TyCtxt, TypeFoldable, TypeVisitable, VtblEntry, +}; use rustc_middle::{middle::codegen_fn_attrs::CodegenFnAttrFlags, mir::visit::TyContext}; use rustc_session::config::EntryFnType; use rustc_session::lint::builtin::LARGE_ASSIGNMENTS; @@ -730,7 +732,8 @@ impl<'a, 'tcx> MirVisitor<'tcx> for MirNeighborCollector<'a, 'tcx> { def_id, substs, ty::ClosureKind::FnOnce, - ); + ) + .expect("failed to normalize and resolve closure during codegen"); if should_codegen_locally(self.tcx, &instance) { self.output.push(create_fn_mono_item(self.tcx, instance, span)); } @@ -928,7 +931,7 @@ impl<'a, 'tcx> MirVisitor<'tcx> for MirNeighborCollector<'a, 'tcx> { fn visit_local( &mut self, - _place_local: &Local, + _place_local: Local, _context: mir::visit::PlaceContext, _location: Location, ) { diff --git a/compiler/rustc_monomorphize/src/partitioning/default.rs b/compiler/rustc_monomorphize/src/partitioning/default.rs index 320765e7af3..9190e5fe4eb 100644 --- a/compiler/rustc_monomorphize/src/partitioning/default.rs +++ b/compiler/rustc_monomorphize/src/partitioning/default.rs @@ -9,7 +9,7 @@ use rustc_middle::middle::exported_symbols::{SymbolExportInfo, SymbolExportLevel use rustc_middle::mir::mono::{CodegenUnit, CodegenUnitNameBuilder, Linkage, Visibility}; use rustc_middle::mir::mono::{InstantiationMode, MonoItem}; use rustc_middle::ty::print::characteristic_def_id_of_type; -use rustc_middle::ty::{self, fold::TypeFoldable, DefIdTree, InstanceDef, TyCtxt}; +use rustc_middle::ty::{self, visit::TypeVisitable, DefIdTree, InstanceDef, TyCtxt}; use rustc_span::symbol::Symbol; use super::PartitioningCx; diff --git a/compiler/rustc_monomorphize/src/polymorphize.rs b/compiler/rustc_monomorphize/src/polymorphize.rs index f29143b4480..aaa924d7fa0 100644 --- a/compiler/rustc_monomorphize/src/polymorphize.rs +++ b/compiler/rustc_monomorphize/src/polymorphize.rs @@ -13,9 +13,9 @@ use rustc_middle::mir::{ }; use rustc_middle::ty::{ self, - fold::{TypeFoldable, TypeSuperFoldable, TypeVisitor}, query::Providers, subst::SubstsRef, + visit::{TypeSuperVisitable, TypeVisitable, TypeVisitor}, Const, Ty, TyCtxt, }; use rustc_span::symbol::sym; diff --git a/compiler/rustc_parse/src/parser/diagnostics.rs b/compiler/rustc_parse/src/parser/diagnostics.rs index 0869ed65ad2..63055c56c5c 100644 --- a/compiler/rustc_parse/src/parser/diagnostics.rs +++ b/compiler/rustc_parse/src/parser/diagnostics.rs @@ -357,7 +357,7 @@ impl<'a> DerefMut for SnapshotParser<'a> { } impl<'a> Parser<'a> { - #[cfg_attr(not(bootstrap), rustc_lint_diagnostics)] + #[rustc_lint_diagnostics] pub(super) fn span_err<S: Into<MultiSpan>>( &self, sp: S, @@ -366,7 +366,7 @@ impl<'a> Parser<'a> { err.span_err(sp, self.diagnostic()) } - #[cfg_attr(not(bootstrap), rustc_lint_diagnostics)] + #[rustc_lint_diagnostics] pub fn struct_span_err<S: Into<MultiSpan>>( &self, sp: S, diff --git a/compiler/rustc_passes/src/check_attr.rs b/compiler/rustc_passes/src/check_attr.rs index 40545b19b24..8c123c052e5 100644 --- a/compiler/rustc_passes/src/check_attr.rs +++ b/compiler/rustc_passes/src/check_attr.rs @@ -1163,7 +1163,7 @@ impl CheckAttrVisitor<'_> { hir_id, meta.span(), |lint| { - lint.build(&"invalid `doc` attribute").emit(); + lint.build("invalid `doc` attribute").emit(); }, ); is_valid = false; diff --git a/compiler/rustc_passes/src/dead.rs b/compiler/rustc_passes/src/dead.rs index 01d93f6ff0c..58c5e5b4dfe 100644 --- a/compiler/rustc_passes/src/dead.rs +++ b/compiler/rustc_passes/src/dead.rs @@ -10,14 +10,12 @@ use rustc_hir::def::{CtorOf, DefKind, Res}; use rustc_hir::def_id::{DefId, LocalDefId}; use rustc_hir::intravisit::{self, Visitor}; use rustc_hir::{Node, PatKind, TyKind}; -use rustc_middle::hir::nested_filter; use rustc_middle::middle::codegen_fn_attrs::CodegenFnAttrFlags; use rustc_middle::middle::privacy; use rustc_middle::ty::query::Providers; use rustc_middle::ty::{self, DefIdTree, TyCtxt}; use rustc_session::lint; use rustc_span::symbol::{sym, Symbol}; -use rustc_span::Span; use std::mem; // Any local node that may call something in its body block should be @@ -82,8 +80,8 @@ impl<'tcx> MarkSymbolVisitor<'tcx> { fn handle_res(&mut self, res: Res) { match res { - Res::Def(DefKind::Const | DefKind::AssocConst | DefKind::TyAlias, _) => { - self.check_def_id(res.def_id()); + Res::Def(DefKind::Const | DefKind::AssocConst | DefKind::TyAlias, def_id) => { + self.check_def_id(def_id); } _ if self.in_pat => {} Res::PrimTy(..) | Res::SelfCtor(..) | Res::Local(..) => {} @@ -102,6 +100,7 @@ impl<'tcx> MarkSymbolVisitor<'tcx> { self.check_def_id(variant_id); } } + Res::Def(_, def_id) => self.check_def_id(def_id), Res::SelfTy { trait_: t, alias_to: i } => { if let Some(t) = t { self.check_def_id(t); @@ -111,9 +110,6 @@ impl<'tcx> MarkSymbolVisitor<'tcx> { } } Res::ToolMod | Res::NonMacroAttr(..) | Res::Err => {} - _ => { - self.check_def_id(res.def_id()); - } } } @@ -285,20 +281,33 @@ impl<'tcx> MarkSymbolVisitor<'tcx> { let def = self.tcx.adt_def(item.def_id); self.repr_has_repr_c = def.repr().c(); - intravisit::walk_item(self, &item); - } - hir::ItemKind::Enum(..) => { - intravisit::walk_item(self, &item); + intravisit::walk_item(self, &item) } hir::ItemKind::ForeignMod { .. } => {} - _ => { - intravisit::walk_item(self, &item); - } + _ => intravisit::walk_item(self, &item), }, Node::TraitItem(trait_item) => { intravisit::walk_trait_item(self, trait_item); } Node::ImplItem(impl_item) => { + let item = self.tcx.local_parent(impl_item.def_id); + if self.tcx.impl_trait_ref(item).is_none() { + //// If it's a type whose items are live, then it's live, too. + //// This is done to handle the case where, for example, the static + //// method of a private type is used, but the type itself is never + //// called directly. + let self_ty = self.tcx.type_of(item); + match *self_ty.kind() { + ty::Adt(def, _) => self.check_def_id(def.did()), + ty::Foreign(did) => self.check_def_id(did), + ty::Dynamic(data, ..) => { + if let Some(def_id) = data.principal_def_id() { + self.check_def_id(def_id) + } + } + _ => {} + } + } intravisit::walk_impl_item(self, impl_item); } Node::ForeignItem(foreign_item) => { @@ -624,8 +633,7 @@ fn live_symbols_and_ignored_derived_traits<'tcx>( } struct DeadVariant { - hir_id: hir::HirId, - span: Span, + def_id: LocalDefId, name: Symbol, level: lint::Level, } @@ -637,85 +645,53 @@ struct DeadVisitor<'tcx> { } impl<'tcx> DeadVisitor<'tcx> { - fn should_warn_about_item(&mut self, item: &hir::Item<'_>) -> bool { - let should_warn = matches!( - item.kind, - hir::ItemKind::Static(..) - | hir::ItemKind::Const(..) - | hir::ItemKind::Fn(..) - | hir::ItemKind::TyAlias(..) - | hir::ItemKind::Enum(..) - | hir::ItemKind::Struct(..) - | hir::ItemKind::Union(..) - ); - should_warn && !self.symbol_is_live(item.def_id) - } - - fn should_warn_about_field(&mut self, field: &hir::FieldDef<'_>) -> bool { - let def_id = self.tcx.hir().local_def_id(field.hir_id); - let field_type = self.tcx.type_of(def_id); - !field.is_positional() - && !self.symbol_is_live(def_id) - && !field_type.is_phantom_data() - && !has_allow_dead_code_or_lang_attr(self.tcx, field.hir_id) - } - - fn should_warn_about_variant(&mut self, variant: &hir::Variant<'_>) -> bool { - let def_id = self.tcx.hir().local_def_id(variant.id); - !self.symbol_is_live(def_id) && !has_allow_dead_code_or_lang_attr(self.tcx, variant.id) - } - - fn should_warn_about_foreign_item(&mut self, fi: &hir::ForeignItem<'_>) -> bool { - !self.symbol_is_live(fi.def_id) && !has_allow_dead_code_or_lang_attr(self.tcx, fi.hir_id()) - } - - // id := HIR id of an item's definition. - fn symbol_is_live(&mut self, def_id: LocalDefId) -> bool { - if self.live_symbols.contains(&def_id) { - return true; + fn should_warn_about_field(&mut self, field: &ty::FieldDef) -> bool { + if self.live_symbols.contains(&field.did.expect_local()) { + return false; } - // If it's a type whose items are live, then it's live, too. - // This is done to handle the case where, for example, the static - // method of a private type is used, but the type itself is never - // called directly. - let inherent_impls = self.tcx.inherent_impls(def_id); - for &impl_did in inherent_impls.iter() { - for item_did in self.tcx.associated_item_def_ids(impl_did) { - if let Some(def_id) = item_did.as_local() - && self.live_symbols.contains(&def_id) - { - return true; - } - } + let is_positional = field.name.as_str().starts_with(|c: char| c.is_ascii_digit()); + if is_positional { + return false; } - false + let field_type = self.tcx.type_of(field.did); + !field_type.is_phantom_data() } fn warn_multiple_dead_codes( &self, - dead_codes: &[(hir::HirId, Span, Symbol)], + dead_codes: &[LocalDefId], participle: &str, - parent_hir_id: Option<hir::HirId>, + parent_item: Option<LocalDefId>, ) { - if let Some((id, _, name)) = dead_codes.first() - && !name.as_str().starts_with('_') - { - self.tcx.struct_span_lint_hir( + if let Some(&first_id) = dead_codes.first() { + let tcx = self.tcx; + let names: Vec<_> = dead_codes + .iter() + .map(|&def_id| tcx.item_name(def_id.to_def_id()).to_string()) + .collect(); + let spans = dead_codes + .iter() + .map(|&def_id| match tcx.def_ident_span(def_id) { + Some(s) => s.with_ctxt(tcx.def_span(def_id).ctxt()), + None => tcx.def_span(def_id), + }) + .collect(); + + tcx.struct_span_lint_hir( lint::builtin::DEAD_CODE, - *id, - MultiSpan::from_spans( - dead_codes.iter().map(|(_, span, _)| *span).collect(), - ), + tcx.hir().local_def_id_to_hir_id(first_id), + MultiSpan::from_spans(spans), |lint| { - let def_id = self.tcx.hir().local_def_id(*id); - let descr = self.tcx.def_kind(def_id).descr(def_id.to_def_id()); + let descr = tcx.def_kind(first_id).descr(first_id.to_def_id()); let span_len = dead_codes.len(); - let names = match &dead_codes.iter().map(|(_, _, n)| n.to_string()).collect::<Vec<_>>()[..] - { + let names = match &names[..] { _ if span_len > 6 => String::new(), [name] => format!("`{name}` "), [names @ .., last] => { - format!("{} and `{last}` ", names.iter().map(|name| format!("`{name}`")).join(", ")) + format!( + "{} and `{last}` ", + names.iter().map(|name| format!("`{name}`")).join(", ") + ) } [] => unreachable!(), }; @@ -725,25 +701,17 @@ impl<'tcx> DeadVisitor<'tcx> { s = pluralize!(span_len), are = pluralize!("is", span_len), )); - let hir = self.tcx.hir(); - if let Some(parent_hir_id) = parent_hir_id - && let Some(parent_node) = hir.find(parent_hir_id) - && let Node::Item(item) = parent_node - { - let def_id = self.tcx.hir().local_def_id(parent_hir_id); - let parent_descr = self.tcx.def_kind(def_id).descr(def_id.to_def_id()); + + if let Some(parent_item) = parent_item { + let parent_descr = tcx.def_kind(parent_item).descr(parent_item.to_def_id()); err.span_label( - item.ident.span, - format!( - "{descr}{s} in this {parent_descr}", - s = pluralize!(span_len) - ), + tcx.def_ident_span(parent_item).unwrap(), + format!("{descr}{s} in this {parent_descr}", s = pluralize!(span_len)), ); } - if let Some(encl_scope) = hir.get_enclosing_scope(*id) - && let Some(encl_def_id) = hir.opt_local_def_id(encl_scope) - && let Some(ign_traits) = self.ignored_derived_traits.get(&encl_def_id) - { + + let encl_def_id = parent_item.unwrap_or(first_id); + if let Some(ign_traits) = self.ignored_derived_traits.get(&encl_def_id) { let traits_str = ign_traits .iter() .map(|(trait_id, _)| format!("`{}`", self.tcx.item_name(*trait_id))) @@ -764,15 +732,15 @@ impl<'tcx> DeadVisitor<'tcx> { ); err.note(&msg); } - err.emit(); - }, + err.emit(); + }, ); } } fn warn_dead_fields_and_variants( &self, - hir_id: hir::HirId, + def_id: LocalDefId, participle: &str, dead_codes: Vec<DeadVariant>, ) { @@ -787,207 +755,110 @@ impl<'tcx> DeadVisitor<'tcx> { dead_codes.sort_by_key(|v| v.level); for (_, group) in &dead_codes.into_iter().group_by(|v| v.level) { self.warn_multiple_dead_codes( - &group - .map(|v| (v.hir_id, v.span, v.name)) - .collect::<Vec<(hir::HirId, Span, Symbol)>>(), + &group.map(|v| v.def_id).collect::<Vec<_>>(), participle, - Some(hir_id), + Some(def_id), ); } } - fn warn_dead_code( - &mut self, - id: hir::HirId, - span: rustc_span::Span, - name: Symbol, - participle: &str, - ) { - self.warn_multiple_dead_codes(&[(id, span, name)], participle, None); + fn warn_dead_code(&mut self, id: LocalDefId, participle: &str) { + self.warn_multiple_dead_codes(&[id], participle, None); } -} -impl<'tcx> Visitor<'tcx> for DeadVisitor<'tcx> { - type NestedFilter = nested_filter::All; - - /// Walk nested items in place so that we don't report dead-code - /// on inner functions when the outer function is already getting - /// an error. We could do this also by checking the parents, but - /// this is how the code is setup and it seems harmless enough. - fn nested_visit_map(&mut self) -> Self::Map { - self.tcx.hir() - } - - fn visit_item(&mut self, item: &'tcx hir::Item<'tcx>) { - if self.should_warn_about_item(item) { - // For most items, we want to highlight its identifier - let span = match item.kind { - hir::ItemKind::Fn(..) - | hir::ItemKind::Mod(..) - | hir::ItemKind::Enum(..) - | hir::ItemKind::Struct(..) - | hir::ItemKind::Union(..) - | hir::ItemKind::Trait(..) - | hir::ItemKind::Impl { .. } => { - // FIXME(66095): Because item.span is annotated with things - // like expansion data, and ident.span isn't, we use the - // def_span method if it's part of a macro invocation - // (and thus has a source_callee set). - // We should probably annotate ident.span with the macro - // context, but that's a larger change. - if item.span.source_callee().is_some() { - self.tcx.sess.source_map().guess_head_span(item.span) - } else { - item.ident.span - } - } - _ => item.span, - }; - let participle = match item.kind { - hir::ItemKind::Struct(..) => "constructed", // Issue #52325 - _ => "used", - }; - self.warn_dead_code(item.hir_id(), span, item.ident.name, participle); - } else { - // Only continue if we didn't warn - intravisit::walk_item(self, item); + fn check_definition(&mut self, def_id: LocalDefId) { + if self.live_symbols.contains(&def_id) { + return; + } + let hir_id = self.tcx.hir().local_def_id_to_hir_id(def_id); + if has_allow_dead_code_or_lang_attr(self.tcx, hir_id) { + return; + } + let Some(name) = self.tcx.opt_item_name(def_id.to_def_id()) else { + return + }; + if name.as_str().starts_with('_') { + return; + } + match self.tcx.def_kind(def_id) { + DefKind::AssocConst + | DefKind::AssocFn + | DefKind::Fn + | DefKind::Static(_) + | DefKind::Const + | DefKind::TyAlias + | DefKind::Enum + | DefKind::Union + | DefKind::ForeignTy => self.warn_dead_code(def_id, "used"), + DefKind::Struct => self.warn_dead_code(def_id, "constructed"), + DefKind::Variant | DefKind::Field => bug!("should be handled specially"), + _ => {} } } +} - // This visitor should only visit a single module at a time. - fn visit_mod(&mut self, _: &'tcx hir::Mod<'tcx>, _: Span, _: hir::HirId) {} +fn check_mod_deathness(tcx: TyCtxt<'_>, module: LocalDefId) { + let (live_symbols, ignored_derived_traits) = tcx.live_symbols_and_ignored_derived_traits(()); + let mut visitor = DeadVisitor { tcx, live_symbols, ignored_derived_traits }; - fn visit_enum_def( - &mut self, - enum_definition: &'tcx hir::EnumDef<'tcx>, - generics: &'tcx hir::Generics<'tcx>, - item_id: hir::HirId, - _: Span, - ) { - intravisit::walk_enum_def(self, enum_definition, generics, item_id); - let dead_variants = enum_definition - .variants - .iter() - .filter_map(|variant| { - if self.should_warn_about_variant(&variant) { - Some(DeadVariant { - hir_id: variant.id, - span: variant.span, - name: variant.ident.name, - level: self.tcx.lint_level_at_node(lint::builtin::DEAD_CODE, variant.id).0, - }) - } else { - None - } - }) - .collect(); - self.warn_dead_fields_and_variants(item_id, "constructed", dead_variants) - } + let module_items = tcx.hir_module_items(module); - fn visit_variant( - &mut self, - variant: &'tcx hir::Variant<'tcx>, - g: &'tcx hir::Generics<'tcx>, - id: hir::HirId, - ) { - if !self.should_warn_about_variant(&variant) { - intravisit::walk_variant(self, variant, g, id); + for item in module_items.items() { + if !live_symbols.contains(&item.def_id) { + let parent = tcx.local_parent(item.def_id); + if parent != module && !live_symbols.contains(&parent) { + // We already have diagnosed something. + continue; + } + visitor.check_definition(item.def_id); + continue; } - } - fn visit_foreign_item(&mut self, fi: &'tcx hir::ForeignItem<'tcx>) { - if self.should_warn_about_foreign_item(fi) { - self.warn_dead_code(fi.hir_id(), fi.span, fi.ident.name, "used"); - } - intravisit::walk_foreign_item(self, fi); - } + let def_kind = tcx.def_kind(item.def_id); + if let DefKind::Struct | DefKind::Union | DefKind::Enum = def_kind { + let adt = tcx.adt_def(item.def_id); + let mut dead_variants = Vec::new(); - fn visit_variant_data( - &mut self, - def: &'tcx hir::VariantData<'tcx>, - _: Symbol, - _: &hir::Generics<'_>, - id: hir::HirId, - _: rustc_span::Span, - ) { - intravisit::walk_struct_def(self, def); - let dead_fields = def - .fields() - .iter() - .filter_map(|field| { - if self.should_warn_about_field(&field) { - Some(DeadVariant { - hir_id: field.hir_id, - span: field.span, - name: field.ident.name, - level: self - .tcx - .lint_level_at_node(lint::builtin::DEAD_CODE, field.hir_id) - .0, - }) - } else { - None + for variant in adt.variants() { + let def_id = variant.def_id.expect_local(); + if !live_symbols.contains(&def_id) { + // Record to group diagnostics. + let hir_id = tcx.hir().local_def_id_to_hir_id(def_id); + let level = tcx.lint_level_at_node(lint::builtin::DEAD_CODE, hir_id).0; + dead_variants.push(DeadVariant { def_id, name: variant.name, level }); + continue; } - }) - .collect(); - self.warn_dead_fields_and_variants(id, "read", dead_fields) - } - - fn visit_impl_item(&mut self, impl_item: &'tcx hir::ImplItem<'tcx>) { - match impl_item.kind { - hir::ImplItemKind::Const(_, body_id) => { - if !self.symbol_is_live(impl_item.def_id) { - self.warn_dead_code( - impl_item.hir_id(), - impl_item.span, - impl_item.ident.name, - "used", - ); - } - self.visit_nested_body(body_id) - } - hir::ImplItemKind::Fn(_, body_id) => { - if !self.symbol_is_live(impl_item.def_id) { - // FIXME(66095): Because impl_item.span is annotated with things - // like expansion data, and ident.span isn't, we use the - // def_span method if it's part of a macro invocation - // (and thus has a source_callee set). - // We should probably annotate ident.span with the macro - // context, but that's a larger change. - let span = if impl_item.span.source_callee().is_some() { - self.tcx.sess.source_map().guess_head_span(impl_item.span) - } else { - impl_item.ident.span - }; - self.warn_dead_code(impl_item.hir_id(), span, impl_item.ident.name, "used"); - } - self.visit_nested_body(body_id) + + let dead_fields = variant + .fields + .iter() + .filter_map(|field| { + let def_id = field.did.expect_local(); + let hir_id = tcx.hir().local_def_id_to_hir_id(def_id); + if visitor.should_warn_about_field(&field) { + let level = tcx.lint_level_at_node(lint::builtin::DEAD_CODE, hir_id).0; + Some(DeadVariant { def_id, name: field.name, level }) + } else { + None + } + }) + .collect(); + visitor.warn_dead_fields_and_variants(def_id, "read", dead_fields) } - hir::ImplItemKind::TyAlias(..) => {} + + visitor.warn_dead_fields_and_variants(item.def_id, "constructed", dead_variants); } } - // Overwrite so that we don't warn the trait item itself. - fn visit_trait_item(&mut self, trait_item: &'tcx hir::TraitItem<'tcx>) { - match trait_item.kind { - hir::TraitItemKind::Const(_, Some(body_id)) - | hir::TraitItemKind::Fn(_, hir::TraitFn::Provided(body_id)) => { - self.visit_nested_body(body_id) - } - hir::TraitItemKind::Const(_, None) - | hir::TraitItemKind::Fn(_, hir::TraitFn::Required(_)) - | hir::TraitItemKind::Type(..) => {} - } + for impl_item in module_items.impl_items() { + visitor.check_definition(impl_item.def_id); } -} -fn check_mod_deathness(tcx: TyCtxt<'_>, module: LocalDefId) { - let (live_symbols, ignored_derived_traits) = tcx.live_symbols_and_ignored_derived_traits(()); - let mut visitor = DeadVisitor { tcx, live_symbols, ignored_derived_traits }; - let (module, _, module_id) = tcx.hir().get_module(module); - // Do not use an ItemLikeVisitor since we may want to skip visiting some items - // when a surrounding one is warned against or `_`. - intravisit::walk_mod(&mut visitor, module, module_id); + for foreign_item in module_items.foreign_items() { + visitor.check_definition(foreign_item.def_id); + } + + // We do not warn trait items. } pub(crate) fn provide(providers: &mut Providers) { diff --git a/compiler/rustc_passes/src/entry.rs b/compiler/rustc_passes/src/entry.rs index f9e67310452..1add91fc9c5 100644 --- a/compiler/rustc_passes/src/entry.rs +++ b/compiler/rustc_passes/src/entry.rs @@ -1,4 +1,4 @@ -use rustc_ast::entry::EntryPointType; +use rustc_ast::{entry::EntryPointType, Attribute}; use rustc_errors::struct_span_err; use rustc_hir::def::DefKind; use rustc_hir::def_id::{DefId, LocalDefId, CRATE_DEF_ID, LOCAL_CRATE}; @@ -7,9 +7,8 @@ use rustc_middle::ty::query::Providers; use rustc_middle::ty::{DefIdTree, TyCtxt}; use rustc_session::config::{CrateType, EntryFnType}; use rustc_session::parse::feature_err; -use rustc_session::Session; use rustc_span::symbol::sym; -use rustc_span::{Span, DUMMY_SP}; +use rustc_span::{Span, Symbol, DUMMY_SP}; struct EntryContext<'tcx> { tcx: TyCtxt<'tcx>, @@ -72,9 +71,16 @@ fn entry_point_type(ctxt: &EntryContext<'_>, id: ItemId, at_root: bool) -> Entry } } -fn throw_attr_err(sess: &Session, span: Span, attr: &str) { - sess.struct_span_err(span, &format!("`{}` attribute can only be used on functions", attr)) - .emit(); +fn err_if_attr_found(ctxt: &EntryContext<'_>, attrs: &[Attribute], sym: Symbol) { + if let Some(attr) = ctxt.tcx.sess.find_by_name(attrs, sym) { + ctxt.tcx + .sess + .struct_span_err( + attr.span, + &format!("`{}` attribute can only be used on functions", sym.as_str()), + ) + .emit(); + } } fn find_item(id: ItemId, ctxt: &mut EntryContext<'_>) { @@ -84,12 +90,8 @@ fn find_item(id: ItemId, ctxt: &mut EntryContext<'_>) { EntryPointType::None => (), _ if !matches!(ctxt.tcx.def_kind(id.def_id), DefKind::Fn) => { let attrs = ctxt.tcx.hir().attrs(id.hir_id()); - if let Some(attr) = ctxt.tcx.sess.find_by_name(attrs, sym::start) { - throw_attr_err(&ctxt.tcx.sess, attr.span, "start"); - } - if let Some(attr) = ctxt.tcx.sess.find_by_name(attrs, sym::rustc_main) { - throw_attr_err(&ctxt.tcx.sess, attr.span, "rustc_main"); - } + err_if_attr_found(ctxt, attrs, sym::start); + err_if_attr_found(ctxt, attrs, sym::rustc_main); } EntryPointType::MainNamed => (), EntryPointType::OtherMain => { diff --git a/compiler/rustc_privacy/src/lib.rs b/compiler/rustc_privacy/src/lib.rs index f5e323e2bc4..5560d44aa0d 100644 --- a/compiler/rustc_privacy/src/lib.rs +++ b/compiler/rustc_privacy/src/lib.rs @@ -27,7 +27,7 @@ use rustc_middle::thir::abstract_const::Node as ACNode; use rustc_middle::ty::query::Providers; use rustc_middle::ty::subst::InternalSubsts; use rustc_middle::ty::{self, Const, DefIdTree, GenericParamDefKind}; -use rustc_middle::ty::{TraitRef, Ty, TyCtxt, TypeFoldable, TypeSuperFoldable, TypeVisitor}; +use rustc_middle::ty::{TraitRef, Ty, TyCtxt, TypeSuperVisitable, TypeVisitable, TypeVisitor}; use rustc_session::lint; use rustc_span::hygiene::Transparency; use rustc_span::symbol::{kw, Ident}; @@ -80,7 +80,7 @@ trait DefIdVisitor<'tcx> { dummy: Default::default(), } } - fn visit(&mut self, ty_fragment: impl TypeFoldable<'tcx>) -> ControlFlow<Self::BreakTy> { + fn visit(&mut self, ty_fragment: impl TypeVisitable<'tcx>) -> ControlFlow<Self::BreakTy> { ty_fragment.visit_with(&mut self.skeleton()) } fn visit_trait(&mut self, trait_ref: TraitRef<'tcx>) -> ControlFlow<Self::BreakTy> { @@ -467,7 +467,7 @@ impl<'tcx> EmbargoVisitor<'tcx> { } let macro_module_def_id = self.tcx.local_parent(local_def_id); - if self.tcx.hir().opt_def_kind(macro_module_def_id) != Some(DefKind::Mod) { + if self.tcx.opt_def_kind(macro_module_def_id) != Some(DefKind::Mod) { // The macro's parent doesn't correspond to a `mod`, return early (#63164, #65252). return; } diff --git a/compiler/rustc_query_impl/src/lib.rs b/compiler/rustc_query_impl/src/lib.rs index d06eb97798e..7c1fdc4e306 100644 --- a/compiler/rustc_query_impl/src/lib.rs +++ b/compiler/rustc_query_impl/src/lib.rs @@ -27,6 +27,8 @@ use rustc_span::Span; mod plumbing; pub use plumbing::QueryCtxt; use rustc_query_system::query::*; +#[cfg(parallel_compiler)] +pub use rustc_query_system::query::{deadlock, QueryContext}; mod keys; use keys::Key; diff --git a/compiler/rustc_query_impl/src/plumbing.rs b/compiler/rustc_query_impl/src/plumbing.rs index 66f4508f6b4..3ed6632ba66 100644 --- a/compiler/rustc_query_impl/src/plumbing.rs +++ b/compiler/rustc_query_impl/src/plumbing.rs @@ -132,11 +132,6 @@ impl<'tcx> QueryCtxt<'tcx> { self.queries.on_disk_cache.as_ref() } - #[cfg(parallel_compiler)] - pub unsafe fn deadlock(self, registry: &rustc_rayon_core::Registry) { - rustc_query_system::query::deadlock(self, registry) - } - pub(super) fn encode_query_results( self, encoder: &mut on_disk_cache::CacheEncoder<'_, 'tcx>, @@ -287,11 +282,14 @@ macro_rules! define_queries { } else { Some(key.default_span(*tcx)) }; - // Use `tcx.hir().opt_def_kind()` to reduce the chance of - // accidentally triggering an infinite query loop. - let def_kind = key.key_as_def_id() - .and_then(|def_id| def_id.as_local()) - .and_then(|def_id| tcx.hir().opt_def_kind(def_id)); + let def_kind = if kind == dep_graph::DepKind::opt_def_kind { + // Try to avoid infinite recursion. + None + } else { + key.key_as_def_id() + .and_then(|def_id| def_id.as_local()) + .and_then(|def_id| tcx.opt_def_kind(def_id)) + }; let hash = || { let mut hcx = tcx.create_stable_hashing_context(); let mut hasher = StableHasher::new(); diff --git a/compiler/rustc_query_system/src/query/job.rs b/compiler/rustc_query_system/src/query/job.rs index 2a07d9b7f80..f1316557c29 100644 --- a/compiler/rustc_query_system/src/query/job.rs +++ b/compiler/rustc_query_system/src/query/job.rs @@ -492,14 +492,13 @@ fn remove_cycle( /// There may be multiple cycles involved in a deadlock, so this searches /// all active queries for cycles before finally resuming all the waiters at once. #[cfg(parallel_compiler)] -pub fn deadlock<CTX: QueryContext>(tcx: CTX, registry: &rayon_core::Registry) { +pub fn deadlock(query_map: QueryMap, registry: &rayon_core::Registry) { let on_panic = OnDrop(|| { eprintln!("deadlock handler panicked, aborting process"); process::abort(); }); let mut wakelist = Vec::new(); - let query_map = tcx.try_collect_active_jobs().unwrap(); let mut jobs: Vec<QueryJobId> = query_map.keys().cloned().collect(); let mut found_cycle = false; diff --git a/compiler/rustc_resolve/src/diagnostics.rs b/compiler/rustc_resolve/src/diagnostics.rs index e8b7cee5734..0f58206eee9 100644 --- a/compiler/rustc_resolve/src/diagnostics.rs +++ b/compiler/rustc_resolve/src/diagnostics.rs @@ -1495,6 +1495,15 @@ impl<'a> Resolver<'a> { err.help("have you added the `#[macro_use]` on the module/import?"); return; } + if ident.name == kw::Default + && let ModuleKind::Def(DefKind::Enum, def_id, _) = parent_scope.module.kind + && let Some(span) = self.opt_span(def_id) + { + err.span_help( + self.session.source_map().guess_head_span(span), + "consider adding `#[derive(Default)]` to this enum", + ); + } for ns in [Namespace::MacroNS, Namespace::TypeNS, Namespace::ValueNS] { if let Ok(binding) = self.early_resolve_ident_in_lexical_scope( ident, @@ -2580,8 +2589,10 @@ fn show_candidates( } else { "item".to_string() }; + let plural_descr = + if descr.ends_with("s") { format!("{}es", descr) } else { format!("{}s", descr) }; - let mut msg = format!("{}these {}s exist but are inaccessible", prefix, descr); + let mut msg = format!("{}these {} exist but are inaccessible", prefix, plural_descr); let mut has_colon = false; let mut spans = Vec::new(); diff --git a/compiler/rustc_resolve/src/imports.rs b/compiler/rustc_resolve/src/imports.rs index c6aa57f039d..e6060ad4665 100644 --- a/compiler/rustc_resolve/src/imports.rs +++ b/compiler/rustc_resolve/src/imports.rs @@ -1090,31 +1090,31 @@ impl<'a, 'b> ImportResolver<'a, 'b> { // Since import resolution is finished, globs will not define any more names. *module.globs.borrow_mut() = Vec::new(); - let mut reexports = Vec::new(); - - module.for_each_child(self.r, |_, ident, _, binding| { - // FIXME: Consider changing the binding inserted by `#[macro_export] macro_rules` - // into the crate root to actual `NameBindingKind::Import`. - if binding.is_import() - || matches!(binding.kind, NameBindingKind::Res(_, _is_macro_export @ true)) - { - let res = binding.res().expect_non_local(); - // Ambiguous imports are treated as errors at this point and are - // not exposed to other crates (see #36837 for more details). - if res != def::Res::Err && !binding.is_ambiguity() { - reexports.push(ModChild { - ident, - res, - vis: binding.vis, - span: binding.span, - macro_rules: false, - }); + if let Some(def_id) = module.opt_def_id() { + let mut reexports = Vec::new(); + + module.for_each_child(self.r, |_, ident, _, binding| { + // FIXME: Consider changing the binding inserted by `#[macro_export] macro_rules` + // into the crate root to actual `NameBindingKind::Import`. + if binding.is_import() + || matches!(binding.kind, NameBindingKind::Res(_, _is_macro_export @ true)) + { + let res = binding.res().expect_non_local(); + // Ambiguous imports are treated as errors at this point and are + // not exposed to other crates (see #36837 for more details). + if res != def::Res::Err && !binding.is_ambiguity() { + reexports.push(ModChild { + ident, + res, + vis: binding.vis, + span: binding.span, + macro_rules: false, + }); + } } - } - }); + }); - if !reexports.is_empty() { - if let Some(def_id) = module.opt_def_id() { + if !reexports.is_empty() { // Call to `expect_local` should be fine because current // code is only called for local modules. self.r.reexport_map.insert(def_id.expect_local(), reexports); diff --git a/compiler/rustc_resolve/src/late/diagnostics.rs b/compiler/rustc_resolve/src/late/diagnostics.rs index 2b4e64bddc2..03cb1cfcfc9 100644 --- a/compiler/rustc_resolve/src/late/diagnostics.rs +++ b/compiler/rustc_resolve/src/late/diagnostics.rs @@ -1503,6 +1503,8 @@ impl<'a: 'ast, 'ast> LateResolutionVisitor<'a, '_, 'ast> { Some(match name { "byte" => sym::u8, // In Java, bytes are signed, but in practice one almost always wants unsigned bytes. "short" => sym::i16, + "Bool" => sym::bool, + "Boolean" => sym::bool, "boolean" => sym::bool, "int" => sym::i32, "long" => sym::i64, diff --git a/compiler/rustc_resolve/src/lib.rs b/compiler/rustc_resolve/src/lib.rs index 57384877da5..28ef384f2c5 100644 --- a/compiler/rustc_resolve/src/lib.rs +++ b/compiler/rustc_resolve/src/lib.rs @@ -13,7 +13,6 @@ #![feature(let_chains)] #![feature(let_else)] #![feature(never_type)] -#![cfg_attr(bootstrap, feature(nll))] #![recursion_limit = "256"] #![allow(rustdoc::private_intra_doc_links)] #![allow(rustc::potential_query_instability)] diff --git a/compiler/rustc_save_analysis/src/lib.rs b/compiler/rustc_save_analysis/src/lib.rs index 99f38b3222d..0a0c674d179 100644 --- a/compiler/rustc_save_analysis/src/lib.rs +++ b/compiler/rustc_save_analysis/src/lib.rs @@ -623,9 +623,9 @@ impl<'tcx> SaveContext<'tcx> { } }, - Node::Binding(&hir::Pat { - kind: hir::PatKind::Binding(_, canonical_id, ..), .. - }) => Res::Local(canonical_id), + Node::Pat(&hir::Pat { kind: hir::PatKind::Binding(_, canonical_id, ..), .. }) => { + Res::Local(canonical_id) + } _ => Res::Err, } diff --git a/compiler/rustc_session/src/config.rs b/compiler/rustc_session/src/config.rs index 14ad1a42a7d..e7717f1367c 100644 --- a/compiler/rustc_session/src/config.rs +++ b/compiler/rustc_session/src/config.rs @@ -1102,49 +1102,6 @@ impl CrateCheckConfig { .extend(atomic_values); // Target specific values - #[cfg(bootstrap)] - { - for target in TARGETS - .iter() - .map(|target| Target::expect_builtin(&TargetTriple::from_triple(target))) - { - self.values_valid - .entry(sym::target_os) - .or_default() - .insert(Symbol::intern(&target.options.os)); - self.values_valid - .entry(sym::target_family) - .or_default() - .extend(target.options.families.iter().map(|family| Symbol::intern(family))); - self.values_valid - .entry(sym::target_arch) - .or_default() - .insert(Symbol::intern(&target.arch)); - self.values_valid - .entry(sym::target_endian) - .or_default() - .insert(Symbol::intern(&target.options.endian.as_str())); - self.values_valid - .entry(sym::target_env) - .or_default() - .insert(Symbol::intern(&target.options.env)); - self.values_valid - .entry(sym::target_abi) - .or_default() - .insert(Symbol::intern(&target.options.abi)); - self.values_valid - .entry(sym::target_vendor) - .or_default() - .insert(Symbol::intern(&target.options.vendor)); - self.values_valid - .entry(sym::target_pointer_width) - .or_default() - .insert(sym::integer(target.pointer_width)); - } - } - - // Target specific values - #[cfg(not(bootstrap))] { const VALUES: [&Symbol; 8] = [ &sym::target_os, @@ -2767,8 +2724,8 @@ pub(crate) mod dep_tracking { use super::{ BranchProtection, CFGuard, CFProtection, CrateType, DebugInfo, ErrorOutputType, InstrumentCoverage, LdImpl, LinkerPluginLto, LocationDetail, LtoCli, OomStrategy, OptLevel, - OutputType, OutputTypes, Passes, SourceFileHashAlgorithm, SwitchWithOptPath, - SymbolManglingVersion, TrimmedDefPaths, + OutputType, OutputTypes, Passes, SourceFileHashAlgorithm, SplitDwarfKind, + SwitchWithOptPath, SymbolManglingVersion, TrimmedDefPaths, }; use crate::lint; use crate::options::WasiExecModel; @@ -2855,6 +2812,7 @@ pub(crate) mod dep_tracking { Edition, LinkerPluginLto, SplitDebuginfo, + SplitDwarfKind, StackProtector, SwitchWithOptPath, SymbolManglingVersion, diff --git a/compiler/rustc_session/src/lib.rs b/compiler/rustc_session/src/lib.rs index 35b55981e37..7353c1ca0e2 100644 --- a/compiler/rustc_session/src/lib.rs +++ b/compiler/rustc_session/src/lib.rs @@ -6,7 +6,7 @@ #![feature(once_cell)] #![feature(option_get_or_insert_default)] #![feature(rustc_attrs)] -#![cfg_attr(not(bootstrap), feature(map_many_mut))] +#![feature(map_many_mut)] #![recursion_limit = "256"] #![allow(rustc::potential_query_instability)] diff --git a/compiler/rustc_session/src/options.rs b/compiler/rustc_session/src/options.rs index 441e1f9f6a2..be70ea5d5e4 100644 --- a/compiler/rustc_session/src/options.rs +++ b/compiler/rustc_session/src/options.rs @@ -1496,7 +1496,7 @@ options! { "control if mem::uninitialized and mem::zeroed panic on more UB"), strip: Strip = (Strip::None, parse_strip, [UNTRACKED], "tell the linker which information to strip (`none` (default), `debuginfo` or `symbols`)"), - split_dwarf_kind: SplitDwarfKind = (SplitDwarfKind::Split, parse_split_dwarf_kind, [UNTRACKED], + split_dwarf_kind: SplitDwarfKind = (SplitDwarfKind::Split, parse_split_dwarf_kind, [TRACKED], "split dwarf variant (only if -Csplit-debuginfo is enabled and on relevant platform) (default: `split`) @@ -1504,7 +1504,7 @@ options! { file which is ignored by the linker `single`: sections which do not require relocation are written into object file but ignored by the linker"), - split_dwarf_inlining: bool = (true, parse_bool, [UNTRACKED], + split_dwarf_inlining: bool = (true, parse_bool, [TRACKED], "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"), symbol_mangling_version: Option<SymbolManglingVersion> = (None, diff --git a/compiler/rustc_session/src/parse.rs b/compiler/rustc_session/src/parse.rs index a5ccae047fc..f31d52147b4 100644 --- a/compiler/rustc_session/src/parse.rs +++ b/compiler/rustc_session/src/parse.rs @@ -311,7 +311,7 @@ impl ParseSess { self.create_warning(warning).emit() } - #[cfg_attr(not(bootstrap), rustc_lint_diagnostics)] + #[rustc_lint_diagnostics] pub fn struct_err( &self, msg: impl Into<DiagnosticMessage>, @@ -319,7 +319,7 @@ impl ParseSess { self.span_diagnostic.struct_err(msg) } - #[cfg_attr(not(bootstrap), rustc_lint_diagnostics)] + #[rustc_lint_diagnostics] pub fn struct_warn(&self, msg: impl Into<DiagnosticMessage>) -> DiagnosticBuilder<'_, ()> { self.span_diagnostic.struct_warn(msg) } diff --git a/compiler/rustc_session/src/session.rs b/compiler/rustc_session/src/session.rs index b5058fd699a..2a5ddd4e9e4 100644 --- a/compiler/rustc_session/src/session.rs +++ b/compiler/rustc_session/src/session.rs @@ -280,7 +280,7 @@ impl Session { self.crate_types.set(crate_types).expect("`crate_types` was initialized twice") } - #[cfg_attr(not(bootstrap), rustc_lint_diagnostics)] + #[rustc_lint_diagnostics] pub fn struct_span_warn<S: Into<MultiSpan>>( &self, sp: S, @@ -288,7 +288,7 @@ impl Session { ) -> DiagnosticBuilder<'_, ()> { self.diagnostic().struct_span_warn(sp, msg) } - #[cfg_attr(not(bootstrap), rustc_lint_diagnostics)] + #[rustc_lint_diagnostics] pub fn struct_span_warn_with_expectation<S: Into<MultiSpan>>( &self, sp: S, @@ -297,7 +297,7 @@ impl Session { ) -> DiagnosticBuilder<'_, ()> { self.diagnostic().struct_span_warn_with_expectation(sp, msg, id) } - #[cfg_attr(not(bootstrap), rustc_lint_diagnostics)] + #[rustc_lint_diagnostics] pub fn struct_span_warn_with_code<S: Into<MultiSpan>>( &self, sp: S, @@ -306,11 +306,11 @@ impl Session { ) -> DiagnosticBuilder<'_, ()> { self.diagnostic().struct_span_warn_with_code(sp, msg, code) } - #[cfg_attr(not(bootstrap), rustc_lint_diagnostics)] + #[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)] + #[rustc_lint_diagnostics] pub fn struct_warn_with_expectation( &self, msg: impl Into<DiagnosticMessage>, @@ -318,7 +318,7 @@ impl Session { ) -> DiagnosticBuilder<'_, ()> { self.diagnostic().struct_warn_with_expectation(msg, id) } - #[cfg_attr(not(bootstrap), rustc_lint_diagnostics)] + #[rustc_lint_diagnostics] pub fn struct_span_allow<S: Into<MultiSpan>>( &self, sp: S, @@ -326,11 +326,11 @@ impl Session { ) -> DiagnosticBuilder<'_, ()> { self.diagnostic().struct_span_allow(sp, msg) } - #[cfg_attr(not(bootstrap), rustc_lint_diagnostics)] + #[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)] + #[rustc_lint_diagnostics] pub fn struct_expect( &self, msg: impl Into<DiagnosticMessage>, @@ -338,7 +338,7 @@ impl Session { ) -> DiagnosticBuilder<'_, ()> { self.diagnostic().struct_expect(msg, id) } - #[cfg_attr(not(bootstrap), rustc_lint_diagnostics)] + #[rustc_lint_diagnostics] pub fn struct_span_err<S: Into<MultiSpan>>( &self, sp: S, @@ -346,7 +346,7 @@ impl Session { ) -> DiagnosticBuilder<'_, ErrorGuaranteed> { self.diagnostic().struct_span_err(sp, msg) } - #[cfg_attr(not(bootstrap), rustc_lint_diagnostics)] + #[rustc_lint_diagnostics] pub fn struct_span_err_with_code<S: Into<MultiSpan>>( &self, sp: S, @@ -356,14 +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)] + #[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)] + #[rustc_lint_diagnostics] pub fn struct_err_with_code( &self, msg: impl Into<DiagnosticMessage>, @@ -371,7 +371,7 @@ impl Session { ) -> DiagnosticBuilder<'_, ErrorGuaranteed> { self.diagnostic().struct_err_with_code(msg, code) } - #[cfg_attr(not(bootstrap), rustc_lint_diagnostics)] + #[rustc_lint_diagnostics] pub fn struct_warn_with_code( &self, msg: impl Into<DiagnosticMessage>, @@ -379,7 +379,7 @@ impl Session { ) -> DiagnosticBuilder<'_, ()> { self.diagnostic().struct_warn_with_code(msg, code) } - #[cfg_attr(not(bootstrap), rustc_lint_diagnostics)] + #[rustc_lint_diagnostics] pub fn struct_span_fatal<S: Into<MultiSpan>>( &self, sp: S, @@ -387,7 +387,7 @@ impl Session { ) -> DiagnosticBuilder<'_, !> { self.diagnostic().struct_span_fatal(sp, msg) } - #[cfg_attr(not(bootstrap), rustc_lint_diagnostics)] + #[rustc_lint_diagnostics] pub fn struct_span_fatal_with_code<S: Into<MultiSpan>>( &self, sp: S, @@ -396,16 +396,16 @@ impl Session { ) -> DiagnosticBuilder<'_, !> { self.diagnostic().struct_span_fatal_with_code(sp, msg, code) } - #[cfg_attr(not(bootstrap), rustc_lint_diagnostics)] + #[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)] + #[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)] + #[rustc_lint_diagnostics] pub fn span_fatal_with_code<S: Into<MultiSpan>>( &self, sp: S, @@ -414,11 +414,11 @@ impl Session { ) -> ! { self.diagnostic().span_fatal_with_code(sp, msg, code) } - #[cfg_attr(not(bootstrap), rustc_lint_diagnostics)] + #[rustc_lint_diagnostics] pub fn fatal(&self, msg: impl Into<DiagnosticMessage>) -> ! { self.diagnostic().fatal(msg).raise() } - #[cfg_attr(not(bootstrap), rustc_lint_diagnostics)] + #[rustc_lint_diagnostics] pub fn span_err_or_warn<S: Into<MultiSpan>>( &self, is_warning: bool, @@ -431,7 +431,7 @@ impl Session { self.span_err(sp, msg); } } - #[cfg_attr(not(bootstrap), rustc_lint_diagnostics)] + #[rustc_lint_diagnostics] pub fn span_err<S: Into<MultiSpan>>( &self, sp: S, @@ -439,7 +439,7 @@ impl Session { ) -> ErrorGuaranteed { self.diagnostic().span_err(sp, msg) } - #[cfg_attr(not(bootstrap), rustc_lint_diagnostics)] + #[rustc_lint_diagnostics] pub fn span_err_with_code<S: Into<MultiSpan>>( &self, sp: S, @@ -448,7 +448,7 @@ impl Session { ) { self.diagnostic().span_err_with_code(sp, msg, code) } - #[cfg_attr(not(bootstrap), rustc_lint_diagnostics)] + #[rustc_lint_diagnostics] pub fn err(&self, msg: impl Into<DiagnosticMessage>) -> ErrorGuaranteed { self.diagnostic().err(msg) } diff --git a/compiler/rustc_span/src/symbol.rs b/compiler/rustc_span/src/symbol.rs index 4e28d2b6001..65a2a18e02f 100644 --- a/compiler/rustc_span/src/symbol.rs +++ b/compiler/rustc_span/src/symbol.rs @@ -173,6 +173,7 @@ symbols! { DebugTuple, Decodable, Decoder, + DecorateLint, Default, Deref, DiagnosticMessage, diff --git a/compiler/rustc_symbol_mangling/src/legacy.rs b/compiler/rustc_symbol_mangling/src/legacy.rs index f67b87a6a52..470438471cb 100644 --- a/compiler/rustc_symbol_mangling/src/legacy.rs +++ b/compiler/rustc_symbol_mangling/src/legacy.rs @@ -3,7 +3,7 @@ use rustc_hir::def_id::CrateNum; use rustc_hir::definitions::{DefPathData, DisambiguatedDefPathData}; use rustc_middle::ty::print::{PrettyPrinter, Print, Printer}; use rustc_middle::ty::subst::{GenericArg, GenericArgKind}; -use rustc_middle::ty::{self, Instance, Ty, TyCtxt, TypeFoldable}; +use rustc_middle::ty::{self, Instance, Ty, TyCtxt, TypeVisitable}; use rustc_middle::util::common::record_time; use tracing::debug; diff --git a/compiler/rustc_symbol_mangling/src/v0.rs b/compiler/rustc_symbol_mangling/src/v0.rs index 1036c5d941b..13229a3995c 100644 --- a/compiler/rustc_symbol_mangling/src/v0.rs +++ b/compiler/rustc_symbol_mangling/src/v0.rs @@ -9,7 +9,7 @@ use rustc_middle::ty::layout::IntegerExt; use rustc_middle::ty::print::{Print, Printer}; use rustc_middle::ty::subst::{GenericArg, GenericArgKind, Subst}; use rustc_middle::ty::{ - self, EarlyBinder, FloatTy, Instance, IntTy, Ty, TyCtxt, TypeFoldable, UintTy, + self, EarlyBinder, FloatTy, Instance, IntTy, Ty, TyCtxt, TypeVisitable, UintTy, }; use rustc_span::symbol::kw; use rustc_target::abi::call::FnAbi; @@ -240,7 +240,7 @@ impl<'tcx> SymbolMangler<'tcx> { print_value: impl FnOnce(&'a mut Self, &T) -> Result<&'a mut Self, !>, ) -> Result<&'a mut Self, !> where - T: TypeFoldable<'tcx>, + T: TypeVisitable<'tcx>, { let regions = if value.has_late_bound_regions() { self.tcx.collect_referenced_late_bound_regions(value) diff --git a/compiler/rustc_trait_selection/src/autoderef.rs b/compiler/rustc_trait_selection/src/autoderef.rs index 5b88cff03d7..8b7e8984a8a 100644 --- a/compiler/rustc_trait_selection/src/autoderef.rs +++ b/compiler/rustc_trait_selection/src/autoderef.rs @@ -4,7 +4,7 @@ use rustc_errors::struct_span_err; use rustc_hir as hir; use rustc_infer::infer::InferCtxt; use rustc_middle::ty::{self, TraitRef, Ty, TyCtxt}; -use rustc_middle::ty::{ToPredicate, TypeFoldable}; +use rustc_middle::ty::{ToPredicate, TypeVisitable}; use rustc_session::Limit; use rustc_span::def_id::LOCAL_CRATE; use rustc_span::Span; diff --git a/compiler/rustc_trait_selection/src/infer.rs b/compiler/rustc_trait_selection/src/infer.rs index f135f0c1b13..9d30374f8b8 100644 --- a/compiler/rustc_trait_selection/src/infer.rs +++ b/compiler/rustc_trait_selection/src/infer.rs @@ -9,7 +9,7 @@ use rustc_middle::infer::canonical::{Canonical, CanonicalizedQueryResponse, Quer use rustc_middle::traits::query::Fallible; use rustc_middle::ty::subst::SubstsRef; use rustc_middle::ty::ToPredicate; -use rustc_middle::ty::{self, Ty, TypeFoldable}; +use rustc_middle::ty::{self, Ty, TypeFoldable, TypeVisitable}; use rustc_span::{Span, DUMMY_SP}; use std::fmt::Debug; diff --git a/compiler/rustc_trait_selection/src/opaque_types.rs b/compiler/rustc_trait_selection/src/opaque_types.rs index 9dd8588cece..d290f7b074c 100644 --- a/compiler/rustc_trait_selection/src/opaque_types.rs +++ b/compiler/rustc_trait_selection/src/opaque_types.rs @@ -9,6 +9,7 @@ use rustc_infer::infer::{InferCtxt, TyCtxtInferExt as _}; use rustc_infer::traits::{Obligation, ObligationCause, TraitEngine}; use rustc_middle::ty::fold::{TypeFoldable, TypeFolder, TypeSuperFoldable}; use rustc_middle::ty::subst::{GenericArg, GenericArgKind, InternalSubsts}; +use rustc_middle::ty::visit::TypeVisitable; use rustc_middle::ty::{self, OpaqueHiddenType, OpaqueTypeKey, ToPredicate, Ty, TyCtxt}; use rustc_span::Span; diff --git a/compiler/rustc_trait_selection/src/traits/auto_trait.rs b/compiler/rustc_trait_selection/src/traits/auto_trait.rs index 90ff07cba02..65ff9ceb67e 100644 --- a/compiler/rustc_trait_selection/src/traits/auto_trait.rs +++ b/compiler/rustc_trait_selection/src/traits/auto_trait.rs @@ -8,6 +8,7 @@ use crate::infer::InferCtxt; use crate::traits::project::ProjectAndUnifyResult; use rustc_middle::mir::interpret::ErrorHandled; use rustc_middle::ty::fold::{TypeFolder, TypeSuperFoldable}; +use rustc_middle::ty::visit::TypeVisitable; use rustc_middle::ty::{Region, RegionVid, Term}; use rustc_data_structures::fx::{FxHashMap, FxHashSet}; @@ -212,15 +213,7 @@ impl<'tcx> AutoTraitFinder<'tcx> { panic!("Unable to fulfill trait {:?} for '{:?}': {:?}", trait_did, ty, errors); } - let body_id_map: FxHashMap<_, _> = infcx - .inner - .borrow() - .region_obligations() - .iter() - .map(|&(id, _)| (id, vec![])) - .collect(); - - infcx.process_registered_region_obligations(&body_id_map, full_env); + infcx.process_registered_region_obligations(&Default::default(), full_env); let region_data = infcx .inner diff --git a/compiler/rustc_trait_selection/src/traits/chalk_fulfill.rs b/compiler/rustc_trait_selection/src/traits/chalk_fulfill.rs index 592b0ab477a..9ef7ac9a8e0 100644 --- a/compiler/rustc_trait_selection/src/traits/chalk_fulfill.rs +++ b/compiler/rustc_trait_selection/src/traits/chalk_fulfill.rs @@ -8,7 +8,7 @@ use crate::traits::{ PredicateObligation, SelectionError, TraitEngine, }; use rustc_data_structures::fx::{FxHashMap, FxIndexSet}; -use rustc_middle::ty::{self, Ty, TypeFoldable}; +use rustc_middle::ty::{self, Ty, TypeVisitable}; pub struct FulfillmentContext<'tcx> { obligations: FxIndexSet<PredicateObligation<'tcx>>, diff --git a/compiler/rustc_trait_selection/src/traits/coherence.rs b/compiler/rustc_trait_selection/src/traits/coherence.rs index 2b26b916d32..f933f1c3c94 100644 --- a/compiler/rustc_trait_selection/src/traits/coherence.rs +++ b/compiler/rustc_trait_selection/src/traits/coherence.rs @@ -16,13 +16,12 @@ use crate::traits::{ //use rustc_data_structures::fx::FxHashMap; use rustc_errors::Diagnostic; use rustc_hir::def_id::{DefId, LOCAL_CRATE}; -use rustc_hir::CRATE_HIR_ID; use rustc_infer::infer::{InferCtxt, TyCtxtInferExt}; use rustc_infer::traits::{util, TraitEngine}; use rustc_middle::traits::specialization_graph::OverlapMode; use rustc_middle::ty::fast_reject::{DeepRejectCtxt, TreatParams}; -use rustc_middle::ty::fold::TypeFoldable; use rustc_middle::ty::subst::Subst; +use rustc_middle::ty::visit::TypeVisitable; use rustc_middle::ty::{self, ImplSubject, Ty, TyCtxt}; use rustc_span::symbol::sym; use rustc_span::DUMMY_SP; @@ -317,14 +316,13 @@ fn negative_impl<'cx, 'tcx>( let (subject2, obligations) = impl_subject_and_oblig(selcx, impl_env, impl2_def_id, impl2_substs); - !equate(&infcx, impl_env, impl1_def_id, subject1, subject2, obligations) + !equate(&infcx, impl_env, subject1, subject2, obligations) }) } fn equate<'cx, 'tcx>( infcx: &InferCtxt<'cx, 'tcx>, impl_env: ty::ParamEnv<'tcx>, - impl1_def_id: DefId, subject1: ImplSubject<'tcx>, subject2: ImplSubject<'tcx>, obligations: impl Iterator<Item = PredicateObligation<'tcx>>, @@ -341,7 +339,7 @@ fn equate<'cx, 'tcx>( let opt_failing_obligation = obligations .into_iter() .chain(more_obligations) - .find(|o| negative_impl_exists(selcx, impl_env, impl1_def_id, o)); + .find(|o| negative_impl_exists(selcx, impl_env, o)); if let Some(failing_obligation) = opt_failing_obligation { debug!("overlap: obligation unsatisfiable {:?}", failing_obligation); @@ -356,18 +354,17 @@ fn equate<'cx, 'tcx>( fn negative_impl_exists<'cx, 'tcx>( selcx: &SelectionContext<'cx, 'tcx>, param_env: ty::ParamEnv<'tcx>, - region_context: DefId, o: &PredicateObligation<'tcx>, ) -> bool { let infcx = &selcx.infcx().fork(); - if resolve_negative_obligation(infcx, param_env, region_context, o) { + if resolve_negative_obligation(infcx, param_env, o) { return true; } // Try to prove a negative obligation exists for super predicates for o in util::elaborate_predicates(infcx.tcx, iter::once(o.predicate)) { - if resolve_negative_obligation(infcx, param_env, region_context, &o) { + if resolve_negative_obligation(infcx, param_env, &o) { return true; } } @@ -379,7 +376,6 @@ fn negative_impl_exists<'cx, 'tcx>( fn resolve_negative_obligation<'cx, 'tcx>( infcx: &InferCtxt<'cx, 'tcx>, param_env: ty::ParamEnv<'tcx>, - region_context: DefId, o: &PredicateObligation<'tcx>, ) -> bool { let tcx = infcx.tcx; @@ -397,19 +393,11 @@ fn resolve_negative_obligation<'cx, 'tcx>( return false; } - let mut outlives_env = OutlivesEnvironment::new(param_env); - // FIXME -- add "assumed to be well formed" types into the `outlives_env` - - // "Save" the accumulated implied bounds into the outlives environment - // (due to the FIXME above, there aren't any, but this step is still needed). - // The "body id" is given as `CRATE_HIR_ID`, which is the same body-id used - // by the "dummy" causes elsewhere (body-id is only relevant when checking - // function bodies with closures). - outlives_env.save_implied_bounds(CRATE_HIR_ID); - - infcx.process_registered_region_obligations(outlives_env.region_bound_pairs_map(), param_env); + // FIXME -- also add "assumed to be well formed" types into the `outlives_env` + let outlives_env = OutlivesEnvironment::new(param_env); + infcx.process_registered_region_obligations(outlives_env.region_bound_pairs(), param_env); - let errors = infcx.resolve_regions(region_context, &outlives_env); + let errors = infcx.resolve_regions(&outlives_env); if !errors.is_empty() { return false; diff --git a/compiler/rustc_trait_selection/src/traits/const_evaluatable.rs b/compiler/rustc_trait_selection/src/traits/const_evaluatable.rs index 424eff2f621..f9b4a1583cc 100644 --- a/compiler/rustc_trait_selection/src/traits/const_evaluatable.rs +++ b/compiler/rustc_trait_selection/src/traits/const_evaluatable.rs @@ -17,7 +17,7 @@ use rustc_middle::mir::interpret::{ErrorHandled, LitToConstError, LitToConstInpu use rustc_middle::thir; use rustc_middle::thir::abstract_const::{self, Node, NodeId, NotConstEvaluatable}; use rustc_middle::ty::subst::{Subst, SubstsRef}; -use rustc_middle::ty::{self, DelaySpanBugEmitted, EarlyBinder, TyCtxt, TypeFoldable}; +use rustc_middle::ty::{self, DelaySpanBugEmitted, EarlyBinder, TyCtxt, TypeVisitable}; use rustc_session::lint; use rustc_span::def_id::LocalDefId; use rustc_span::Span; diff --git a/compiler/rustc_trait_selection/src/traits/error_reporting/mod.rs b/compiler/rustc_trait_selection/src/traits/error_reporting/mod.rs index debb9e82951..8fd58f3ce1a 100644 --- a/compiler/rustc_trait_selection/src/traits/error_reporting/mod.rs +++ b/compiler/rustc_trait_selection/src/traits/error_reporting/mod.rs @@ -30,6 +30,7 @@ use rustc_middle::ty::error::ExpectedFound; use rustc_middle::ty::fold::{TypeFolder, TypeSuperFoldable}; use rustc_middle::ty::{ self, SubtypePredicate, ToPolyTraitRef, ToPredicate, TraitRef, Ty, TyCtxt, TypeFoldable, + TypeVisitable, }; use rustc_span::symbol::{kw, sym}; use rustc_span::{ExpnKind, Span, DUMMY_SP}; @@ -1958,26 +1959,6 @@ impl<'a, 'tcx> InferCtxtPrivExt<'a, 'tcx> for InferCtxt<'a, 'tcx> { if predicate.references_error() { return; } - // Typically, this ambiguity should only happen if - // there are unresolved type inference variables - // (otherwise it would suggest a coherence - // failure). But given #21974 that is not necessarily - // the case -- we can have multiple where clauses that - // are only distinguished by a region, which results - // in an ambiguity even when all types are fully - // known, since we don't dispatch based on region - // relationships. - - // Pick the first substitution that still contains inference variables as the one - // we're going to emit an error for. If there are none (see above), fall back to - // the substitution for `Self`. - let subst = { - let substs = data.trait_ref.substs; - substs - .iter() - .find(|s| s.has_infer_types_or_consts()) - .unwrap_or_else(|| substs[0]) - }; // This is kind of a hack: it frequently happens that some earlier // error prevents types from being fully inferred, and then we get @@ -1999,27 +1980,41 @@ impl<'a, 'tcx> InferCtxtPrivExt<'a, 'tcx> for InferCtxt<'a, 'tcx> { self.emit_inference_failure_err( body_id, span, - subst, - vec![], + trait_ref.self_ty().skip_binder().into(), ErrorCode::E0282, + false, ) .emit(); } return; } - let impl_candidates = self - .find_similar_impl_candidates(trait_ref) - .into_iter() - .map(|candidate| candidate.trait_ref) - .collect(); - let mut err = self.emit_inference_failure_err( - body_id, - span, - subst, - impl_candidates, - ErrorCode::E0283, - ); + // Typically, this ambiguity should only happen if + // there are unresolved type inference variables + // (otherwise it would suggest a coherence + // failure). But given #21974 that is not necessarily + // the case -- we can have multiple where clauses that + // are only distinguished by a region, which results + // in an ambiguity even when all types are fully + // known, since we don't dispatch based on region + // relationships. + + // Pick the first substitution that still contains inference variables as the one + // we're going to emit an error for. If there are none (see above), fall back to + // a more general error. + let subst = data.trait_ref.substs.iter().find(|s| s.has_infer_types_or_consts()); + + let mut err = if let Some(subst) = subst { + self.emit_inference_failure_err(body_id, span, subst, ErrorCode::E0283, true) + } else { + struct_span_err!( + self.tcx.sess, + span, + E0283, + "type annotations needed: cannot satisfy `{}`", + predicate, + ) + }; let obligation = Obligation::new( obligation.cause.clone(), @@ -2110,7 +2105,7 @@ impl<'a, 'tcx> InferCtxtPrivExt<'a, 'tcx> for InferCtxt<'a, 'tcx> { return; } - self.emit_inference_failure_err(body_id, span, arg, vec![], ErrorCode::E0282) + self.emit_inference_failure_err(body_id, span, arg, ErrorCode::E0282, false) } ty::PredicateKind::Subtype(data) => { @@ -2124,26 +2119,30 @@ impl<'a, 'tcx> InferCtxtPrivExt<'a, 'tcx> for InferCtxt<'a, 'tcx> { let SubtypePredicate { a_is_expected: _, a, b } = data; // both must be type variables, or the other would've been instantiated assert!(a.is_ty_var() && b.is_ty_var()); - self.emit_inference_failure_err(body_id, span, a.into(), vec![], ErrorCode::E0282) + self.emit_inference_failure_err(body_id, span, a.into(), ErrorCode::E0282, true) } ty::PredicateKind::Projection(data) => { - let self_ty = data.projection_ty.self_ty(); - let term = data.term; if predicate.references_error() || self.is_tainted_by_errors() { return; } - if self_ty.needs_infer() && term.needs_infer() { - // We do this for the `foo.collect()?` case to produce a suggestion. + let subst = data + .projection_ty + .substs + .iter() + .chain(Some(data.term.into_arg())) + .find(|g| g.has_infer_types_or_consts()); + if let Some(subst) = subst { let mut err = self.emit_inference_failure_err( body_id, span, - self_ty.into(), - vec![], + subst, ErrorCode::E0284, + true, ); err.note(&format!("cannot satisfy `{}`", predicate)); err } else { + // If we can't find a substitution, just print a generic error let mut err = struct_span_err!( self.tcx.sess, span, diff --git a/compiler/rustc_trait_selection/src/traits/error_reporting/suggestions.rs b/compiler/rustc_trait_selection/src/traits/error_reporting/suggestions.rs index a8be6f74c99..31d54b5b403 100644 --- a/compiler/rustc_trait_selection/src/traits/error_reporting/suggestions.rs +++ b/compiler/rustc_trait_selection/src/traits/error_reporting/suggestions.rs @@ -24,7 +24,7 @@ use rustc_middle::hir::map; use rustc_middle::ty::{ self, suggest_arbitrary_trait_bound, suggest_constraining_type_param, AdtKind, DefIdTree, GeneratorDiagnosticData, GeneratorInteriorTypeCause, Infer, InferTy, IsSuggestable, - ToPredicate, Ty, TyCtxt, TypeFoldable, TypeFolder, TypeSuperFoldable, + ToPredicate, Ty, TyCtxt, TypeFoldable, TypeFolder, TypeSuperFoldable, TypeVisitable, }; use rustc_middle::ty::{TypeAndMut, TypeckResults}; use rustc_session::Limit; diff --git a/compiler/rustc_trait_selection/src/traits/fulfill.rs b/compiler/rustc_trait_selection/src/traits/fulfill.rs index d61166437d7..78600652254 100644 --- a/compiler/rustc_trait_selection/src/traits/fulfill.rs +++ b/compiler/rustc_trait_selection/src/traits/fulfill.rs @@ -10,7 +10,7 @@ use rustc_middle::thir::abstract_const::NotConstEvaluatable; use rustc_middle::ty::error::{ExpectedFound, TypeError}; use rustc_middle::ty::subst::SubstsRef; use rustc_middle::ty::ToPredicate; -use rustc_middle::ty::{self, Binder, Const, Ty, TypeFoldable}; +use rustc_middle::ty::{self, Binder, Const, Ty, TypeVisitable}; use std::marker::PhantomData; use super::const_evaluatable; @@ -131,8 +131,6 @@ impl<'a, 'tcx> FulfillmentContext<'tcx> { let span = debug_span!("select", obligation_forest_size = ?self.predicates.len()); let _enter = span.enter(); - let mut errors = Vec::new(); - // Process pending obligations. let outcome: Outcome<_, _> = self.predicates.process_obligations(&mut FulfillProcessor { selcx, @@ -142,7 +140,8 @@ impl<'a, 'tcx> FulfillmentContext<'tcx> { // FIXME: if we kept the original cache key, we could mark projection // obligations as complete for the projection cache here. - errors.extend(outcome.errors.into_iter().map(to_fulfillment_error)); + let errors: Vec<FulfillmentError<'tcx>> = + outcome.errors.into_iter().map(to_fulfillment_error).collect(); debug!( "select({} predicates remaining, {} errors) done", @@ -728,7 +727,7 @@ impl<'a, 'b, 'tcx> FulfillProcessor<'a, 'b, 'tcx> { } return ProcessResult::Changed(vec![]); } else { - tracing::debug!("Does NOT hold: {:?}", obligation); + debug!("Does NOT hold: {:?}", obligation); } } diff --git a/compiler/rustc_trait_selection/src/traits/misc.rs b/compiler/rustc_trait_selection/src/traits/misc.rs index f04f527ccb7..dd2769c7186 100644 --- a/compiler/rustc_trait_selection/src/traits/misc.rs +++ b/compiler/rustc_trait_selection/src/traits/misc.rs @@ -5,7 +5,7 @@ use crate::traits::{self, ObligationCause}; use rustc_hir as hir; use rustc_infer::infer::TyCtxtInferExt; -use rustc_middle::ty::{self, Ty, TyCtxt, TypeFoldable}; +use rustc_middle::ty::{self, Ty, TyCtxt, TypeVisitable}; use crate::traits::error_reporting::InferCtxtExt; diff --git a/compiler/rustc_trait_selection/src/traits/mod.rs b/compiler/rustc_trait_selection/src/traits/mod.rs index 34b0f431b8e..74d2eb17b6b 100644 --- a/compiler/rustc_trait_selection/src/traits/mod.rs +++ b/compiler/rustc_trait_selection/src/traits/mod.rs @@ -32,6 +32,7 @@ use rustc_hir::def_id::DefId; use rustc_hir::lang_items::LangItem; use rustc_middle::ty::fold::TypeFoldable; use rustc_middle::ty::subst::{InternalSubsts, SubstsRef}; +use rustc_middle::ty::visit::TypeVisitable; use rustc_middle::ty::{self, GenericParamDefKind, ToPredicate, Ty, TyCtxt, VtblEntry}; use rustc_span::{sym, Span}; use smallvec::SmallVec; @@ -198,17 +199,13 @@ pub fn type_known_to_meet_bound_modulo_regions<'a, 'tcx>( } } +#[instrument(level = "debug", skip(tcx, elaborated_env))] fn do_normalize_predicates<'tcx>( tcx: TyCtxt<'tcx>, - region_context: DefId, cause: ObligationCause<'tcx>, elaborated_env: ty::ParamEnv<'tcx>, predicates: Vec<ty::Predicate<'tcx>>, ) -> Result<Vec<ty::Predicate<'tcx>>, ErrorGuaranteed> { - debug!( - "do_normalize_predicates(predicates={:?}, region_context={:?}, cause={:?})", - predicates, region_context, cause, - ); let span = cause.span; tcx.infer_ctxt().enter(|infcx| { // FIXME. We should really... do something with these region @@ -240,7 +237,7 @@ fn do_normalize_predicates<'tcx>( // cares about declarations like `'a: 'b`. let outlives_env = OutlivesEnvironment::new(elaborated_env); - infcx.resolve_regions_and_report_errors(region_context, &outlives_env); + infcx.resolve_regions_and_report_errors(&outlives_env); let predicates = match infcx.fully_resolve(predicates) { Ok(predicates) => predicates, @@ -269,9 +266,9 @@ fn do_normalize_predicates<'tcx>( // FIXME: this is gonna need to be removed ... /// Normalizes the parameter environment, reporting errors if they occur. +#[instrument(level = "debug", skip(tcx))] pub fn normalize_param_env_or_error<'tcx>( tcx: TyCtxt<'tcx>, - region_context: DefId, unnormalized_env: ty::ParamEnv<'tcx>, cause: ObligationCause<'tcx>, ) -> ty::ParamEnv<'tcx> { @@ -289,12 +286,6 @@ pub fn normalize_param_env_or_error<'tcx>( // parameter environments once for every fn as it goes, // and errors will get reported then; so outside of type inference we // can be sure that no errors should occur. - - debug!( - "normalize_param_env_or_error(region_context={:?}, unnormalized_env={:?}, cause={:?})", - region_context, unnormalized_env, cause - ); - let mut predicates: Vec<_> = util::elaborate_predicates(tcx, unnormalized_env.caller_bounds().into_iter()) .map(|obligation| obligation.predicate) @@ -338,7 +329,6 @@ pub fn normalize_param_env_or_error<'tcx>( ); let Ok(non_outlives_predicates) = do_normalize_predicates( tcx, - region_context, cause.clone(), elaborated_env, predicates, @@ -362,7 +352,6 @@ pub fn normalize_param_env_or_error<'tcx>( ); let Ok(outlives_predicates) = do_normalize_predicates( tcx, - region_context, cause, outlives_env, outlives_predicates, diff --git a/compiler/rustc_trait_selection/src/traits/object_safety.rs b/compiler/rustc_trait_selection/src/traits/object_safety.rs index 8d344591915..ac1811244ca 100644 --- a/compiler/rustc_trait_selection/src/traits/object_safety.rs +++ b/compiler/rustc_trait_selection/src/traits/object_safety.rs @@ -19,7 +19,7 @@ use rustc_hir as hir; use rustc_hir::def_id::DefId; use rustc_middle::ty::subst::{GenericArg, InternalSubsts, Subst}; use rustc_middle::ty::{ - self, EarlyBinder, Ty, TyCtxt, TypeFoldable, TypeSuperFoldable, TypeVisitor, + self, EarlyBinder, Ty, TyCtxt, TypeSuperVisitable, TypeVisitable, TypeVisitor, }; use rustc_middle::ty::{Predicate, ToPredicate}; use rustc_session::lint::builtin::WHERE_CLAUSES_OBJECT_SAFETY; @@ -731,7 +731,7 @@ fn receiver_is_dispatchable<'tcx>( }) } -fn contains_illegal_self_type_reference<'tcx, T: TypeFoldable<'tcx>>( +fn contains_illegal_self_type_reference<'tcx, T: TypeVisitable<'tcx>>( tcx: TyCtxt<'tcx>, trait_def_id: DefId, value: T, diff --git a/compiler/rustc_trait_selection/src/traits/project.rs b/compiler/rustc_trait_selection/src/traits/project.rs index aba4f144d4b..b3e7fbb3578 100644 --- a/compiler/rustc_trait_selection/src/traits/project.rs +++ b/compiler/rustc_trait_selection/src/traits/project.rs @@ -29,8 +29,9 @@ use rustc_hir::def_id::DefId; use rustc_hir::lang_items::LangItem; use rustc_infer::infer::resolve::OpportunisticRegionResolver; use rustc_middle::traits::select::OverflowError; -use rustc_middle::ty::fold::{MaxUniverse, TypeFoldable, TypeFolder, TypeSuperFoldable}; +use rustc_middle::ty::fold::{TypeFoldable, TypeFolder, TypeSuperFoldable}; use rustc_middle::ty::subst::Subst; +use rustc_middle::ty::visit::{MaxUniverse, TypeVisitable}; use rustc_middle::ty::{self, EarlyBinder, Term, ToPredicate, Ty, TyCtxt}; use rustc_span::symbol::sym; @@ -359,7 +360,7 @@ where result } -pub(crate) fn needs_normalization<'tcx, T: TypeFoldable<'tcx>>(value: &T, reveal: Reveal) -> bool { +pub(crate) fn needs_normalization<'tcx, T: TypeVisitable<'tcx>>(value: &T, reveal: Reveal) -> bool { match reveal { Reveal::UserFacing => value .has_type_flags(ty::TypeFlags::HAS_TY_PROJECTION | ty::TypeFlags::HAS_CT_PROJECTION), diff --git a/compiler/rustc_trait_selection/src/traits/query/dropck_outlives.rs b/compiler/rustc_trait_selection/src/traits/query/dropck_outlives.rs index 25cc6e9f9f2..aad3c37f84e 100644 --- a/compiler/rustc_trait_selection/src/traits/query/dropck_outlives.rs +++ b/compiler/rustc_trait_selection/src/traits/query/dropck_outlives.rs @@ -1,73 +1,7 @@ -use crate::infer::at::At; -use crate::infer::canonical::OriginalQueryValues; -use crate::infer::InferOk; - -use rustc_middle::ty::subst::GenericArg; use rustc_middle::ty::{self, Ty, TyCtxt}; pub use rustc_middle::traits::query::{DropckConstraint, DropckOutlivesResult}; -pub trait AtExt<'tcx> { - fn dropck_outlives(&self, ty: Ty<'tcx>) -> InferOk<'tcx, Vec<GenericArg<'tcx>>>; -} - -impl<'cx, 'tcx> AtExt<'tcx> for At<'cx, 'tcx> { - /// Given a type `ty` of some value being dropped, computes a set - /// of "kinds" (types, regions) that must be outlive the execution - /// of the destructor. These basically correspond to data that the - /// destructor might access. This is used during regionck to - /// impose "outlives" constraints on any lifetimes referenced - /// within. - /// - /// The rules here are given by the "dropck" RFCs, notably [#1238] - /// and [#1327]. This is a fixed-point computation, where we - /// explore all the data that will be dropped (transitively) when - /// a value of type `ty` is dropped. For each type T that will be - /// dropped and which has a destructor, we must assume that all - /// the types/regions of T are live during the destructor, unless - /// they are marked with a special attribute (`#[may_dangle]`). - /// - /// [#1238]: https://github.com/rust-lang/rfcs/blob/master/text/1238-nonparametric-dropck.md - /// [#1327]: https://github.com/rust-lang/rfcs/blob/master/text/1327-dropck-param-eyepatch.md - fn dropck_outlives(&self, ty: Ty<'tcx>) -> InferOk<'tcx, Vec<GenericArg<'tcx>>> { - debug!("dropck_outlives(ty={:?}, param_env={:?})", ty, self.param_env,); - - // Quick check: there are a number of cases that we know do not require - // any destructor. - let tcx = self.infcx.tcx; - if trivial_dropck_outlives(tcx, ty) { - return InferOk { value: vec![], obligations: vec![] }; - } - - let mut orig_values = OriginalQueryValues::default(); - let c_ty = self.infcx.canonicalize_query(self.param_env.and(ty), &mut orig_values); - let span = self.cause.span; - debug!("c_ty = {:?}", c_ty); - if let Ok(result) = tcx.dropck_outlives(c_ty) - && result.is_proven() - && let Ok(InferOk { value, obligations }) = - self.infcx.instantiate_query_response_and_region_obligations( - self.cause, - self.param_env, - &orig_values, - result, - ) - { - let ty = self.infcx.resolve_vars_if_possible(ty); - let kinds = value.into_kinds_reporting_overflows(tcx, span, ty); - return InferOk { value: kinds, obligations }; - } - - // Errors and ambiguity in dropck occur in two cases: - // - unresolved inference variables at the end of typeck - // - non well-formed types where projections cannot be resolved - // Either of these should have created an error before. - tcx.sess.delay_span_bug(span, "dtorck encountered internal error"); - - InferOk { value: vec![], obligations: vec![] } - } -} - /// This returns true if the type `ty` is "trivial" for /// dropck-outlives -- that is, if it doesn't require any types to /// outlive. This is similar but not *quite* the same as the @@ -79,6 +13,8 @@ impl<'cx, 'tcx> AtExt<'tcx> for At<'cx, 'tcx> { /// /// Note also that `needs_drop` requires a "global" type (i.e., one /// with erased regions), but this function does not. +/// +// FIXME(@lcnr): remove this module and move this function somewhere else. pub fn trivial_dropck_outlives<'tcx>(tcx: TyCtxt<'tcx>, ty: Ty<'tcx>) -> bool { match ty.kind() { // None of these types have a destructor and hence they do not @@ -105,7 +41,7 @@ pub fn trivial_dropck_outlives<'tcx>(tcx: TyCtxt<'tcx>, ty: Ty<'tcx>) -> bool { ty::Array(ty, _) | ty::Slice(ty) => trivial_dropck_outlives(tcx, *ty), // (T1..Tn) and closures have same properties as T1..Tn -- - // check if *any* of those are trivial. + // check if *all* of them are trivial. ty::Tuple(tys) => tys.iter().all(|t| trivial_dropck_outlives(tcx, t)), ty::Closure(_, ref substs) => { trivial_dropck_outlives(tcx, substs.as_closure().tupled_upvars_ty()) diff --git a/compiler/rustc_trait_selection/src/traits/query/normalize.rs b/compiler/rustc_trait_selection/src/traits/query/normalize.rs index 7f15b683fda..eccfb3477b9 100644 --- a/compiler/rustc_trait_selection/src/traits/query/normalize.rs +++ b/compiler/rustc_trait_selection/src/traits/query/normalize.rs @@ -14,6 +14,7 @@ use rustc_infer::traits::Normalized; use rustc_middle::mir; use rustc_middle::ty::fold::{FallibleTypeFolder, TypeFoldable, TypeSuperFoldable}; use rustc_middle::ty::subst::Subst; +use rustc_middle::ty::visit::{TypeSuperVisitable, TypeVisitable}; use rustc_middle::ty::{self, Ty, TyCtxt, TypeVisitor}; use std::ops::ControlFlow; @@ -108,7 +109,7 @@ struct MaxEscapingBoundVarVisitor { } impl<'tcx> TypeVisitor<'tcx> for MaxEscapingBoundVarVisitor { - fn visit_binder<T: TypeFoldable<'tcx>>( + fn visit_binder<T: TypeVisitable<'tcx>>( &mut self, t: &ty::Binder<'tcx, T>, ) -> ControlFlow<Self::BreakTy> { diff --git a/compiler/rustc_trait_selection/src/traits/query/type_op/custom.rs b/compiler/rustc_trait_selection/src/traits/query/type_op/custom.rs index 605c9ace5ed..c9d46b2810d 100644 --- a/compiler/rustc_trait_selection/src/traits/query/type_op/custom.rs +++ b/compiler/rustc_trait_selection/src/traits/query/type_op/custom.rs @@ -95,7 +95,7 @@ pub fn scrape_region_constraints<'tcx, Op: super::TypeOp<'tcx, Output = R>, R>( infcx.tcx, region_obligations .iter() - .map(|(_, r_o)| (r_o.sup_type, r_o.sub_region)) + .map(|r_o| (r_o.sup_type, r_o.sub_region)) .map(|(ty, r)| (infcx.resolve_vars_if_possible(ty), r)), ®ion_constraint_data, ); diff --git a/compiler/rustc_trait_selection/src/traits/query/type_op/implied_outlives_bounds.rs b/compiler/rustc_trait_selection/src/traits/query/type_op/implied_outlives_bounds.rs index 46d6e973d4c..2a3319f0f26 100644 --- a/compiler/rustc_trait_selection/src/traits/query/type_op/implied_outlives_bounds.rs +++ b/compiler/rustc_trait_selection/src/traits/query/type_op/implied_outlives_bounds.rs @@ -3,7 +3,7 @@ use crate::traits::query::Fallible; use rustc_infer::traits::query::OutlivesBound; use rustc_middle::ty::{self, ParamEnvAnd, Ty, TyCtxt}; -#[derive(Copy, Clone, Debug, HashStable, TypeFoldable, Lift)] +#[derive(Copy, Clone, Debug, HashStable, TypeFoldable, TypeVisitable, Lift)] pub struct ImpliedOutlivesBounds<'tcx> { pub ty: Ty<'tcx>, } diff --git a/compiler/rustc_trait_selection/src/traits/query/type_op/outlives.rs b/compiler/rustc_trait_selection/src/traits/query/type_op/outlives.rs index 82f147f8143..b63382429d0 100644 --- a/compiler/rustc_trait_selection/src/traits/query/type_op/outlives.rs +++ b/compiler/rustc_trait_selection/src/traits/query/type_op/outlives.rs @@ -3,7 +3,7 @@ use crate::traits::query::dropck_outlives::{trivial_dropck_outlives, DropckOutli use crate::traits::query::Fallible; use rustc_middle::ty::{ParamEnvAnd, Ty, TyCtxt}; -#[derive(Copy, Clone, Debug, HashStable, TypeFoldable, Lift)] +#[derive(Copy, Clone, Debug, HashStable, TypeFoldable, TypeVisitable, Lift)] pub struct DropckOutlives<'tcx> { dropped_ty: Ty<'tcx>, } diff --git a/compiler/rustc_trait_selection/src/traits/select/candidate_assembly.rs b/compiler/rustc_trait_selection/src/traits/select/candidate_assembly.rs index cfd50c1afb9..0f7af41cfe3 100644 --- a/compiler/rustc_trait_selection/src/traits/select/candidate_assembly.rs +++ b/compiler/rustc_trait_selection/src/traits/select/candidate_assembly.rs @@ -12,7 +12,7 @@ use rustc_infer::traits::TraitEngine; use rustc_infer::traits::{Obligation, SelectionError, TraitObligation}; use rustc_lint_defs::builtin::DEREF_INTO_DYN_SUPERTRAIT; use rustc_middle::ty::print::with_no_trimmed_paths; -use rustc_middle::ty::{self, ToPredicate, Ty, TypeFoldable}; +use rustc_middle::ty::{self, ToPredicate, Ty, TypeVisitable}; use rustc_target::spec::abi::Abi; use crate::traits; diff --git a/compiler/rustc_trait_selection/src/traits/select/mod.rs b/compiler/rustc_trait_selection/src/traits/select/mod.rs index 4223cdb5dbb..596ee435622 100644 --- a/compiler/rustc_trait_selection/src/traits/select/mod.rs +++ b/compiler/rustc_trait_selection/src/traits/select/mod.rs @@ -39,7 +39,7 @@ use rustc_middle::ty::print::with_no_trimmed_paths; use rustc_middle::ty::relate::TypeRelation; use rustc_middle::ty::subst::{Subst, SubstsRef}; use rustc_middle::ty::{self, EarlyBinder, PolyProjectionPredicate, ToPolyTraitRef, ToPredicate}; -use rustc_middle::ty::{Ty, TyCtxt, TypeFoldable}; +use rustc_middle::ty::{Ty, TyCtxt, TypeFoldable, TypeVisitable}; use rustc_span::symbol::sym; use std::cell::{Cell, RefCell}; diff --git a/compiler/rustc_trait_selection/src/traits/specialize/mod.rs b/compiler/rustc_trait_selection/src/traits/specialize/mod.rs index a1861529b59..7efb0360b7f 100644 --- a/compiler/rustc_trait_selection/src/traits/specialize/mod.rs +++ b/compiler/rustc_trait_selection/src/traits/specialize/mod.rs @@ -16,9 +16,8 @@ use crate::infer::{InferCtxt, InferOk, TyCtxtInferExt}; use crate::traits::select::IntercrateAmbiguityCause; use crate::traits::{self, coherence, FutureCompatOverlapErrorKind, ObligationCause, TraitEngine}; use rustc_data_structures::fx::FxHashSet; -use rustc_errors::{struct_span_err, EmissionGuarantee}; +use rustc_errors::{struct_span_err, EmissionGuarantee, LintDiagnosticBuilder}; use rustc_hir::def_id::{DefId, LocalDefId}; -use rustc_middle::lint::LintDiagnosticBuilder; use rustc_middle::ty::subst::{InternalSubsts, Subst, SubstsRef}; use rustc_middle::ty::{self, ImplSubject, TyCtxt}; use rustc_session::lint::builtin::COHERENCE_LEAK_CHECK; diff --git a/compiler/rustc_trait_selection/src/traits/specialize/specialization_graph.rs b/compiler/rustc_trait_selection/src/traits/specialize/specialization_graph.rs index 930c80e0abb..fcb73b43fa8 100644 --- a/compiler/rustc_trait_selection/src/traits/specialize/specialization_graph.rs +++ b/compiler/rustc_trait_selection/src/traits/specialize/specialization_graph.rs @@ -4,7 +4,7 @@ use crate::traits; use rustc_hir::def_id::DefId; use rustc_middle::ty::fast_reject::{self, SimplifiedType, TreatParams}; use rustc_middle::ty::print::with_no_trimmed_paths; -use rustc_middle::ty::{self, TyCtxt, TypeFoldable}; +use rustc_middle::ty::{self, TyCtxt, TypeVisitable}; pub use rustc_middle::traits::specialization_graph::*; diff --git a/compiler/rustc_trait_selection/src/traits/structural_match.rs b/compiler/rustc_trait_selection/src/traits/structural_match.rs index bc2ce31df6d..f3ae34ce30a 100644 --- a/compiler/rustc_trait_selection/src/traits/structural_match.rs +++ b/compiler/rustc_trait_selection/src/traits/structural_match.rs @@ -6,7 +6,7 @@ use rustc_data_structures::fx::FxHashSet; use rustc_hir as hir; use rustc_hir::lang_items::LangItem; use rustc_middle::ty::query::Providers; -use rustc_middle::ty::{self, AdtDef, Ty, TyCtxt, TypeFoldable, TypeSuperFoldable, TypeVisitor}; +use rustc_middle::ty::{self, AdtDef, Ty, TyCtxt, TypeSuperVisitable, TypeVisitable, TypeVisitor}; use rustc_span::Span; use std::ops::ControlFlow; diff --git a/compiler/rustc_trait_selection/src/traits/util.rs b/compiler/rustc_trait_selection/src/traits/util.rs index 3a00c41d90a..3170b29ee69 100644 --- a/compiler/rustc_trait_selection/src/traits/util.rs +++ b/compiler/rustc_trait_selection/src/traits/util.rs @@ -6,7 +6,7 @@ use smallvec::SmallVec; use rustc_data_structures::fx::FxHashSet; use rustc_hir::def_id::DefId; use rustc_middle::ty::subst::{GenericArg, Subst, SubstsRef}; -use rustc_middle::ty::{self, EarlyBinder, ImplSubject, ToPredicate, Ty, TyCtxt, TypeFoldable}; +use rustc_middle::ty::{self, EarlyBinder, ImplSubject, ToPredicate, Ty, TyCtxt, TypeVisitable}; use super::{Normalized, Obligation, ObligationCause, PredicateObligation, SelectionContext}; pub use rustc_infer::traits::{self, util::*}; diff --git a/compiler/rustc_trait_selection/src/traits/wf.rs b/compiler/rustc_trait_selection/src/traits/wf.rs index 8d666046ad9..d43b3c9091f 100644 --- a/compiler/rustc_trait_selection/src/traits/wf.rs +++ b/compiler/rustc_trait_selection/src/traits/wf.rs @@ -5,7 +5,7 @@ use rustc_hir as hir; use rustc_hir::def_id::DefId; use rustc_hir::lang_items::LangItem; use rustc_middle::ty::subst::{GenericArg, GenericArgKind, SubstsRef}; -use rustc_middle::ty::{self, ToPredicate, Ty, TyCtxt, TypeFoldable}; +use rustc_middle::ty::{self, ToPredicate, Ty, TyCtxt, TypeVisitable}; use rustc_span::Span; use std::iter; diff --git a/compiler/rustc_traits/src/chalk/lowering.rs b/compiler/rustc_traits/src/chalk/lowering.rs index 2453d3a692a..c7c604e14e3 100644 --- a/compiler/rustc_traits/src/chalk/lowering.rs +++ b/compiler/rustc_traits/src/chalk/lowering.rs @@ -35,7 +35,8 @@ use rustc_ast::ast; use rustc_middle::traits::{ChalkEnvironmentAndGoal, ChalkRustInterner as RustInterner}; use rustc_middle::ty::subst::{GenericArg, GenericArgKind, SubstsRef}; use rustc_middle::ty::{ - self, Binder, Region, Ty, TyCtxt, TypeFoldable, TypeFolder, TypeSuperFoldable, TypeVisitor, + self, Binder, Region, Ty, TyCtxt, TypeFoldable, TypeFolder, TypeSuperFoldable, + TypeSuperVisitable, TypeVisitable, TypeVisitor, }; use rustc_span::def_id::DefId; @@ -896,7 +897,7 @@ impl<'tcx> BoundVarsCollector<'tcx> { } impl<'tcx> TypeVisitor<'tcx> for BoundVarsCollector<'tcx> { - fn visit_binder<T: TypeFoldable<'tcx>>( + fn visit_binder<T: TypeVisitable<'tcx>>( &mut self, t: &Binder<'tcx, T>, ) -> ControlFlow<Self::BreakTy> { diff --git a/compiler/rustc_traits/src/chalk/mod.rs b/compiler/rustc_traits/src/chalk/mod.rs index 59cf37fee9c..db7ea4253e3 100644 --- a/compiler/rustc_traits/src/chalk/mod.rs +++ b/compiler/rustc_traits/src/chalk/mod.rs @@ -14,7 +14,7 @@ use rustc_middle::infer::canonical::{CanonicalTyVarKind, CanonicalVarKind}; use rustc_middle::traits::ChalkRustInterner; use rustc_middle::ty::query::Providers; use rustc_middle::ty::subst::GenericArg; -use rustc_middle::ty::{self, BoundVar, ParamTy, TyCtxt, TypeFoldable}; +use rustc_middle::ty::{self, BoundVar, ParamTy, TyCtxt, TypeFoldable, TypeVisitable}; use rustc_infer::infer::canonical::{ Canonical, CanonicalVarValues, Certainty, QueryRegionConstraints, QueryResponse, diff --git a/compiler/rustc_traits/src/implied_outlives_bounds.rs b/compiler/rustc_traits/src/implied_outlives_bounds.rs index ae48211d52d..c7cac8fca89 100644 --- a/compiler/rustc_traits/src/implied_outlives_bounds.rs +++ b/compiler/rustc_traits/src/implied_outlives_bounds.rs @@ -9,7 +9,7 @@ use rustc_infer::infer::{InferCtxt, TyCtxtInferExt}; use rustc_infer::traits::query::OutlivesBound; use rustc_infer::traits::TraitEngineExt as _; use rustc_middle::ty::query::Providers; -use rustc_middle::ty::{self, Ty, TyCtxt, TypeFoldable}; +use rustc_middle::ty::{self, Ty, TyCtxt, TypeVisitable}; use rustc_span::source_map::DUMMY_SP; use rustc_trait_selection::infer::InferCtxtBuilderExt; use rustc_trait_selection::traits::query::{CanonicalTyGoal, Fallible, NoSolution}; diff --git a/compiler/rustc_ty_utils/src/instance.rs b/compiler/rustc_ty_utils/src/instance.rs index 552db5406df..5e58f237982 100644 --- a/compiler/rustc_ty_utils/src/instance.rs +++ b/compiler/rustc_ty_utils/src/instance.rs @@ -4,7 +4,7 @@ use rustc_infer::infer::TyCtxtInferExt; use rustc_middle::traits::CodegenObligationError; use rustc_middle::ty::subst::SubstsRef; use rustc_middle::ty::{ - self, Binder, Instance, Ty, TyCtxt, TypeFoldable, TypeSuperFoldable, TypeVisitor, + self, Binder, Instance, Ty, TyCtxt, TypeSuperVisitable, TypeVisitable, TypeVisitor, }; use rustc_span::{sym, DUMMY_SP}; use rustc_trait_selection::traits; @@ -56,7 +56,7 @@ impl<'tcx> BoundVarsCollector<'tcx> { impl<'tcx> TypeVisitor<'tcx> for BoundVarsCollector<'tcx> { type BreakTy = (); - fn visit_binder<T: TypeFoldable<'tcx>>( + fn visit_binder<T: TypeVisitable<'tcx>>( &mut self, t: &Binder<'tcx, T>, ) -> ControlFlow<Self::BreakTy> { @@ -332,12 +332,12 @@ fn resolve_associated_item<'tcx>( }), traits::ImplSource::Closure(closure_data) => { let trait_closure_kind = tcx.fn_trait_kind_from_lang_item(trait_id).unwrap(); - Some(Instance::resolve_closure( + Instance::resolve_closure( tcx, closure_data.closure_def_id, closure_data.substs, trait_closure_kind, - )) + ) } traits::ImplSource::FnPointer(ref data) => match data.fn_ty.kind() { ty::FnDef(..) | ty::FnPtr(..) => Some(Instance { diff --git a/compiler/rustc_ty_utils/src/ty.rs b/compiler/rustc_ty_utils/src/ty.rs index 38ae6a25b18..1d345caf699 100644 --- a/compiler/rustc_ty_utils/src/ty.rs +++ b/compiler/rustc_ty_utils/src/ty.rs @@ -211,7 +211,7 @@ fn param_env(tcx: TyCtxt<'_>, def_id: DefId) -> ty::ParamEnv<'_> { tcx.hir().maybe_body_owned_by(id).map_or(id, |body| body.hir_id) }); let cause = traits::ObligationCause::misc(tcx.def_span(def_id), body_id); - traits::normalize_param_env_or_error(tcx, def_id, unnormalized_env, cause) + traits::normalize_param_env_or_error(tcx, unnormalized_env, cause) } /// Elaborate the environment. diff --git a/compiler/rustc_type_ir/src/lib.rs b/compiler/rustc_type_ir/src/lib.rs index f9708d6d919..6744536338c 100644 --- a/compiler/rustc_type_ir/src/lib.rs +++ b/compiler/rustc_type_ir/src/lib.rs @@ -599,6 +599,7 @@ impl UnifyKey for FloatVid { } #[derive(Copy, Clone, PartialEq, Decodable, Encodable, Hash)] +#[rustc_pass_by_value] pub enum Variance { Covariant, // T<A> <: T<B> iff A <: B -- e.g., function return type Invariant, // T<A> <: T<B> iff B == A -- e.g., type of mutable cell diff --git a/compiler/rustc_typeck/src/astconv/mod.rs b/compiler/rustc_typeck/src/astconv/mod.rs index eec3b24aec2..703277ec66a 100644 --- a/compiler/rustc_typeck/src/astconv/mod.rs +++ b/compiler/rustc_typeck/src/astconv/mod.rs @@ -28,7 +28,7 @@ use rustc_middle::middle::stability::AllowUnstable; use rustc_middle::ty::subst::{self, GenericArgKind, InternalSubsts, Subst, SubstsRef}; use rustc_middle::ty::GenericParamDefKind; use rustc_middle::ty::{ - self, Const, DefIdTree, EarlyBinder, IsSuggestable, Ty, TyCtxt, TypeFoldable, + self, Const, DefIdTree, EarlyBinder, IsSuggestable, Ty, TyCtxt, TypeVisitable, }; use rustc_session::lint::builtin::{AMBIGUOUS_ASSOCIATED_ITEMS, BARE_TRAIT_OBJECTS}; use rustc_span::edition::Edition; @@ -38,7 +38,9 @@ use rustc_span::{Span, DUMMY_SP}; use rustc_target::spec::abi; use rustc_trait_selection::traits; use rustc_trait_selection::traits::astconv_object_safety_violations; -use rustc_trait_selection::traits::error_reporting::report_object_safety_error; +use rustc_trait_selection::traits::error_reporting::{ + report_object_safety_error, suggestions::NextTypeParamName, +}; use rustc_trait_selection::traits::wf::object_region_bounds; use smallvec::SmallVec; @@ -2986,6 +2988,50 @@ impl<'o, 'tcx> dyn AstConv<'tcx> + 'o { Some(r) } + /// Make sure that we are in the condition to suggest the blanket implementation. + fn maybe_lint_blanket_trait_impl<T: rustc_errors::EmissionGuarantee>( + &self, + self_ty: &hir::Ty<'_>, + diag: &mut DiagnosticBuilder<'_, T>, + ) { + let tcx = self.tcx(); + let parent_id = tcx.hir().get_parent_item(self_ty.hir_id); + if let hir::Node::Item(hir::Item { + kind: + hir::ItemKind::Impl(hir::Impl { + self_ty: impl_self_ty, of_trait: Some(of_trait_ref), generics, .. + }), + .. + }) = tcx.hir().get_by_def_id(parent_id) && self_ty.hir_id == impl_self_ty.hir_id + { + if !of_trait_ref.trait_def_id().map_or(false, |def_id| def_id.is_local()) { + return; + } + let of_trait_span = of_trait_ref.path.span; + // make sure that we are not calling unwrap to abort during the compilation + let Ok(impl_trait_name) = tcx.sess.source_map().span_to_snippet(self_ty.span) else { return; }; + let Ok(of_trait_name) = tcx.sess.source_map().span_to_snippet(of_trait_span) else { return; }; + // check if the trait has generics, to make a correct suggestion + let param_name = generics.params.next_type_param_name(None); + + let add_generic_sugg = if let Some(span) = generics.span_for_param_suggestion() { + (span, format!(", {}: {}", param_name, impl_trait_name)) + } else { + (generics.span, format!("<{}: {}>", param_name, impl_trait_name)) + }; + diag.multipart_suggestion( + format!("alternatively use a blanket \ + implementation to implement `{of_trait_name}` for \ + all types that also implement `{impl_trait_name}`"), + vec![ + (self_ty.span, param_name), + add_generic_sugg, + ], + Applicability::MaybeIncorrect, + ); + } + } + fn maybe_lint_bare_trait(&self, self_ty: &hir::Ty<'_>, in_path: bool) { let tcx = self.tcx(); if let hir::TyKind::TraitObject([poly_trait_ref, ..], _, TraitObjectSyntax::None) = @@ -3021,9 +3067,12 @@ impl<'o, 'tcx> dyn AstConv<'tcx> + 'o { if self_ty.span.edition() >= Edition::Edition2021 { let msg = "trait objects must include the `dyn` keyword"; let label = "add `dyn` keyword before this trait"; - rustc_errors::struct_span_err!(tcx.sess, self_ty.span, E0782, "{}", msg) - .multipart_suggestion_verbose(label, sugg, Applicability::MachineApplicable) - .emit(); + let mut diag = + rustc_errors::struct_span_err!(tcx.sess, self_ty.span, E0782, "{}", msg); + diag.multipart_suggestion_verbose(label, sugg, Applicability::MachineApplicable); + // check if the impl trait that we are considering is a impl of a local trait + self.maybe_lint_blanket_trait_impl(&self_ty, &mut diag); + diag.emit(); } else { let msg = "trait objects without an explicit `dyn` are deprecated"; tcx.struct_span_lint_hir( @@ -3031,13 +3080,14 @@ impl<'o, 'tcx> dyn AstConv<'tcx> + 'o { self_ty.hir_id, self_ty.span, |lint| { - lint.build(msg) - .multipart_suggestion_verbose( - "use `dyn`", - sugg, - Applicability::MachineApplicable, - ) - .emit(); + let mut diag = lint.build(msg); + diag.multipart_suggestion_verbose( + "use `dyn`", + sugg, + Applicability::MachineApplicable, + ); + self.maybe_lint_blanket_trait_impl::<()>(&self_ty, &mut diag); + diag.emit(); }, ); } diff --git a/compiler/rustc_typeck/src/check/_match.rs b/compiler/rustc_typeck/src/check/_match.rs index 035571c881c..deaadf0e5c8 100644 --- a/compiler/rustc_typeck/src/check/_match.rs +++ b/compiler/rustc_typeck/src/check/_match.rs @@ -4,7 +4,7 @@ use rustc_errors::{Applicability, Diagnostic, MultiSpan}; use rustc_hir::{self as hir, ExprKind}; use rustc_infer::infer::type_variable::{TypeVariableOrigin, TypeVariableOriginKind}; use rustc_infer::traits::Obligation; -use rustc_middle::ty::{self, ToPredicate, Ty, TypeFoldable}; +use rustc_middle::ty::{self, ToPredicate, Ty, TypeVisitable}; use rustc_span::Span; use rustc_trait_selection::traits::query::evaluate_obligation::InferCtxtExt; use rustc_trait_selection::traits::{ diff --git a/compiler/rustc_typeck/src/check/callee.rs b/compiler/rustc_typeck/src/check/callee.rs index 83a8c5ea021..2c8be88ef6c 100644 --- a/compiler/rustc_typeck/src/check/callee.rs +++ b/compiler/rustc_typeck/src/check/callee.rs @@ -18,7 +18,7 @@ use rustc_middle::ty::adjustment::{ Adjust, Adjustment, AllowTwoPhase, AutoBorrow, AutoBorrowMutability, }; use rustc_middle::ty::subst::{Subst, SubstsRef}; -use rustc_middle::ty::{self, Ty, TyCtxt, TypeFoldable}; +use rustc_middle::ty::{self, Ty, TyCtxt, TypeVisitable}; use rustc_span::symbol::{sym, Ident}; use rustc_span::Span; use rustc_target::spec::abi; @@ -280,15 +280,36 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { callee_node: &hir::ExprKind<'_>, callee_span: Span, ) { - let hir_id = self.tcx.hir().get_parent_node(hir_id); - let parent_node = self.tcx.hir().get(hir_id); + let hir = self.tcx.hir(); + let parent_hir_id = hir.get_parent_node(hir_id); + let parent_node = hir.get(parent_hir_id); if let ( hir::Node::Expr(hir::Expr { - kind: hir::ExprKind::Closure { fn_decl_span, .. }, .. + kind: hir::ExprKind::Closure { fn_decl_span, body, .. }, + .. }), hir::ExprKind::Block(..), ) = (parent_node, callee_node) { + let fn_decl_span = if hir.body(*body).generator_kind + == Some(hir::GeneratorKind::Async(hir::AsyncGeneratorKind::Closure)) + { + // Actually need to unwrap a few more layers of HIR to get to + // the _real_ closure... + let async_closure = hir.get_parent_node(hir.get_parent_node(parent_hir_id)); + if let hir::Node::Expr(hir::Expr { + kind: hir::ExprKind::Closure { fn_decl_span, .. }, + .. + }) = hir.get(async_closure) + { + *fn_decl_span + } else { + return; + } + } else { + *fn_decl_span + }; + let start = fn_decl_span.shrink_to_lo(); let end = callee_span.shrink_to_hi(); err.multipart_suggestion( diff --git a/compiler/rustc_typeck/src/check/cast.rs b/compiler/rustc_typeck/src/check/cast.rs index 7d5d6849b3b..66dd5582490 100644 --- a/compiler/rustc_typeck/src/check/cast.rs +++ b/compiler/rustc_typeck/src/check/cast.rs @@ -40,7 +40,7 @@ use rustc_middle::ty::adjustment::AllowTwoPhase; use rustc_middle::ty::cast::{CastKind, CastTy}; use rustc_middle::ty::error::TypeError; use rustc_middle::ty::subst::SubstsRef; -use rustc_middle::ty::{self, Ty, TypeAndMut, TypeFoldable}; +use rustc_middle::ty::{self, Ty, TypeAndMut, TypeVisitable}; use rustc_session::lint; use rustc_session::Session; use rustc_span::symbol::sym; diff --git a/compiler/rustc_typeck/src/check/check.rs b/compiler/rustc_typeck/src/check/check.rs index 6222dbb4074..6ed2ce155d9 100644 --- a/compiler/rustc_typeck/src/check/check.rs +++ b/compiler/rustc_typeck/src/check/check.rs @@ -13,6 +13,7 @@ use rustc_hir::def_id::{DefId, LocalDefId}; use rustc_hir::intravisit::Visitor; use rustc_hir::lang_items::LangItem; use rustc_hir::{ItemKind, Node, PathSegment}; +use rustc_infer::infer::outlives::env::OutlivesEnvironment; use rustc_infer::infer::type_variable::{TypeVariableOrigin, TypeVariableOriginKind}; use rustc_infer::infer::{RegionVariableOrigin, TyCtxtInferExt}; use rustc_infer::traits::Obligation; @@ -20,7 +21,9 @@ use rustc_middle::hir::nested_filter; use rustc_middle::ty::layout::{LayoutError, MAX_SIMD_LANES}; use rustc_middle::ty::subst::GenericArgKind; use rustc_middle::ty::util::{Discr, IntTypeExt}; -use rustc_middle::ty::{self, ParamEnv, ToPredicate, Ty, TyCtxt, TypeFoldable, TypeSuperFoldable}; +use rustc_middle::ty::{ + self, ParamEnv, ToPredicate, Ty, TyCtxt, TypeSuperVisitable, TypeVisitable, +}; use rustc_session::lint::builtin::{UNINHABITED_STATIC, UNSUPPORTED_CALLING_CONVENTIONS}; use rustc_span::symbol::sym; use rustc_span::{self, Span}; @@ -521,7 +524,7 @@ pub(super) fn check_opaque_for_inheriting_lifetimes<'tcx>( struct FoundParentLifetime; struct FindParentLifetimeVisitor<'tcx>(&'tcx ty::Generics); - impl<'tcx> ty::fold::TypeVisitor<'tcx> for FindParentLifetimeVisitor<'tcx> { + impl<'tcx> ty::visit::TypeVisitor<'tcx> for FindParentLifetimeVisitor<'tcx> { type BreakTy = FoundParentLifetime; fn visit_region(&mut self, r: ty::Region<'tcx>) -> ControlFlow<Self::BreakTy> { @@ -555,7 +558,7 @@ pub(super) fn check_opaque_for_inheriting_lifetimes<'tcx>( selftys: Vec<(Span, Option<String>)>, } - impl<'tcx> ty::fold::TypeVisitor<'tcx> for ProhibitOpaqueVisitor<'tcx> { + impl<'tcx> ty::visit::TypeVisitor<'tcx> for ProhibitOpaqueVisitor<'tcx> { type BreakTy = Ty<'tcx>; fn visit_ty(&mut self, t: Ty<'tcx>) -> ControlFlow<Self::BreakTy> { @@ -736,10 +739,8 @@ fn check_opaque_meets_bounds<'tcx>( hir::OpaqueTyOrigin::FnReturn(..) | hir::OpaqueTyOrigin::AsyncFn(..) => {} // Can have different predicates to their defining use hir::OpaqueTyOrigin::TyAlias => { - // Finally, resolve all regions. This catches wily misuses of - // lifetime parameters. - let fcx = FnCtxt::new(&inh, param_env, hir_id); - fcx.regionck_item(hir_id, span, FxHashSet::default()); + let outlives_environment = OutlivesEnvironment::new(param_env); + infcx.check_region_obligations_and_report_errors(&outlives_environment); } } @@ -1596,7 +1597,7 @@ fn opaque_type_cycle_error(tcx: TyCtxt<'_>, def_id: LocalDefId, span: Span) -> E .filter(|(_, ty)| !matches!(ty.kind(), ty::Never)) { struct OpaqueTypeCollector(Vec<DefId>); - impl<'tcx> ty::fold::TypeVisitor<'tcx> for OpaqueTypeCollector { + impl<'tcx> ty::visit::TypeVisitor<'tcx> for OpaqueTypeCollector { fn visit_ty(&mut self, t: Ty<'tcx>) -> ControlFlow<Self::BreakTy> { match *t.kind() { ty::Opaque(def, _) => { diff --git a/compiler/rustc_typeck/src/check/closure.rs b/compiler/rustc_typeck/src/check/closure.rs index 131e594ed94..1681e6af812 100644 --- a/compiler/rustc_typeck/src/check/closure.rs +++ b/compiler/rustc_typeck/src/check/closure.rs @@ -10,8 +10,8 @@ use rustc_hir::lang_items::LangItem; use rustc_infer::infer::type_variable::{TypeVariableOrigin, TypeVariableOriginKind}; use rustc_infer::infer::LateBoundRegionConversionTime; use rustc_infer::infer::{InferOk, InferResult}; -use rustc_middle::ty::fold::TypeFoldable; use rustc_middle::ty::subst::InternalSubsts; +use rustc_middle::ty::visit::TypeVisitable; use rustc_middle::ty::{self, Ty}; use rustc_span::source_map::Span; use rustc_target::spec::abi::Abi; diff --git a/compiler/rustc_typeck/src/check/coercion.rs b/compiler/rustc_typeck/src/check/coercion.rs index 43fc49c6801..acd7e4a92dc 100644 --- a/compiler/rustc_typeck/src/check/coercion.rs +++ b/compiler/rustc_typeck/src/check/coercion.rs @@ -50,9 +50,9 @@ use rustc_middle::ty::adjustment::{ Adjust, Adjustment, AllowTwoPhase, AutoBorrow, AutoBorrowMutability, PointerCast, }; use rustc_middle::ty::error::TypeError; -use rustc_middle::ty::fold::TypeFoldable; use rustc_middle::ty::relate::RelateResult; use rustc_middle::ty::subst::SubstsRef; +use rustc_middle::ty::visit::TypeVisitable; use rustc_middle::ty::{self, ToPredicate, Ty, TypeAndMut}; use rustc_session::parse::feature_err; use rustc_span::symbol::sym; diff --git a/compiler/rustc_typeck/src/check/compare_method.rs b/compiler/rustc_typeck/src/check/compare_method.rs index 95c82a7d2c3..0a9b6863ef5 100644 --- a/compiler/rustc_typeck/src/check/compare_method.rs +++ b/compiler/rustc_typeck/src/check/compare_method.rs @@ -1,3 +1,4 @@ +use crate::check::regionck::OutlivesEnvironmentExt; use crate::errors::LifetimesOrBoundsMismatchOnTrait; use rustc_data_structures::stable_set::FxHashSet; use rustc_errors::{pluralize, struct_span_err, Applicability, DiagnosticId, ErrorGuaranteed}; @@ -5,6 +6,7 @@ use rustc_hir as hir; use rustc_hir::def::{DefKind, Res}; use rustc_hir::intravisit; use rustc_hir::{GenericParamKind, ImplItemKind, TraitItemKind}; +use rustc_infer::infer::outlives::env::OutlivesEnvironment; use rustc_infer::infer::{self, InferOk, TyCtxtInferExt}; use rustc_infer::traits::util; use rustc_middle::ty::error::{ExpectedFound, TypeError}; @@ -78,10 +80,11 @@ fn compare_predicate_entailment<'tcx>( let trait_to_impl_substs = impl_trait_ref.substs; // This node-id should be used for the `body_id` field on each - // `ObligationCause` (and the `FnCtxt`). This is what - // `regionck_item` expects. + // `ObligationCause` (and the `FnCtxt`). + // + // FIXME(@lcnr): remove that after removing `cause.body_id` from + // obligations. let impl_m_hir_id = tcx.hir().local_def_id_to_hir_id(impl_m.def_id.expect_local()); - // We sometimes modify the span further down. let mut cause = ObligationCause::new( impl_m_span, @@ -208,8 +211,7 @@ fn compare_predicate_entailment<'tcx>( Reveal::UserFacing, hir::Constness::NotConst, ); - let param_env = - traits::normalize_param_env_or_error(tcx, impl_m.def_id, param_env, normalize_cause); + let param_env = traits::normalize_param_env_or_error(tcx, param_env, normalize_cause); tcx.infer_ctxt().enter(|infcx| { let inh = Inherited::new(infcx, impl_m.def_id.expect_local()); @@ -399,8 +401,9 @@ fn compare_predicate_entailment<'tcx>( // Finally, resolve all regions. This catches wily misuses of // lifetime parameters. - let fcx = FnCtxt::new(&inh, param_env, impl_m_hir_id); - fcx.regionck_item(impl_m_hir_id, impl_m_span, wf_tys); + let mut outlives_environment = OutlivesEnvironment::new(param_env); + outlives_environment.add_implied_bounds(infcx, wf_tys, impl_m_hir_id); + infcx.check_region_obligations_and_report_errors(&outlives_environment); Ok(()) }) @@ -1155,8 +1158,8 @@ pub(crate) fn compare_const_impl<'tcx>( return; } - let fcx = FnCtxt::new(&inh, param_env, impl_c_hir_id); - fcx.regionck_item(impl_c_hir_id, impl_c_span, FxHashSet::default()); + let outlives_environment = OutlivesEnvironment::new(param_env); + infcx.resolve_regions_and_report_errors(&outlives_environment); }); } @@ -1247,12 +1250,7 @@ fn compare_type_predicate_entailment<'tcx>( Reveal::UserFacing, hir::Constness::NotConst, ); - let param_env = traits::normalize_param_env_or_error( - tcx, - impl_ty.def_id, - param_env, - normalize_cause.clone(), - ); + let param_env = traits::normalize_param_env_or_error(tcx, param_env, normalize_cause.clone()); tcx.infer_ctxt().enter(|infcx| { let inh = Inherited::new(infcx, impl_ty.def_id.expect_local()); let infcx = &inh.infcx; @@ -1279,8 +1277,8 @@ fn compare_type_predicate_entailment<'tcx>( // Finally, resolve all regions. This catches wily misuses of // lifetime parameters. - let fcx = FnCtxt::new(&inh, param_env, impl_ty_hir_id); - fcx.regionck_item(impl_ty_hir_id, impl_ty_span, FxHashSet::default()); + let outlives_environment = OutlivesEnvironment::new(param_env); + infcx.check_region_obligations_and_report_errors(&outlives_environment); Ok(()) }) @@ -1504,12 +1502,16 @@ pub fn check_type_bounds<'tcx>( // Finally, resolve all regions. This catches wily misuses of // lifetime parameters. + // + // FIXME: Remove that `FnCtxt`. let fcx = FnCtxt::new(&inh, param_env, impl_ty_hir_id); let implied_bounds = match impl_ty.container { ty::TraitContainer(_) => FxHashSet::default(), ty::ImplContainer(def_id) => fcx.impl_implied_bounds(def_id, impl_ty_span), }; - fcx.regionck_item(impl_ty_hir_id, impl_ty_span, implied_bounds); + let mut outlives_environment = OutlivesEnvironment::new(param_env); + outlives_environment.add_implied_bounds(infcx, implied_bounds, impl_ty_hir_id); + infcx.check_region_obligations_and_report_errors(&outlives_environment); Ok(()) }) diff --git a/compiler/rustc_typeck/src/check/demand.rs b/compiler/rustc_typeck/src/check/demand.rs index 961bbc42661..53ca027bb57 100644 --- a/compiler/rustc_typeck/src/check/demand.rs +++ b/compiler/rustc_typeck/src/check/demand.rs @@ -223,7 +223,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { None, hir::Path { res: hir::def::Res::Local(hir_id), .. }, )) => { - if let Some(hir::Node::Binding(pat)) = self.tcx.hir().find(*hir_id) { + if let Some(hir::Node::Pat(pat)) = self.tcx.hir().find(*hir_id) { let parent = self.tcx.hir().get_parent_node(pat.hir_id); primary_span = pat.span; secondary_span = pat.span; diff --git a/compiler/rustc_typeck/src/check/dropck.rs b/compiler/rustc_typeck/src/check/dropck.rs index ed3b9f2db1f..72095c40807 100644 --- a/compiler/rustc_typeck/src/check/dropck.rs +++ b/compiler/rustc_typeck/src/check/dropck.rs @@ -1,5 +1,6 @@ -use crate::check::regionck::RegionCtxt; -use crate::hir; +// FIXME(@lcnr): Move this module out of `rustc_typeck`. +// +// We don't do any drop checking during hir typeck. use crate::hir::def_id::{DefId, LocalDefId}; use rustc_errors::{struct_span_err, ErrorGuaranteed}; use rustc_middle::ty::error::TypeError; @@ -7,9 +8,6 @@ use rustc_middle::ty::relate::{Relate, RelateResult, TypeRelation}; use rustc_middle::ty::subst::SubstsRef; use rustc_middle::ty::util::IgnoreRegions; use rustc_middle::ty::{self, Predicate, Ty, TyCtxt}; -use rustc_span::Span; -use rustc_trait_selection::traits::query::dropck_outlives::AtExt; -use rustc_trait_selection::traits::ObligationCause; /// This function confirms that the `Drop` implementation identified by /// `drop_impl_did` is not any more specialized than the type it is @@ -231,23 +229,6 @@ fn ensure_drop_predicates_are_implied_by_item_defn<'tcx>( result } -/// This function is not only checking that the dropck obligations are met for -/// the given type, but it's also currently preventing non-regular recursion in -/// types from causing stack overflows (dropck_no_diverge_on_nonregular_*.rs). -pub(crate) fn check_drop_obligations<'a, 'tcx>( - rcx: &mut RegionCtxt<'a, 'tcx>, - ty: Ty<'tcx>, - span: Span, - body_id: hir::HirId, -) { - debug!("check_drop_obligations typ: {:?}", ty); - - let cause = &ObligationCause::misc(span, body_id); - let infer_ok = rcx.infcx.at(cause, rcx.fcx.param_env).dropck_outlives(ty); - debug!("dropck_outlives = {:#?}", infer_ok); - rcx.fcx.register_infer_ok_obligations(infer_ok); -} - // This is an implementation of the TypeRelation trait with the // aim of simply comparing for equality (without side-effects). // It is not intended to be used anywhere else other than here. diff --git a/compiler/rustc_typeck/src/check/expr.rs b/compiler/rustc_typeck/src/check/expr.rs index b4476d5c59b..45ea04f2342 100644 --- a/compiler/rustc_typeck/src/check/expr.rs +++ b/compiler/rustc_typeck/src/check/expr.rs @@ -44,7 +44,7 @@ use rustc_middle::middle::stability; use rustc_middle::ty::adjustment::{Adjust, Adjustment, AllowTwoPhase}; use rustc_middle::ty::error::TypeError::FieldMisMatch; use rustc_middle::ty::subst::SubstsRef; -use rustc_middle::ty::{self, AdtKind, DefIdTree, Ty, TypeFoldable}; +use rustc_middle::ty::{self, AdtKind, DefIdTree, Ty, TypeVisitable}; use rustc_session::parse::feature_err; use rustc_span::hygiene::DesugaringKind; use rustc_span::lev_distance::find_best_match_for_name; diff --git a/compiler/rustc_typeck/src/check/fn_ctxt/_impl.rs b/compiler/rustc_typeck/src/check/fn_ctxt/_impl.rs index d5075537ced..f3341e72e73 100644 --- a/compiler/rustc_typeck/src/check/fn_ctxt/_impl.rs +++ b/compiler/rustc_typeck/src/check/fn_ctxt/_impl.rs @@ -23,6 +23,7 @@ use rustc_middle::ty::fold::TypeFoldable; use rustc_middle::ty::subst::{ self, GenericArgKind, InternalSubsts, Subst, SubstsRef, UserSelfTy, UserSubsts, }; +use rustc_middle::ty::visit::TypeVisitable; use rustc_middle::ty::{ self, AdtKind, CanonicalUserType, DefIdTree, EarlyBinder, GenericParamDefKind, ToPolyTraitRef, ToPredicate, Ty, UserType, @@ -156,6 +157,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { self.typeck_results.borrow_mut().field_indices_mut().insert(hir_id, index); } + #[instrument(level = "debug", skip(self))] pub(in super::super) fn write_resolution( &self, hir_id: hir::HirId, @@ -164,8 +166,8 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { self.typeck_results.borrow_mut().type_dependent_defs_mut().insert(hir_id, r); } + #[instrument(level = "debug", skip(self))] pub fn write_method_call(&self, hir_id: hir::HirId, method: MethodCallee<'tcx>) { - debug!("write_method_call(hir_id={:?}, method={:?})", hir_id, method); self.write_resolution(hir_id, Ok((DefKind::AssocFn, method.def_id))); self.write_substs(hir_id, method.substs); @@ -556,7 +558,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { // sufficiently enforced with erased regions. =) fn can_contain_user_lifetime_bounds<T>(t: T) -> bool where - T: TypeFoldable<'tcx>, + T: TypeVisitable<'tcx>, { t.has_free_regions() || t.has_projections() || t.has_infer_types() } @@ -1537,8 +1539,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { ty } else { if !self.is_tainted_by_errors() { - self.emit_inference_failure_err((**self).body_id, sp, ty.into(), vec![], E0282) - .note("type must be known at this point") + self.emit_inference_failure_err((**self).body_id, sp, ty.into(), E0282, true) .emit(); } let err = self.tcx.ty_error(); diff --git a/compiler/rustc_typeck/src/check/fn_ctxt/checks.rs b/compiler/rustc_typeck/src/check/fn_ctxt/checks.rs index d2e16021827..1794446e92a 100644 --- a/compiler/rustc_typeck/src/check/fn_ctxt/checks.rs +++ b/compiler/rustc_typeck/src/check/fn_ctxt/checks.rs @@ -24,7 +24,7 @@ use rustc_infer::infer::error_reporting::{FailureCode, ObligationCauseExt}; use rustc_infer::infer::InferOk; use rustc_infer::infer::TypeTrace; use rustc_middle::ty::adjustment::AllowTwoPhase; -use rustc_middle::ty::fold::TypeFoldable; +use rustc_middle::ty::visit::TypeVisitable; use rustc_middle::ty::{self, IsSuggestable, Ty, TyCtxt}; use rustc_session::Session; use rustc_span::symbol::Ident; diff --git a/compiler/rustc_typeck/src/check/fn_ctxt/mod.rs b/compiler/rustc_typeck/src/check/fn_ctxt/mod.rs index 8b680a3d042..05bcc710e16 100644 --- a/compiler/rustc_typeck/src/check/fn_ctxt/mod.rs +++ b/compiler/rustc_typeck/src/check/fn_ctxt/mod.rs @@ -15,8 +15,8 @@ use rustc_hir::def_id::DefId; use rustc_infer::infer; use rustc_infer::infer::type_variable::{TypeVariableOrigin, TypeVariableOriginKind}; use rustc_middle::infer::unify_key::{ConstVariableOrigin, ConstVariableOriginKind}; -use rustc_middle::ty::fold::TypeFoldable; use rustc_middle::ty::subst::GenericArgKind; +use rustc_middle::ty::visit::TypeVisitable; use rustc_middle::ty::{self, Const, Ty, TyCtxt}; use rustc_session::Session; use rustc_span::symbol::Ident; diff --git a/compiler/rustc_typeck/src/check/generator_interior/drop_ranges/cfg_build.rs b/compiler/rustc_typeck/src/check/generator_interior/drop_ranges/cfg_build.rs index dbc309b29ff..365ff429243 100644 --- a/compiler/rustc_typeck/src/check/generator_interior/drop_ranges/cfg_build.rs +++ b/compiler/rustc_typeck/src/check/generator_interior/drop_ranges/cfg_build.rs @@ -251,7 +251,6 @@ impl<'a, 'tcx> DropRangeVisitor<'a, 'tcx> { | hir::Node::Ty(..) | hir::Node::TypeBinding(..) | hir::Node::TraitRef(..) - | hir::Node::Binding(..) | hir::Node::Pat(..) | hir::Node::Arm(..) | hir::Node::Local(..) diff --git a/compiler/rustc_typeck/src/check/inherited.rs b/compiler/rustc_typeck/src/check/inherited.rs index 08a64d8e673..2ce258cf69c 100644 --- a/compiler/rustc_typeck/src/check/inherited.rs +++ b/compiler/rustc_typeck/src/check/inherited.rs @@ -8,6 +8,7 @@ use rustc_hir::HirIdMap; use rustc_infer::infer; use rustc_infer::infer::{InferCtxt, InferOk, TyCtxtInferExt}; use rustc_middle::ty::fold::TypeFoldable; +use rustc_middle::ty::visit::TypeVisitable; use rustc_middle::ty::{self, Ty, TyCtxt}; use rustc_span::{self, Span}; use rustc_trait_selection::infer::InferCtxtExt as _; diff --git a/compiler/rustc_typeck/src/check/intrinsicck.rs b/compiler/rustc_typeck/src/check/intrinsicck.rs index 469e6118575..cc91f2431e0 100644 --- a/compiler/rustc_typeck/src/check/intrinsicck.rs +++ b/compiler/rustc_typeck/src/check/intrinsicck.rs @@ -4,7 +4,7 @@ use rustc_errors::struct_span_err; use rustc_hir as hir; use rustc_index::vec::Idx; use rustc_middle::ty::layout::{LayoutError, SizeSkeleton}; -use rustc_middle::ty::{self, Article, FloatTy, InferTy, IntTy, Ty, TyCtxt, TypeFoldable, UintTy}; +use rustc_middle::ty::{self, Article, FloatTy, InferTy, IntTy, Ty, TyCtxt, TypeVisitable, UintTy}; use rustc_session::lint; use rustc_span::{Span, Symbol, DUMMY_SP}; use rustc_target::abi::{Pointer, VariantIdx}; diff --git a/compiler/rustc_typeck/src/check/method/mod.rs b/compiler/rustc_typeck/src/check/method/mod.rs index 5ca82218355..e29f0275bf4 100644 --- a/compiler/rustc_typeck/src/check/method/mod.rs +++ b/compiler/rustc_typeck/src/check/method/mod.rs @@ -21,7 +21,7 @@ use rustc_infer::infer::{self, InferOk}; use rustc_middle::ty::subst::Subst; use rustc_middle::ty::subst::{InternalSubsts, SubstsRef}; use rustc_middle::ty::GenericParamDefKind; -use rustc_middle::ty::{self, ToPredicate, Ty, TypeFoldable}; +use rustc_middle::ty::{self, ToPredicate, Ty, TypeVisitable}; use rustc_span::symbol::Ident; use rustc_span::Span; use rustc_trait_selection::traits; diff --git a/compiler/rustc_typeck/src/check/method/probe.rs b/compiler/rustc_typeck/src/check/method/probe.rs index 87254b211d6..e9b91414a07 100644 --- a/compiler/rustc_typeck/src/check/method/probe.rs +++ b/compiler/rustc_typeck/src/check/method/probe.rs @@ -21,7 +21,9 @@ use rustc_middle::middle::stability; use rustc_middle::ty::fast_reject::{simplify_type, TreatParams}; use rustc_middle::ty::subst::{InternalSubsts, Subst, SubstsRef}; use rustc_middle::ty::GenericParamDefKind; -use rustc_middle::ty::{self, EarlyBinder, ParamEnvAnd, ToPredicate, Ty, TyCtxt, TypeFoldable}; +use rustc_middle::ty::{ + self, EarlyBinder, ParamEnvAnd, ToPredicate, Ty, TyCtxt, TypeFoldable, TypeVisitable, +}; use rustc_session::lint; use rustc_span::def_id::LocalDefId; use rustc_span::lev_distance::{ diff --git a/compiler/rustc_typeck/src/check/method/suggest.rs b/compiler/rustc_typeck/src/check/method/suggest.rs index fa5f0eff223..e7a2b32571c 100644 --- a/compiler/rustc_typeck/src/check/method/suggest.rs +++ b/compiler/rustc_typeck/src/check/method/suggest.rs @@ -17,7 +17,7 @@ use rustc_middle::traits::util::supertraits; use rustc_middle::ty::fast_reject::{simplify_type, TreatParams}; use rustc_middle::ty::print::with_crate_prefix; use rustc_middle::ty::ToPolyTraitRef; -use rustc_middle::ty::{self, DefIdTree, ToPredicate, Ty, TyCtxt, TypeFoldable}; +use rustc_middle::ty::{self, DefIdTree, ToPredicate, Ty, TyCtxt, TypeVisitable}; use rustc_span::symbol::{kw, sym, Ident}; use rustc_span::{lev_distance, source_map, ExpnKind, FileName, MacroKind, Span}; use rustc_trait_selection::traits::error_reporting::on_unimplemented::InferCtxtExt as _; diff --git a/compiler/rustc_typeck/src/check/mod.rs b/compiler/rustc_typeck/src/check/mod.rs index 0ede9ef7756..dee58791cec 100644 --- a/compiler/rustc_typeck/src/check/mod.rs +++ b/compiler/rustc_typeck/src/check/mod.rs @@ -368,7 +368,7 @@ fn typeck_with_fallback<'tcx>( let typeck_results = Inherited::build(tcx, def_id).enter(|inh| { let param_env = tcx.param_env(def_id); - let (fcx, wf_tys) = if let Some(hir::FnSig { header, decl, .. }) = fn_sig { + let fcx = if let Some(hir::FnSig { header, decl, .. }) = fn_sig { let fn_sig = if crate::collect::get_infer_ret_ty(&decl.output).is_some() { let fcx = FnCtxt::new(&inh, param_env, body.value.hir_id); <dyn AstConv<'_>>::ty_of_fn(&fcx, id, header.unsafety, header.abi, decl, None, None) @@ -378,13 +378,7 @@ fn typeck_with_fallback<'tcx>( check_abi(tcx, id, span, fn_sig.abi()); - // When normalizing the function signature, we assume all types are - // well-formed. So, we don't need to worry about the obligations - // from normalization. We could just discard these, but to align with - // compare_method and elsewhere, we just add implied bounds for - // these types. - let mut wf_tys = FxHashSet::default(); - // Compute the fty from point of view of inside the fn. + // Compute the function signature from point of view of inside the fn. let fn_sig = tcx.liberate_late_bound_regions(def_id.to_def_id(), fn_sig); let fn_sig = inh.normalize_associated_types_in( body.value.span, @@ -392,10 +386,7 @@ fn typeck_with_fallback<'tcx>( param_env, fn_sig, ); - wf_tys.extend(fn_sig.inputs_and_output.iter()); - - let fcx = check_fn(&inh, param_env, fn_sig, decl, id, body, None, true).0; - (fcx, wf_tys) + check_fn(&inh, param_env, fn_sig, decl, id, body, None, true).0 } else { let fcx = FnCtxt::new(&inh, param_env, body.value.hir_id); let expected_type = body_ty @@ -458,7 +449,7 @@ fn typeck_with_fallback<'tcx>( fcx.write_ty(id, expected_type); - (fcx, FxHashSet::default()) + fcx }; let fallback_has_occurred = fcx.type_inference_fallback(); @@ -490,11 +481,7 @@ fn typeck_with_fallback<'tcx>( fcx.check_asms(); - if fn_sig.is_some() { - fcx.regionck_fn(id, body, span, wf_tys); - } else { - fcx.regionck_expr(body); - } + fcx.infcx.skip_region_resolution(); fcx.resolve_type_vars_in_body(body) }); diff --git a/compiler/rustc_typeck/src/check/op.rs b/compiler/rustc_typeck/src/check/op.rs index c2f97a5051c..42893789957 100644 --- a/compiler/rustc_typeck/src/check/op.rs +++ b/compiler/rustc_typeck/src/check/op.rs @@ -10,7 +10,7 @@ use rustc_middle::ty::adjustment::{ Adjust, Adjustment, AllowTwoPhase, AutoBorrow, AutoBorrowMutability, }; use rustc_middle::ty::{ - self, Ty, TyCtxt, TypeFoldable, TypeFolder, TypeSuperFoldable, TypeVisitor, + self, Ty, TyCtxt, TypeFolder, TypeSuperFoldable, TypeSuperVisitable, TypeVisitable, TypeVisitor, }; use rustc_span::source_map::Spanned; use rustc_span::symbol::{sym, Ident}; diff --git a/compiler/rustc_typeck/src/check/pat.rs b/compiler/rustc_typeck/src/check/pat.rs index e1ec9f13cd1..fbfbfba5c2a 100644 --- a/compiler/rustc_typeck/src/check/pat.rs +++ b/compiler/rustc_typeck/src/check/pat.rs @@ -13,7 +13,7 @@ use rustc_hir::{HirId, Pat, PatKind}; use rustc_infer::infer; use rustc_infer::infer::type_variable::{TypeVariableOrigin, TypeVariableOriginKind}; use rustc_middle::middle::stability::EvalResult; -use rustc_middle::ty::{self, Adt, BindingMode, Ty, TypeFoldable}; +use rustc_middle::ty::{self, Adt, BindingMode, Ty, TypeVisitable}; use rustc_session::lint::builtin::NON_EXHAUSTIVE_OMITTED_PATTERNS; use rustc_span::hygiene::DesugaringKind; use rustc_span::lev_distance::find_best_match_for_name; diff --git a/compiler/rustc_typeck/src/check/regionck.rs b/compiler/rustc_typeck/src/check/regionck.rs index 0ce63922098..1c3c5f999bc 100644 --- a/compiler/rustc_typeck/src/check/regionck.rs +++ b/compiler/rustc_typeck/src/check/regionck.rs @@ -1,106 +1,9 @@ -//! The region check is a final pass that runs over the AST after we have -//! inferred the type constraints but before we have actually finalized -//! the types. Its purpose is to embed a variety of region constraints. -//! Inserting these constraints as a separate pass is good because (1) it -//! localizes the code that has to do with region inference and (2) often -//! we cannot know what constraints are needed until the basic types have -//! been inferred. -//! -//! ### Interaction with the borrow checker -//! -//! In general, the job of the borrowck module (which runs later) is to -//! check that all soundness criteria are met, given a particular set of -//! regions. The job of *this* module is to anticipate the needs of the -//! borrow checker and infer regions that will satisfy its requirements. -//! It is generally true that the inference doesn't need to be sound, -//! meaning that if there is a bug and we inferred bad regions, the borrow -//! checker should catch it. This is not entirely true though; for -//! example, the borrow checker doesn't check subtyping, and it doesn't -//! check that region pointers are always live when they are used. It -//! might be worthwhile to fix this so that borrowck serves as a kind of -//! verification step -- that would add confidence in the overall -//! correctness of the compiler, at the cost of duplicating some type -//! checks and effort. -//! -//! ### Inferring the duration of borrows, automatic and otherwise -//! -//! Whenever we introduce a borrowed pointer, for example as the result of -//! a borrow expression `let x = &data`, the lifetime of the pointer `x` -//! is always specified as a region inference variable. `regionck` has the -//! job of adding constraints such that this inference variable is as -//! narrow as possible while still accommodating all uses (that is, every -//! dereference of the resulting pointer must be within the lifetime). -//! -//! #### Reborrows -//! -//! Generally speaking, `regionck` does NOT try to ensure that the data -//! `data` will outlive the pointer `x`. That is the job of borrowck. The -//! one exception is when "re-borrowing" the contents of another borrowed -//! pointer. For example, imagine you have a borrowed pointer `b` with -//! lifetime `L1` and you have an expression `&*b`. The result of this -//! expression will be another borrowed pointer with lifetime `L2` (which is -//! an inference variable). The borrow checker is going to enforce the -//! constraint that `L2 < L1`, because otherwise you are re-borrowing data -//! for a lifetime larger than the original loan. However, without the -//! routines in this module, the region inferencer would not know of this -//! dependency and thus it might infer the lifetime of `L2` to be greater -//! than `L1` (issue #3148). -//! -//! There are a number of troublesome scenarios in the tests -//! `region-dependent-*.rs`, but here is one example: -//! -//! struct Foo { i: i32 } -//! struct Bar { foo: Foo } -//! fn get_i<'a>(x: &'a Bar) -> &'a i32 { -//! let foo = &x.foo; // Lifetime L1 -//! &foo.i // Lifetime L2 -//! } -//! -//! Note that this comes up either with `&` expressions, `ref` -//! bindings, and `autorefs`, which are the three ways to introduce -//! a borrow. -//! -//! The key point here is that when you are borrowing a value that -//! is "guaranteed" by a borrowed pointer, you must link the -//! lifetime of that borrowed pointer (`L1`, here) to the lifetime of -//! the borrow itself (`L2`). What do I mean by "guaranteed" by a -//! borrowed pointer? I mean any data that is reached by first -//! dereferencing a borrowed pointer and then either traversing -//! interior offsets or boxes. We say that the guarantor -//! of such data is the region of the borrowed pointer that was -//! traversed. This is essentially the same as the ownership -//! relation, except that a borrowed pointer never owns its -//! contents. - -use crate::check::dropck; -use crate::check::FnCtxt; -use crate::mem_categorization as mc; use crate::outlives::outlives_bounds::InferCtxtExt as _; use rustc_data_structures::stable_set::FxHashSet; use rustc_hir as hir; -use rustc_hir::def_id::LocalDefId; -use rustc_hir::intravisit::{self, Visitor}; -use rustc_hir::PatKind; use rustc_infer::infer::outlives::env::OutlivesEnvironment; -use rustc_infer::infer::{self, InferCtxt, RegionObligation}; -use rustc_middle::hir::place::{PlaceBase, PlaceWithHirId}; -use rustc_middle::ty::adjustment; -use rustc_middle::ty::{self, Ty}; -use rustc_span::Span; -use std::ops::Deref; - -// a variation on try that just returns unit -macro_rules! ignore_err { - ($e:expr) => { - match $e { - Ok(e) => e, - Err(_) => { - debug!("ignoring mem-categorization error!"); - return (); - } - } - }; -} +use rustc_infer::infer::InferCtxt; +use rustc_middle::ty::Ty; pub(crate) trait OutlivesEnvironmentExt<'tcx> { fn add_implied_bounds( @@ -108,7 +11,6 @@ pub(crate) trait OutlivesEnvironmentExt<'tcx> { infcx: &InferCtxt<'_, 'tcx>, fn_sig_tys: FxHashSet<Ty<'tcx>>, body_id: hir::HirId, - span: Span, ); } @@ -135,750 +37,11 @@ impl<'tcx> OutlivesEnvironmentExt<'tcx> for OutlivesEnvironment<'tcx> { infcx: &InferCtxt<'a, 'tcx>, fn_sig_tys: FxHashSet<Ty<'tcx>>, body_id: hir::HirId, - span: Span, ) { for ty in fn_sig_tys { let ty = infcx.resolve_vars_if_possible(ty); - let implied_bounds = infcx.implied_outlives_bounds(self.param_env, body_id, ty, span); + let implied_bounds = infcx.implied_outlives_bounds(self.param_env, body_id, ty); self.add_outlives_bounds(Some(infcx), implied_bounds) } } } - -/////////////////////////////////////////////////////////////////////////// -// PUBLIC ENTRY POINTS - -impl<'a, 'tcx> FnCtxt<'a, 'tcx> { - pub fn regionck_expr(&self, body: &'tcx hir::Body<'tcx>) { - let subject = self.tcx.hir().body_owner_def_id(body.id()); - let id = body.value.hir_id; - let mut rcx = RegionCtxt::new(self, id, Subject(subject), self.param_env); - - // There are no add'l implied bounds when checking a - // standalone expr (e.g., the `E` in a type like `[u32; E]`). - rcx.outlives_environment.save_implied_bounds(id); - - if !self.errors_reported_since_creation() { - // regionck assumes typeck succeeded - rcx.visit_body(body); - rcx.visit_region_obligations(id); - } - // Checked by NLL - rcx.fcx.skip_region_resolution(); - } - - /// Region checking during the WF phase for items. `wf_tys` are the - /// types from which we should derive implied bounds, if any. - #[instrument(level = "debug", skip(self))] - pub fn regionck_item(&self, item_id: hir::HirId, span: Span, wf_tys: FxHashSet<Ty<'tcx>>) { - let subject = self.tcx.hir().local_def_id(item_id); - let mut rcx = RegionCtxt::new(self, item_id, Subject(subject), self.param_env); - rcx.outlives_environment.add_implied_bounds(self, wf_tys, item_id, span); - rcx.outlives_environment.save_implied_bounds(item_id); - rcx.visit_region_obligations(item_id); - rcx.resolve_regions_and_report_errors(); - } - - /// Region check a function body. Not invoked on closures, but - /// only on the "root" fn item (in which closures may be - /// embedded). Walks the function body and adds various add'l - /// constraints that are needed for region inference. This is - /// separated both to isolate "pure" region constraints from the - /// rest of type check and because sometimes we need type - /// inference to have completed before we can determine which - /// constraints to add. - pub(crate) fn regionck_fn( - &self, - fn_id: hir::HirId, - body: &'tcx hir::Body<'tcx>, - span: Span, - wf_tys: FxHashSet<Ty<'tcx>>, - ) { - debug!("regionck_fn(id={})", fn_id); - let subject = self.tcx.hir().body_owner_def_id(body.id()); - let hir_id = body.value.hir_id; - let mut rcx = RegionCtxt::new(self, hir_id, Subject(subject), self.param_env); - // We need to add the implied bounds from the function signature - rcx.outlives_environment.add_implied_bounds(self, wf_tys, fn_id, span); - rcx.outlives_environment.save_implied_bounds(fn_id); - - if !self.errors_reported_since_creation() { - // regionck assumes typeck succeeded - rcx.visit_fn_body(fn_id, body, self.tcx.hir().span(fn_id)); - } - - // Checked by NLL - rcx.fcx.skip_region_resolution(); - } -} - -/////////////////////////////////////////////////////////////////////////// -// INTERNALS - -pub struct RegionCtxt<'a, 'tcx> { - pub fcx: &'a FnCtxt<'a, 'tcx>, - - outlives_environment: OutlivesEnvironment<'tcx>, - - // id of innermost fn body id - body_id: hir::HirId, - body_owner: LocalDefId, - - // id of AST node being analyzed (the subject of the analysis). - subject_def_id: LocalDefId, -} - -impl<'a, 'tcx> Deref for RegionCtxt<'a, 'tcx> { - type Target = FnCtxt<'a, 'tcx>; - fn deref(&self) -> &Self::Target { - self.fcx - } -} - -pub struct Subject(LocalDefId); - -impl<'a, 'tcx> RegionCtxt<'a, 'tcx> { - pub fn new( - fcx: &'a FnCtxt<'a, 'tcx>, - initial_body_id: hir::HirId, - Subject(subject): Subject, - param_env: ty::ParamEnv<'tcx>, - ) -> RegionCtxt<'a, 'tcx> { - let outlives_environment = OutlivesEnvironment::new(param_env); - RegionCtxt { - fcx, - body_id: initial_body_id, - body_owner: subject, - subject_def_id: subject, - outlives_environment, - } - } - - /// Try to resolve the type for the given node, returning `t_err` if an error results. Note that - /// we never care about the details of the error, the same error will be detected and reported - /// in the writeback phase. - /// - /// Note one important point: we do not attempt to resolve *region variables* here. This is - /// because regionck is essentially adding constraints to those region variables and so may yet - /// influence how they are resolved. - /// - /// Consider this silly example: - /// - /// ```ignore UNSOLVED (does replacing @i32 with Box<i32> preserve the desired semantics for the example?) - /// fn borrow(x: &i32) -> &i32 {x} - /// fn foo(x: @i32) -> i32 { // block: B - /// let b = borrow(x); // region: <R0> - /// *b - /// } - /// ``` - /// - /// Here, the region of `b` will be `<R0>`. `<R0>` is constrained to be some subregion of the - /// block B and some superregion of the call. If we forced it now, we'd choose the smaller - /// region (the call). But that would make the *b illegal. Since we don't resolve, the type - /// of b will be `&<R0>.i32` and then `*b` will require that `<R0>` be bigger than the let and - /// the `*b` expression, so we will effectively resolve `<R0>` to be the block B. - pub fn resolve_type(&self, unresolved_ty: Ty<'tcx>) -> Ty<'tcx> { - self.resolve_vars_if_possible(unresolved_ty) - } - - /// Try to resolve the type for the given node. - fn resolve_node_type(&self, id: hir::HirId) -> Ty<'tcx> { - let t = self.node_ty(id); - self.resolve_type(t) - } - - /// This is the "main" function when region-checking a function item or a - /// closure within a function item. It begins by updating various fields - /// (e.g., `outlives_environment`) to be appropriate to the function and - /// then adds constraints derived from the function body. - /// - /// Note that it does **not** restore the state of the fields that - /// it updates! This is intentional, since -- for the main - /// function -- we wish to be able to read the final - /// `outlives_environment` and other fields from the caller. For - /// closures, however, we save and restore any "scoped state" - /// before we invoke this function. (See `visit_fn` in the - /// `intravisit::Visitor` impl below.) - fn visit_fn_body( - &mut self, - id: hir::HirId, // the id of the fn itself - body: &'tcx hir::Body<'tcx>, - span: Span, - ) { - // When we enter a function, we can derive - debug!("visit_fn_body(id={:?})", id); - - let body_id = body.id(); - self.body_id = body_id.hir_id; - self.body_owner = self.tcx.hir().body_owner_def_id(body_id); - - let Some(fn_sig) = self.typeck_results.borrow().liberated_fn_sigs().get(id) else { - bug!("No fn-sig entry for id={:?}", id); - }; - - // Collect the types from which we create inferred bounds. - // For the return type, if diverging, substitute `bool` just - // because it will have no effect. - // - // FIXME(#27579) return types should not be implied bounds - let fn_sig_tys: FxHashSet<_> = - fn_sig.inputs().iter().cloned().chain(Some(fn_sig.output())).collect(); - - self.outlives_environment.add_implied_bounds(self.fcx, fn_sig_tys, body_id.hir_id, span); - self.outlives_environment.save_implied_bounds(body_id.hir_id); - self.link_fn_params(body.params); - self.visit_body(body); - self.visit_region_obligations(body_id.hir_id); - } - - fn visit_inline_const(&mut self, id: hir::HirId, body: &'tcx hir::Body<'tcx>) { - debug!("visit_inline_const(id={:?})", id); - - // Save state of current function. We will restore afterwards. - let old_body_id = self.body_id; - let old_body_owner = self.body_owner; - let env_snapshot = self.outlives_environment.push_snapshot_pre_typeck_child(); - - let body_id = body.id(); - self.body_id = body_id.hir_id; - self.body_owner = self.tcx.hir().body_owner_def_id(body_id); - - self.outlives_environment.save_implied_bounds(body_id.hir_id); - - self.visit_body(body); - self.visit_region_obligations(body_id.hir_id); - - // Restore state from previous function. - self.outlives_environment.pop_snapshot_post_typeck_child(env_snapshot); - self.body_id = old_body_id; - self.body_owner = old_body_owner; - } - - fn visit_region_obligations(&mut self, hir_id: hir::HirId) { - debug!("visit_region_obligations: hir_id={:?}", hir_id); - - // region checking can introduce new pending obligations - // which, when processed, might generate new region - // obligations. So make sure we process those. - self.select_all_obligations_or_error(); - } - - fn resolve_regions_and_report_errors(&self) { - self.infcx.process_registered_region_obligations( - self.outlives_environment.region_bound_pairs_map(), - self.param_env, - ); - - self.fcx.resolve_regions_and_report_errors( - self.subject_def_id.to_def_id(), - &self.outlives_environment, - ); - } - - fn constrain_bindings_in_pat(&mut self, pat: &hir::Pat<'_>) { - debug!("regionck::visit_pat(pat={:?})", pat); - pat.each_binding(|_, hir_id, span, _| { - let typ = self.resolve_node_type(hir_id); - let body_id = self.body_id; - dropck::check_drop_obligations(self, typ, span, body_id); - }) - } -} - -impl<'a, 'tcx> Visitor<'tcx> for RegionCtxt<'a, 'tcx> { - // (..) FIXME(#3238) should use visit_pat, not visit_arm/visit_local, - // However, right now we run into an issue whereby some free - // regions are not properly related if they appear within the - // types of arguments that must be inferred. This could be - // addressed by deferring the construction of the region - // hierarchy, and in particular the relationships between free - // regions, until regionck, as described in #3238. - - fn visit_fn( - &mut self, - fk: intravisit::FnKind<'tcx>, - _: &'tcx hir::FnDecl<'tcx>, - body_id: hir::BodyId, - span: Span, - hir_id: hir::HirId, - ) { - assert!( - matches!(fk, intravisit::FnKind::Closure), - "visit_fn invoked for something other than a closure" - ); - - // Save state of current function before invoking - // `visit_fn_body`. We will restore afterwards. - let old_body_id = self.body_id; - let old_body_owner = self.body_owner; - let env_snapshot = self.outlives_environment.push_snapshot_pre_typeck_child(); - - let body = self.tcx.hir().body(body_id); - self.visit_fn_body(hir_id, body, span); - - // Restore state from previous function. - self.outlives_environment.pop_snapshot_post_typeck_child(env_snapshot); - self.body_id = old_body_id; - self.body_owner = old_body_owner; - } - - //visit_pat: visit_pat, // (..) see above - - fn visit_arm(&mut self, arm: &'tcx hir::Arm<'tcx>) { - // see above - self.constrain_bindings_in_pat(arm.pat); - intravisit::walk_arm(self, arm); - } - - fn visit_local(&mut self, l: &'tcx hir::Local<'tcx>) { - // see above - self.constrain_bindings_in_pat(l.pat); - self.link_local(l); - intravisit::walk_local(self, l); - } - - fn visit_expr(&mut self, expr: &'tcx hir::Expr<'tcx>) { - // Check any autoderefs or autorefs that appear. - let cmt_result = self.constrain_adjustments(expr); - - // If necessary, constrain destructors in this expression. This will be - // the adjusted form if there is an adjustment. - match cmt_result { - Ok(head_cmt) => { - self.check_safety_of_rvalue_destructor_if_necessary(&head_cmt, expr.span); - } - Err(..) => { - self.tcx.sess.delay_span_bug(expr.span, "cat_expr Errd"); - } - } - - match expr.kind { - hir::ExprKind::AddrOf(hir::BorrowKind::Ref, m, ref base) => { - self.link_addr_of(expr, m, base); - - intravisit::walk_expr(self, expr); - } - - hir::ExprKind::Match(ref discr, arms, _) => { - self.link_match(discr, arms); - - intravisit::walk_expr(self, expr); - } - - hir::ExprKind::ConstBlock(anon_const) => { - let body = self.tcx.hir().body(anon_const.body); - self.visit_inline_const(anon_const.hir_id, body); - } - - _ => intravisit::walk_expr(self, expr), - } - } -} - -impl<'a, 'tcx> RegionCtxt<'a, 'tcx> { - /// Creates a temporary `MemCategorizationContext` and pass it to the closure. - fn with_mc<F, R>(&self, f: F) -> R - where - F: for<'b> FnOnce(mc::MemCategorizationContext<'b, 'tcx>) -> R, - { - f(mc::MemCategorizationContext::new( - &self.infcx, - self.outlives_environment.param_env, - self.body_owner, - &self.typeck_results.borrow(), - )) - } - - /// Invoked on any adjustments that occur. Checks that if this is a region pointer being - /// dereferenced, the lifetime of the pointer includes the deref expr. - fn constrain_adjustments( - &mut self, - expr: &hir::Expr<'_>, - ) -> mc::McResult<PlaceWithHirId<'tcx>> { - debug!("constrain_adjustments(expr={:?})", expr); - - let mut place = self.with_mc(|mc| mc.cat_expr_unadjusted(expr))?; - - let typeck_results = self.typeck_results.borrow(); - let adjustments = typeck_results.expr_adjustments(expr); - if adjustments.is_empty() { - return Ok(place); - } - - debug!("constrain_adjustments: adjustments={:?}", adjustments); - - // If necessary, constrain destructors in the unadjusted form of this - // expression. - self.check_safety_of_rvalue_destructor_if_necessary(&place, expr.span); - - for adjustment in adjustments { - debug!("constrain_adjustments: adjustment={:?}, place={:?}", adjustment, place); - - if let adjustment::Adjust::Deref(Some(deref)) = adjustment.kind { - self.link_region( - expr.span, - deref.region, - ty::BorrowKind::from_mutbl(deref.mutbl), - &place, - ); - } - - if let adjustment::Adjust::Borrow(ref autoref) = adjustment.kind { - self.link_autoref(expr, &place, autoref); - } - - place = self.with_mc(|mc| mc.cat_expr_adjusted(expr, place, adjustment))?; - } - - Ok(place) - } - - fn check_safety_of_rvalue_destructor_if_necessary( - &mut self, - place_with_id: &PlaceWithHirId<'tcx>, - span: Span, - ) { - if let PlaceBase::Rvalue = place_with_id.place.base { - if place_with_id.place.projections.is_empty() { - let typ = self.resolve_type(place_with_id.place.ty()); - let body_id = self.body_id; - dropck::check_drop_obligations(self, typ, span, body_id); - } - } - } - /// Adds constraints to inference such that `T: 'a` holds (or - /// reports an error if it cannot). - /// - /// # Parameters - /// - /// - `origin`, the reason we need this constraint - /// - `ty`, the type `T` - /// - `region`, the region `'a` - pub fn type_must_outlive( - &self, - origin: infer::SubregionOrigin<'tcx>, - ty: Ty<'tcx>, - region: ty::Region<'tcx>, - ) { - self.infcx.register_region_obligation( - self.body_id, - RegionObligation { sub_region: region, sup_type: ty, origin }, - ); - } - - /// Computes the guarantor for an expression `&base` and then ensures that the lifetime of the - /// resulting pointer is linked to the lifetime of its guarantor (if any). - fn link_addr_of( - &mut self, - expr: &hir::Expr<'_>, - mutability: hir::Mutability, - base: &hir::Expr<'_>, - ) { - debug!("link_addr_of(expr={:?}, base={:?})", expr, base); - - let cmt = ignore_err!(self.with_mc(|mc| mc.cat_expr(base))); - - debug!("link_addr_of: cmt={:?}", cmt); - - self.link_region_from_node_type(expr.span, expr.hir_id, mutability, &cmt); - } - - /// Computes the guarantors for any ref bindings in a `let` and - /// then ensures that the lifetime of the resulting pointer is - /// linked to the lifetime of the initialization expression. - fn link_local(&self, local: &hir::Local<'_>) { - debug!("regionck::for_local()"); - let init_expr = match local.init { - None => { - return; - } - Some(expr) => &*expr, - }; - let discr_cmt = ignore_err!(self.with_mc(|mc| mc.cat_expr(init_expr))); - self.link_pattern(discr_cmt, local.pat); - } - - /// Computes the guarantors for any ref bindings in a match and - /// then ensures that the lifetime of the resulting pointer is - /// linked to the lifetime of its guarantor (if any). - fn link_match(&self, discr: &hir::Expr<'_>, arms: &[hir::Arm<'_>]) { - debug!("regionck::for_match()"); - let discr_cmt = ignore_err!(self.with_mc(|mc| mc.cat_expr(discr))); - debug!("discr_cmt={:?}", discr_cmt); - for arm in arms { - self.link_pattern(discr_cmt.clone(), arm.pat); - } - } - - /// Computes the guarantors for any ref bindings in a match and - /// then ensures that the lifetime of the resulting pointer is - /// linked to the lifetime of its guarantor (if any). - fn link_fn_params(&self, params: &[hir::Param<'_>]) { - for param in params { - let param_ty = self.node_ty(param.hir_id); - let param_cmt = - self.with_mc(|mc| mc.cat_rvalue(param.hir_id, param.pat.span, param_ty)); - debug!("param_ty={:?} param_cmt={:?} param={:?}", param_ty, param_cmt, param); - self.link_pattern(param_cmt, param.pat); - } - } - - /// Link lifetimes of any ref bindings in `root_pat` to the pointers found - /// in the discriminant, if needed. - fn link_pattern(&self, discr_cmt: PlaceWithHirId<'tcx>, root_pat: &hir::Pat<'_>) { - debug!("link_pattern(discr_cmt={:?}, root_pat={:?})", discr_cmt, root_pat); - ignore_err!(self.with_mc(|mc| { - mc.cat_pattern(discr_cmt, root_pat, |sub_cmt, hir::Pat { kind, span, hir_id, .. }| { - // `ref x` pattern - if let PatKind::Binding(..) = kind - && let Some(ty::BindByReference(mutbl)) = mc.typeck_results.extract_binding_mode(self.tcx.sess, *hir_id, *span) { - self.link_region_from_node_type(*span, *hir_id, mutbl, sub_cmt); - } - }) - })); - } - - /// Link lifetime of borrowed pointer resulting from autoref to lifetimes in the value being - /// autoref'd. - fn link_autoref( - &self, - expr: &hir::Expr<'_>, - expr_cmt: &PlaceWithHirId<'tcx>, - autoref: &adjustment::AutoBorrow<'tcx>, - ) { - debug!("link_autoref(autoref={:?}, expr_cmt={:?})", autoref, expr_cmt); - - match *autoref { - adjustment::AutoBorrow::Ref(r, m) => { - self.link_region(expr.span, r, ty::BorrowKind::from_mutbl(m.into()), expr_cmt); - } - - adjustment::AutoBorrow::RawPtr(_) => {} - } - } - - /// Like `link_region()`, except that the region is extracted from the type of `id`, - /// which must be some reference (`&T`, `&str`, etc). - fn link_region_from_node_type( - &self, - span: Span, - id: hir::HirId, - mutbl: hir::Mutability, - cmt_borrowed: &PlaceWithHirId<'tcx>, - ) { - debug!( - "link_region_from_node_type(id={:?}, mutbl={:?}, cmt_borrowed={:?})", - id, mutbl, cmt_borrowed - ); - - let rptr_ty = self.resolve_node_type(id); - if let ty::Ref(r, _, _) = rptr_ty.kind() { - debug!("rptr_ty={}", rptr_ty); - self.link_region(span, *r, ty::BorrowKind::from_mutbl(mutbl), cmt_borrowed); - } - } - - /// Informs the inference engine that `borrow_cmt` is being borrowed with - /// kind `borrow_kind` and lifetime `borrow_region`. - /// In order to ensure borrowck is satisfied, this may create constraints - /// between regions, as explained in `link_reborrowed_region()`. - fn link_region( - &self, - span: Span, - borrow_region: ty::Region<'tcx>, - borrow_kind: ty::BorrowKind, - borrow_place: &PlaceWithHirId<'tcx>, - ) { - let origin = infer::DataBorrowed(borrow_place.place.ty(), span); - self.type_must_outlive(origin, borrow_place.place.ty(), borrow_region); - - for pointer_ty in borrow_place.place.deref_tys() { - debug!( - "link_region(borrow_region={:?}, borrow_kind={:?}, pointer_ty={:?})", - borrow_region, borrow_kind, borrow_place - ); - match *pointer_ty.kind() { - ty::RawPtr(_) => return, - ty::Ref(ref_region, _, ref_mutability) => { - if self.link_reborrowed_region(span, borrow_region, ref_region, ref_mutability) - { - return; - } - } - _ => assert!(pointer_ty.is_box(), "unexpected built-in deref type {}", pointer_ty), - } - } - if let PlaceBase::Upvar(upvar_id) = borrow_place.place.base { - self.link_upvar_region(span, borrow_region, upvar_id); - } - } - - /// This is the most complicated case: the path being borrowed is - /// itself the referent of a borrowed pointer. Let me give an - /// example fragment of code to make clear(er) the situation: - /// - /// ```ignore (incomplete Rust code) - /// let r: &'a mut T = ...; // the original reference "r" has lifetime 'a - /// ... - /// &'z *r // the reborrow has lifetime 'z - /// ``` - /// - /// Now, in this case, our primary job is to add the inference - /// constraint that `'z <= 'a`. Given this setup, let's clarify the - /// parameters in (roughly) terms of the example: - /// - /// ```plain,ignore (pseudo-Rust) - /// A borrow of: `& 'z bk * r` where `r` has type `& 'a bk T` - /// borrow_region ^~ ref_region ^~ - /// borrow_kind ^~ ref_kind ^~ - /// ref_cmt ^ - /// ``` - /// - /// Here `bk` stands for some borrow-kind (e.g., `mut`, `uniq`, etc). - /// - /// There is a complication beyond the simple scenario I just painted: there - /// may in fact be more levels of reborrowing. In the example, I said the - /// borrow was like `&'z *r`, but it might in fact be a borrow like - /// `&'z **q` where `q` has type `&'a &'b mut T`. In that case, we want to - /// ensure that `'z <= 'a` and `'z <= 'b`. - /// - /// The return value of this function indicates whether we *don't* need to - /// the recurse to the next reference up. - /// - /// This is explained more below. - fn link_reborrowed_region( - &self, - span: Span, - borrow_region: ty::Region<'tcx>, - ref_region: ty::Region<'tcx>, - ref_mutability: hir::Mutability, - ) -> bool { - debug!("link_reborrowed_region: {:?} <= {:?}", borrow_region, ref_region); - self.sub_regions(infer::Reborrow(span), borrow_region, ref_region); - - // Decide whether we need to recurse and link any regions within - // the `ref_cmt`. This is concerned for the case where the value - // being reborrowed is in fact a borrowed pointer found within - // another borrowed pointer. For example: - // - // let p: &'b &'a mut T = ...; - // ... - // &'z **p - // - // What makes this case particularly tricky is that, if the data - // being borrowed is a `&mut` or `&uniq` borrow, borrowck requires - // not only that `'z <= 'a`, (as before) but also `'z <= 'b` - // (otherwise the user might mutate through the `&mut T` reference - // after `'b` expires and invalidate the borrow we are looking at - // now). - // - // So let's re-examine our parameters in light of this more - // complicated (possible) scenario: - // - // A borrow of: `& 'z bk * * p` where `p` has type `&'b bk & 'a bk T` - // borrow_region ^~ ref_region ^~ - // borrow_kind ^~ ref_kind ^~ - // ref_cmt ^~~ - // - // (Note that since we have not examined `ref_cmt.cat`, we don't - // know whether this scenario has occurred; but I wanted to show - // how all the types get adjusted.) - match ref_mutability { - hir::Mutability::Not => { - // The reference being reborrowed is a shareable ref of - // type `&'a T`. In this case, it doesn't matter where we - // *found* the `&T` pointer, the memory it references will - // be valid and immutable for `'a`. So we can stop here. - true - } - - hir::Mutability::Mut => { - // The reference being reborrowed is either an `&mut T`. This is - // the case where recursion is needed. - false - } - } - } - - /// An upvar may be behind up to 2 references: - /// - /// * One can come from the reference to a "by-reference" upvar. - /// * Another one can come from the reference to the closure itself if it's - /// a `FnMut` or `Fn` closure. - /// - /// This function links the lifetimes of those references to the lifetime - /// of the borrow that's provided. See [RegionCtxt::link_reborrowed_region] for some - /// more explanation of this in the general case. - /// - /// We also supply a *cause*, and in this case we set the cause to - /// indicate that the reference being "reborrowed" is itself an upvar. This - /// provides a nicer error message should something go wrong. - fn link_upvar_region( - &self, - span: Span, - borrow_region: ty::Region<'tcx>, - upvar_id: ty::UpvarId, - ) { - debug!("link_upvar_region(borrorw_region={:?}, upvar_id={:?}", borrow_region, upvar_id); - // A by-reference upvar can't be borrowed for longer than the - // upvar is borrowed from the environment. - let closure_local_def_id = upvar_id.closure_expr_id; - let mut all_captures_are_imm_borrow = true; - for captured_place in self - .typeck_results - .borrow() - .closure_min_captures - .get(&closure_local_def_id.to_def_id()) - .and_then(|root_var_min_cap| root_var_min_cap.get(&upvar_id.var_path.hir_id)) - .into_iter() - .flatten() - { - match captured_place.info.capture_kind { - ty::UpvarCapture::ByRef(upvar_borrow) => { - self.sub_regions( - infer::ReborrowUpvar(span, upvar_id), - borrow_region, - captured_place.region.unwrap(), - ); - if let ty::ImmBorrow = upvar_borrow { - debug!("link_upvar_region: capture by shared ref"); - } else { - all_captures_are_imm_borrow = false; - } - } - ty::UpvarCapture::ByValue => { - all_captures_are_imm_borrow = false; - } - } - } - if all_captures_are_imm_borrow { - return; - } - let fn_hir_id = self.tcx.hir().local_def_id_to_hir_id(closure_local_def_id); - let ty = self.resolve_node_type(fn_hir_id); - debug!("link_upvar_region: ty={:?}", ty); - - // A closure capture can't be borrowed for longer than the - // reference to the closure. - if let ty::Closure(_, substs) = ty.kind() { - match self.infcx.closure_kind(substs) { - Some(ty::ClosureKind::Fn | ty::ClosureKind::FnMut) => { - // Region of environment pointer - let env_region = self.tcx.mk_region(ty::ReFree(ty::FreeRegion { - scope: upvar_id.closure_expr_id.to_def_id(), - bound_region: ty::BrEnv, - })); - self.sub_regions( - infer::ReborrowUpvar(span, upvar_id), - borrow_region, - env_region, - ); - } - Some(ty::ClosureKind::FnOnce) => {} - None => { - span_bug!(span, "Have not inferred closure kind before regionck"); - } - } - } - } -} diff --git a/compiler/rustc_typeck/src/check/upvar.rs b/compiler/rustc_typeck/src/check/upvar.rs index 0837d9c4a20..87f85a9842f 100644 --- a/compiler/rustc_typeck/src/check/upvar.rs +++ b/compiler/rustc_typeck/src/check/upvar.rs @@ -1707,12 +1707,14 @@ fn drop_location_span<'tcx>(tcx: TyCtxt<'tcx>, hir_id: hir::HirId) -> Span { hir::Node::Item(item) => match item.kind { hir::ItemKind::Fn(_, _, owner_id) => tcx.hir().span(owner_id.hir_id), _ => { - bug!("Drop location span error: need to handle more ItemKind {:?}", item.kind); + bug!("Drop location span error: need to handle more ItemKind '{:?}'", item.kind); } }, hir::Node::Block(block) => tcx.hir().span(block.hir_id), + hir::Node::TraitItem(item) => tcx.hir().span(item.hir_id()), + hir::Node::ImplItem(item) => tcx.hir().span(item.hir_id()), _ => { - bug!("Drop location span error: need to handle more Node {:?}", owner_node); + bug!("Drop location span error: need to handle more Node '{:?}'", owner_node); } }; tcx.sess.source_map().end_point(owner_span) diff --git a/compiler/rustc_typeck/src/check/wfcheck.rs b/compiler/rustc_typeck/src/check/wfcheck.rs index 7fe36781cf4..84a8cc431f4 100644 --- a/compiler/rustc_typeck/src/check/wfcheck.rs +++ b/compiler/rustc_typeck/src/check/wfcheck.rs @@ -18,7 +18,7 @@ use rustc_middle::ty::subst::{GenericArgKind, InternalSubsts, Subst}; use rustc_middle::ty::trait_def::TraitSpecializationKind; use rustc_middle::ty::{ self, AdtKind, DefIdTree, EarlyBinder, GenericParamDefKind, ToPredicate, Ty, TyCtxt, - TypeFoldable, TypeSuperFoldable, TypeVisitor, + TypeFoldable, TypeSuperVisitable, TypeVisitable, TypeVisitor, }; use rustc_session::parse::feature_err; use rustc_span::symbol::{sym, Ident, Symbol}; @@ -62,7 +62,10 @@ impl<'tcx> CheckWfFcxBuilder<'tcx> { } let wf_tys = f(&fcx); fcx.select_all_obligations_or_error(); - fcx.regionck_item(id, span, wf_tys); + + let mut outlives_environment = OutlivesEnvironment::new(param_env); + outlives_environment.add_implied_bounds(&fcx.infcx, wf_tys, id); + fcx.infcx.check_region_obligations_and_report_errors(&outlives_environment); }); } } @@ -655,13 +658,12 @@ fn resolve_regions_with_wf_tys<'tcx>( // call individually. tcx.infer_ctxt().enter(|infcx| { let mut outlives_environment = OutlivesEnvironment::new(param_env); - outlives_environment.add_implied_bounds(&infcx, wf_tys.clone(), id, DUMMY_SP); - outlives_environment.save_implied_bounds(id); - let region_bound_pairs = outlives_environment.region_bound_pairs_map().get(&id).unwrap(); + outlives_environment.add_implied_bounds(&infcx, wf_tys.clone(), id); + let region_bound_pairs = outlives_environment.region_bound_pairs(); add_constraints(&infcx, region_bound_pairs); - let errors = infcx.resolve_regions(id.expect_owner().to_def_id(), &outlives_environment); + let errors = infcx.resolve_regions(&outlives_environment); debug!(?errors, "errors"); @@ -1367,7 +1369,7 @@ fn check_where_clauses<'tcx, 'fcx>( struct CountParams { params: FxHashSet<u32>, } - impl<'tcx> ty::fold::TypeVisitor<'tcx> for CountParams { + impl<'tcx> ty::visit::TypeVisitor<'tcx> for CountParams { type BreakTy = (); fn visit_ty(&mut self, t: Ty<'tcx>) -> ControlFlow<Self::BreakTy> { diff --git a/compiler/rustc_typeck/src/check/writeback.rs b/compiler/rustc_typeck/src/check/writeback.rs index 9459cf5f8ca..41d241f84ac 100644 --- a/compiler/rustc_typeck/src/check/writeback.rs +++ b/compiler/rustc_typeck/src/check/writeback.rs @@ -15,6 +15,7 @@ use rustc_middle::hir::place::Place as HirPlace; use rustc_middle::mir::FakeReadCause; use rustc_middle::ty::adjustment::{Adjust, Adjustment, PointerCast}; use rustc_middle::ty::fold::{TypeFoldable, TypeFolder, TypeSuperFoldable}; +use rustc_middle::ty::visit::{TypeSuperVisitable, TypeVisitable}; use rustc_middle::ty::{self, ClosureSizeProfileData, Ty, TyCtxt}; use rustc_span::symbol::sym; use rustc_span::Span; @@ -692,8 +693,8 @@ impl<'cx, 'tcx> Resolver<'cx, 'tcx> { Some(self.body.id()), self.span.to_span(self.tcx), t.into(), - vec![], E0282, + false, ) .emit(); } @@ -706,8 +707,8 @@ impl<'cx, 'tcx> Resolver<'cx, 'tcx> { Some(self.body.id()), self.span.to_span(self.tcx), c.into(), - vec![], E0282, + false, ) .emit(); } diff --git a/compiler/rustc_typeck/src/coherence/builtin.rs b/compiler/rustc_typeck/src/coherence/builtin.rs index c647c2a4c1b..d532050d050 100644 --- a/compiler/rustc_typeck/src/coherence/builtin.rs +++ b/compiler/rustc_typeck/src/coherence/builtin.rs @@ -11,7 +11,7 @@ use rustc_infer::infer; use rustc_infer::infer::outlives::env::OutlivesEnvironment; use rustc_infer::infer::TyCtxtInferExt; use rustc_middle::ty::adjustment::CoerceUnsizedInfo; -use rustc_middle::ty::{self, suggest_constraining_type_params, Ty, TyCtxt, TypeFoldable}; +use rustc_middle::ty::{self, suggest_constraining_type_params, Ty, TyCtxt, TypeVisitable}; use rustc_trait_selection::traits::error_reporting::InferCtxtExt; use rustc_trait_selection::traits::misc::{can_type_implement_copy, CopyImplementationError}; use rustc_trait_selection::traits::predicate_for_trait_def; @@ -349,7 +349,7 @@ fn visit_implementation_of_dispatch_from_dyn<'tcx>(tcx: TyCtxt<'tcx>, impl_did: // Finally, resolve all regions. let outlives_env = OutlivesEnvironment::new(param_env); - infcx.resolve_regions_and_report_errors(impl_did.to_def_id(), &outlives_env); + infcx.resolve_regions_and_report_errors(&outlives_env); } } _ => { @@ -606,7 +606,7 @@ pub fn coerce_unsized_info<'tcx>(tcx: TyCtxt<'tcx>, impl_did: DefId) -> CoerceUn // Finally, resolve all regions. let outlives_env = OutlivesEnvironment::new(param_env); - infcx.resolve_regions_and_report_errors(impl_did.to_def_id(), &outlives_env); + infcx.resolve_regions_and_report_errors(&outlives_env); CoerceUnsizedInfo { custom_kind: kind } }) diff --git a/compiler/rustc_typeck/src/coherence/mod.rs b/compiler/rustc_typeck/src/coherence/mod.rs index 447ec87f302..623c2a15232 100644 --- a/compiler/rustc_typeck/src/coherence/mod.rs +++ b/compiler/rustc_typeck/src/coherence/mod.rs @@ -8,7 +8,7 @@ use rustc_errors::struct_span_err; use rustc_hir::def_id::{DefId, LocalDefId}; use rustc_middle::ty::query::Providers; -use rustc_middle::ty::{self, TyCtxt, TypeFoldable}; +use rustc_middle::ty::{self, TyCtxt, TypeVisitable}; use rustc_span::Span; use rustc_trait_selection::traits; diff --git a/compiler/rustc_typeck/src/coherence/orphan.rs b/compiler/rustc_typeck/src/coherence/orphan.rs index f3a043a08a3..ef0a9a27a01 100644 --- a/compiler/rustc_typeck/src/coherence/orphan.rs +++ b/compiler/rustc_typeck/src/coherence/orphan.rs @@ -10,7 +10,7 @@ use rustc_middle::ty::subst::GenericArgKind; use rustc_middle::ty::subst::InternalSubsts; use rustc_middle::ty::util::IgnoreRegions; use rustc_middle::ty::{ - self, ImplPolarity, Ty, TyCtxt, TypeFoldable, TypeSuperFoldable, TypeVisitor, + self, ImplPolarity, Ty, TyCtxt, TypeSuperVisitable, TypeVisitable, TypeVisitor, }; use rustc_session::lint; use rustc_span::def_id::{DefId, LocalDefId}; diff --git a/compiler/rustc_typeck/src/collect/type_of.rs b/compiler/rustc_typeck/src/collect/type_of.rs index 6ee2b544916..f942a4fb53a 100644 --- a/compiler/rustc_typeck/src/collect/type_of.rs +++ b/compiler/rustc_typeck/src/collect/type_of.rs @@ -8,7 +8,7 @@ use rustc_hir::{HirId, Node}; use rustc_middle::hir::nested_filter; use rustc_middle::ty::subst::InternalSubsts; use rustc_middle::ty::util::IntTypeExt; -use rustc_middle::ty::{self, DefIdTree, Ty, TyCtxt, TypeFoldable, TypeFolder, TypeSuperFoldable}; +use rustc_middle::ty::{self, DefIdTree, Ty, TyCtxt, TypeFolder, TypeSuperFoldable, TypeVisitable}; use rustc_span::symbol::Ident; use rustc_span::{Span, DUMMY_SP}; diff --git a/compiler/rustc_typeck/src/constrained_generic_params.rs b/compiler/rustc_typeck/src/constrained_generic_params.rs index 858cf63390a..8428e466406 100644 --- a/compiler/rustc_typeck/src/constrained_generic_params.rs +++ b/compiler/rustc_typeck/src/constrained_generic_params.rs @@ -1,5 +1,5 @@ use rustc_data_structures::fx::FxHashSet; -use rustc_middle::ty::fold::{TypeFoldable, TypeSuperFoldable, TypeVisitor}; +use rustc_middle::ty::visit::{TypeSuperVisitable, TypeVisitable, TypeVisitor}; use rustc_middle::ty::{self, Ty, TyCtxt}; use rustc_span::source_map::Span; use std::ops::ControlFlow; @@ -43,7 +43,7 @@ pub fn parameters_for_impl<'tcx>( /// of parameters whose values are needed in order to constrain `ty` - these /// differ, with the latter being a superset, in the presence of projections. pub fn parameters_for<'tcx>( - t: &impl TypeFoldable<'tcx>, + t: &impl TypeVisitable<'tcx>, include_nonconstraining: bool, ) -> Vec<Parameter> { let mut collector = ParameterCollector { parameters: vec![], include_nonconstraining }; diff --git a/compiler/rustc_typeck/src/impl_wf_check.rs b/compiler/rustc_typeck/src/impl_wf_check.rs index 981c35e184b..e7ca70de4ba 100644 --- a/compiler/rustc_typeck/src/impl_wf_check.rs +++ b/compiler/rustc_typeck/src/impl_wf_check.rs @@ -16,7 +16,7 @@ use rustc_errors::struct_span_err; use rustc_hir::def::DefKind; use rustc_hir::def_id::LocalDefId; use rustc_middle::ty::query::Providers; -use rustc_middle::ty::{self, TyCtxt, TypeFoldable}; +use rustc_middle::ty::{self, TyCtxt, TypeVisitable}; use rustc_span::Span; use std::collections::hash_map::Entry::{Occupied, Vacant}; 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 f07396ce74f..c46b825f457 100644 --- a/compiler/rustc_typeck/src/impl_wf_check/min_specialization.rs +++ b/compiler/rustc_typeck/src/impl_wf_check/min_specialization.rs @@ -75,7 +75,7 @@ use rustc_infer::infer::{InferCtxt, TyCtxtInferExt}; use rustc_infer::traits::specialization_graph::Node; use rustc_middle::ty::subst::{GenericArg, InternalSubsts, SubstsRef}; use rustc_middle::ty::trait_def::TraitSpecializationKind; -use rustc_middle::ty::{self, TyCtxt, TypeFoldable}; +use rustc_middle::ty::{self, TyCtxt, TypeVisitable}; use rustc_span::Span; use rustc_trait_selection::traits::{self, translate_substs, wf}; @@ -150,7 +150,7 @@ fn get_impl_substs<'tcx>( // Conservatively use an empty `ParamEnv`. let outlives_env = OutlivesEnvironment::new(ty::ParamEnv::empty()); - infcx.resolve_regions_and_report_errors(impl1_def_id.to_def_id(), &outlives_env); + infcx.resolve_regions_and_report_errors(&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 }); @@ -279,11 +279,16 @@ fn check_predicates<'tcx>( span: Span, ) { let tcx = infcx.tcx; - let impl1_predicates: Vec<_> = traits::elaborate_predicates( + let instantiated = tcx.predicates_of(impl1_def_id).instantiate(tcx, impl1_substs); + let impl1_predicates: Vec<_> = traits::elaborate_predicates_with_span( tcx, - tcx.predicates_of(impl1_def_id).instantiate(tcx, impl1_substs).predicates.into_iter(), + std::iter::zip( + instantiated.predicates, + // Don't drop predicates (unsound!) because `spans` is too short + instantiated.spans.into_iter().chain(std::iter::repeat(span)), + ), ) - .map(|obligation| obligation.predicate) + .map(|obligation| (obligation.predicate, obligation.cause.span)) .collect(); let mut impl2_predicates = if impl2_node.is_from_trait() { @@ -321,7 +326,7 @@ fn check_predicates<'tcx>( // which is sound because we forbid impls like the following // // impl<D: Debug> AlwaysApplicable for D { } - let always_applicable_traits = impl1_predicates.iter().copied().filter(|&predicate| { + let always_applicable_traits = impl1_predicates.iter().copied().filter(|&(predicate, _)| { matches!( trait_predicate_kind(tcx, predicate), Some(TraitSpecializationKind::AlwaysApplicable) @@ -345,11 +350,11 @@ fn check_predicates<'tcx>( } } impl2_predicates.extend( - traits::elaborate_predicates(tcx, always_applicable_traits) + traits::elaborate_predicates_with_span(tcx, always_applicable_traits) .map(|obligation| obligation.predicate), ); - for predicate in impl1_predicates { + for (predicate, span) in impl1_predicates { if !impl2_predicates.contains(&predicate) { check_specialization_on(tcx, predicate, span) } @@ -384,9 +389,17 @@ fn check_specialization_on<'tcx>(tcx: TyCtxt<'tcx>, predicate: ty::Predicate<'tc .emit(); } } + ty::PredicateKind::Projection(ty::ProjectionPredicate { projection_ty, term }) => { + tcx.sess + .struct_span_err( + span, + &format!("cannot specialize on associated type `{projection_ty} == {term}`",), + ) + .emit(); + } _ => { tcx.sess - .struct_span_err(span, &format!("cannot specialize on `{:?}`", predicate)) + .struct_span_err(span, &format!("cannot specialize on predicate `{}`", predicate)) .emit(); } } diff --git a/compiler/rustc_typeck/src/mem_categorization.rs b/compiler/rustc_typeck/src/mem_categorization.rs index 9acae8d79e7..ced919f66db 100644 --- a/compiler/rustc_typeck/src/mem_categorization.rs +++ b/compiler/rustc_typeck/src/mem_categorization.rs @@ -51,6 +51,7 @@ use rustc_middle::hir::place::*; use rustc_middle::ty::adjustment; use rustc_middle::ty::fold::TypeFoldable; +use rustc_middle::ty::visit::TypeVisitable; use rustc_middle::ty::{self, Ty, TyCtxt}; use rustc_data_structures::fx::FxIndexMap; diff --git a/compiler/rustc_typeck/src/outlives/outlives_bounds.rs b/compiler/rustc_typeck/src/outlives/outlives_bounds.rs index 3bf697e7682..70b8bcd0220 100644 --- a/compiler/rustc_typeck/src/outlives/outlives_bounds.rs +++ b/compiler/rustc_typeck/src/outlives/outlives_bounds.rs @@ -1,6 +1,5 @@ use rustc_hir as hir; use rustc_middle::ty::{self, Ty}; -use rustc_span::source_map::Span; use rustc_trait_selection::infer::InferCtxt; use rustc_trait_selection::traits::query::type_op::{self, TypeOp, TypeOpOutput}; use rustc_trait_selection::traits::query::NoSolution; @@ -14,7 +13,6 @@ pub trait InferCtxtExt<'tcx> { param_env: ty::ParamEnv<'tcx>, body_id: hir::HirId, ty: Ty<'tcx>, - span: Span, ) -> Vec<OutlivesBound<'tcx>>; } @@ -38,16 +36,14 @@ impl<'cx, 'tcx> InferCtxtExt<'tcx> for InferCtxt<'cx, 'tcx> { /// Note that this may cause outlives obligations to be injected /// into the inference context with this body-id. /// - `ty`, the type that we are supposed to assume is WF. - /// - `span`, a span to use when normalizing, hopefully not important, - /// might be useful if a `bug!` occurs. - #[instrument(level = "debug", skip(self, param_env, body_id, span))] + #[instrument(level = "debug", skip(self, param_env, body_id))] fn implied_outlives_bounds( &self, param_env: ty::ParamEnv<'tcx>, body_id: hir::HirId, ty: Ty<'tcx>, - span: Span, ) -> Vec<OutlivesBound<'tcx>> { + let span = self.tcx.hir().span(body_id); let result = param_env .and(type_op::implied_outlives_bounds::ImpliedOutlivesBounds { ty }) .fully_perform(self); diff --git a/compiler/rustc_typeck/src/structured_errors/missing_cast_for_variadic_arg.rs b/compiler/rustc_typeck/src/structured_errors/missing_cast_for_variadic_arg.rs index bafc5a0b918..324df313ef1 100644 --- a/compiler/rustc_typeck/src/structured_errors/missing_cast_for_variadic_arg.rs +++ b/compiler/rustc_typeck/src/structured_errors/missing_cast_for_variadic_arg.rs @@ -1,6 +1,6 @@ use crate::structured_errors::StructuredDiagnostic; use rustc_errors::{Applicability, DiagnosticBuilder, DiagnosticId, ErrorGuaranteed}; -use rustc_middle::ty::{Ty, TypeFoldable}; +use rustc_middle::ty::{Ty, TypeVisitable}; use rustc_session::Session; use rustc_span::Span; diff --git a/compiler/rustc_typeck/src/structured_errors/sized_unsized_cast.rs b/compiler/rustc_typeck/src/structured_errors/sized_unsized_cast.rs index afc5c1fe6cc..bb608805488 100644 --- a/compiler/rustc_typeck/src/structured_errors/sized_unsized_cast.rs +++ b/compiler/rustc_typeck/src/structured_errors/sized_unsized_cast.rs @@ -1,6 +1,6 @@ use crate::structured_errors::StructuredDiagnostic; use rustc_errors::{DiagnosticBuilder, DiagnosticId, ErrorGuaranteed}; -use rustc_middle::ty::{Ty, TypeFoldable}; +use rustc_middle::ty::{Ty, TypeVisitable}; use rustc_session::Session; use rustc_span::Span; diff --git a/library/alloc/src/boxed.rs b/library/alloc/src/boxed.rs index cc395759b20..d83bab7bbbd 100644 --- a/library/alloc/src/boxed.rs +++ b/library/alloc/src/boxed.rs @@ -206,7 +206,7 @@ impl<T> Box<T> { /// ``` /// let five = Box::new(5); /// ``` - #[cfg(all(not(no_global_oom_handling), not(bootstrap)))] + #[cfg(all(not(no_global_oom_handling)))] #[inline(always)] #[stable(feature = "rust1", since = "1.0.0")] #[must_use] @@ -215,23 +215,6 @@ impl<T> Box<T> { Box::new(x) } - /// Allocates memory on the heap and then places `x` into it. - /// - /// This doesn't actually allocate if `T` is zero-sized. - /// - /// # Examples - /// - /// ``` - /// let five = Box::new(5); - /// ``` - #[cfg(all(not(no_global_oom_handling), bootstrap))] - #[inline(always)] - #[stable(feature = "rust1", since = "1.0.0")] - #[must_use] - pub fn new(x: T) -> Self { - box x - } - /// Constructs a new box with uninitialized contents. /// /// # Examples @@ -296,7 +279,7 @@ impl<T> Box<T> { #[must_use] #[inline(always)] pub fn pin(x: T) -> Pin<Box<T>> { - (#[cfg_attr(not(bootstrap), rustc_box)] + (#[rustc_box] Box::new(x)) .into() } @@ -1255,7 +1238,7 @@ unsafe impl<#[may_dangle] T: ?Sized, A: Allocator> Drop for Box<T, A> { impl<T: Default> Default for Box<T> { /// Creates a `Box<T>`, with the `Default` value for T. fn default() -> Self { - #[cfg_attr(not(bootstrap), rustc_box)] + #[rustc_box] Box::new(T::default()) } } @@ -1628,7 +1611,7 @@ impl<T, const N: usize> From<[T; N]> for Box<[T]> { /// println!("{boxed:?}"); /// ``` fn from(array: [T; N]) -> Box<[T]> { - #[cfg_attr(not(bootstrap), rustc_box)] + #[rustc_box] Box::new(array) } } diff --git a/library/alloc/src/boxed/thin.rs b/library/alloc/src/boxed/thin.rs index 09308d4d090..649ccfcaa9e 100644 --- a/library/alloc/src/boxed/thin.rs +++ b/library/alloc/src/boxed/thin.rs @@ -31,7 +31,9 @@ use core::ptr::{self, NonNull}; /// ``` #[unstable(feature = "thin_box", issue = "92791")] pub struct ThinBox<T: ?Sized> { - ptr: WithHeader<<T as Pointee>::Metadata>, + // This is essentially `WithHeader<<T as Pointee>::Metadata>`, + // but that would be invariant in `T`, and we want covariance. + ptr: WithOpaqueHeader, _marker: PhantomData<T>, } @@ -59,7 +61,7 @@ impl<T> ThinBox<T> { #[cfg(not(no_global_oom_handling))] pub fn new(value: T) -> Self { let meta = ptr::metadata(&value); - let ptr = WithHeader::new(meta, value); + let ptr = WithOpaqueHeader::new(meta, value); ThinBox { ptr, _marker: PhantomData } } } @@ -83,7 +85,7 @@ impl<Dyn: ?Sized> ThinBox<Dyn> { T: Unsize<Dyn>, { let meta = ptr::metadata(&value as &Dyn); - let ptr = WithHeader::new(meta, value); + let ptr = WithOpaqueHeader::new(meta, value); ThinBox { ptr, _marker: PhantomData } } } @@ -130,7 +132,7 @@ impl<T: ?Sized> Drop for ThinBox<T> { unsafe { let value = self.deref_mut(); let value = value as *mut T; - self.ptr.drop::<T>(value); + self.with_header().drop::<T>(value); } } } @@ -140,11 +142,16 @@ impl<T: ?Sized> ThinBox<T> { fn meta(&self) -> <T as Pointee>::Metadata { // Safety: // - NonNull and valid. - unsafe { *self.ptr.header() } + unsafe { *self.with_header().header() } } fn data(&self) -> *mut u8 { - self.ptr.value() + self.with_header().value() + } + + fn with_header(&self) -> &WithHeader<<T as Pointee>::Metadata> { + // SAFETY: both types are transparent to `NonNull<u8>` + unsafe { &*((&self.ptr) as *const WithOpaqueHeader as *const WithHeader<_>) } } } @@ -153,8 +160,22 @@ impl<T: ?Sized> ThinBox<T> { /// metadata (`H`) are ZSTs. /// 2. A pointer to a valid `T` that has a header `H` directly before the /// pointed-to location. +#[repr(transparent)] struct WithHeader<H>(NonNull<u8>, PhantomData<H>); +/// An opaque representation of `WithHeader<H>` to avoid the +/// projection invariance of `<T as Pointee>::Metadata`. +#[repr(transparent)] +struct WithOpaqueHeader(NonNull<u8>); + +impl WithOpaqueHeader { + #[cfg(not(no_global_oom_handling))] + fn new<H, T>(header: H, value: T) -> Self { + let ptr = WithHeader::new(header, value); + Self(ptr.0) + } +} + impl<H> WithHeader<H> { #[cfg(not(no_global_oom_handling))] fn new<T>(header: H, value: T) -> WithHeader<H> { diff --git a/library/alloc/src/lib.rs b/library/alloc/src/lib.rs index c08caa7b93e..d3816d70b63 100644 --- a/library/alloc/src/lib.rs +++ b/library/alloc/src/lib.rs @@ -149,7 +149,6 @@ #![feature(allocator_internals)] #![feature(allow_internal_unstable)] #![feature(associated_type_bounds)] -#![cfg_attr(bootstrap, feature(box_syntax))] #![feature(cfg_sanitize)] #![feature(const_deref)] #![feature(const_mut_refs)] diff --git a/library/alloc/src/macros.rs b/library/alloc/src/macros.rs index 37898b6655f..88eb6aa7a83 100644 --- a/library/alloc/src/macros.rs +++ b/library/alloc/src/macros.rs @@ -34,7 +34,7 @@ /// be mindful of side effects. /// /// [`Vec`]: crate::vec::Vec -#[cfg(all(not(no_global_oom_handling), not(test), not(bootstrap)))] +#[cfg(all(not(no_global_oom_handling), not(test)))] #[macro_export] #[stable(feature = "rust1", since = "1.0.0")] #[rustc_diagnostic_item = "vec_macro"] @@ -54,24 +54,6 @@ macro_rules! vec { ); } -/// Creates a `Vec` containing the arguments (bootstrap version). -#[cfg(all(not(no_global_oom_handling), not(test), bootstrap))] -#[macro_export] -#[stable(feature = "rust1", since = "1.0.0")] -#[rustc_diagnostic_item = "vec_macro"] -#[allow_internal_unstable(box_syntax, liballoc_internals)] -macro_rules! vec { - () => ( - $crate::__rust_force_expr!($crate::vec::Vec::new()) - ); - ($elem:expr; $n:expr) => ( - $crate::__rust_force_expr!($crate::vec::from_elem($elem, $n)) - ); - ($($x:expr),+ $(,)?) => ( - $crate::__rust_force_expr!(<[_]>::into_vec(box [$($x),+])) - ); -} - // HACK(japaric): with cfg(test) the inherent `[T]::into_vec` method, which is // required for this macro definition, is not available. Instead use the // `slice::into_vec` function which is only available with cfg(test) diff --git a/library/alloc/src/vec/mod.rs b/library/alloc/src/vec/mod.rs index e25f98d8aa6..fa9f2131c0c 100644 --- a/library/alloc/src/vec/mod.rs +++ b/library/alloc/src/vec/mod.rs @@ -1379,9 +1379,6 @@ impl<T, A: Allocator> Vec<T, A> { } let len = self.len(); - if index > len { - assert_failed(index, len); - } // space for the new element if len == self.buf.capacity() { @@ -1393,9 +1390,15 @@ impl<T, A: Allocator> Vec<T, A> { // The spot to put the new value { let p = self.as_mut_ptr().add(index); - // Shift everything over to make space. (Duplicating the - // `index`th element into two consecutive places.) - ptr::copy(p, p.offset(1), len - index); + if index < len { + // Shift everything over to make space. (Duplicating the + // `index`th element into two consecutive places.) + ptr::copy(p, p.offset(1), len - index); + } else if index == len { + // No elements need shifting. + } else { + assert_failed(index, len); + } // Write it in, overwriting the first copy of the `index`th // element. ptr::write(p, element); @@ -3017,7 +3020,7 @@ impl<T, const N: usize> From<[T; N]> for Vec<T> { #[cfg(not(test))] fn from(s: [T; N]) -> Vec<T> { <[T]>::into_vec( - #[cfg_attr(not(bootstrap), rustc_box)] + #[rustc_box] Box::new(s), ) } diff --git a/library/alloc/tests/thin_box.rs b/library/alloc/tests/thin_box.rs index 70d1db8b457..368aa564f94 100644 --- a/library/alloc/tests/thin_box.rs +++ b/library/alloc/tests/thin_box.rs @@ -26,6 +26,13 @@ fn want_thin() { assert!(is_thin::<i32>()); } +#[allow(dead_code)] +fn assert_covariance() { + fn thin_box<'new>(b: ThinBox<[&'static str]>) -> ThinBox<[&'new str]> { + b + } +} + #[track_caller] fn verify_aligned<T>(ptr: *const T) { // Use `black_box` to attempt to obscure the fact that we're calling this diff --git a/library/core/src/clone.rs b/library/core/src/clone.rs index fd5624812f5..06dca7e59a2 100644 --- a/library/core/src/clone.rs +++ b/library/core/src/clone.rs @@ -106,7 +106,7 @@ use crate::marker::Destruct; #[lang = "clone"] #[rustc_diagnostic_item = "Clone"] #[rustc_trivial_field_reads] -#[cfg_attr(not(bootstrap), const_trait)] +#[const_trait] pub trait Clone: Sized { /// Returns a copy of the value. /// @@ -129,7 +129,6 @@ pub trait Clone: Sized { /// allocations. #[inline] #[stable(feature = "rust1", since = "1.0.0")] - #[cfg_attr(bootstrap, default_method_body_is_const)] fn clone_from(&mut self, source: &Self) where Self: ~const Destruct, diff --git a/library/core/src/cmp.rs b/library/core/src/cmp.rs index 064675ee7cf..1d3466696ed 100644 --- a/library/core/src/cmp.rs +++ b/library/core/src/cmp.rs @@ -214,7 +214,7 @@ use self::Ordering::*; append_const_msg, ) )] -#[cfg_attr(not(bootstrap), const_trait)] +#[const_trait] #[rustc_diagnostic_item = "PartialEq"] pub trait PartialEq<Rhs: ?Sized = Self> { /// This method tests for `self` and `other` values to be equal, and is used @@ -227,7 +227,6 @@ pub trait PartialEq<Rhs: ?Sized = Self> { #[inline] #[must_use] #[stable(feature = "rust1", since = "1.0.0")] - #[cfg_attr(bootstrap, default_method_body_is_const)] fn ne(&self, other: &Rhs) -> bool { !self.eq(other) } @@ -1054,7 +1053,7 @@ impl PartialOrd for Ordering { append_const_msg, ) )] -#[cfg_attr(not(bootstrap), const_trait)] +#[const_trait] #[rustc_diagnostic_item = "PartialOrd"] pub trait PartialOrd<Rhs: ?Sized = Self>: PartialEq<Rhs> { /// This method returns an ordering between `self` and `other` values if one exists. @@ -1098,7 +1097,6 @@ pub trait PartialOrd<Rhs: ?Sized = Self>: PartialEq<Rhs> { #[inline] #[must_use] #[stable(feature = "rust1", since = "1.0.0")] - #[cfg_attr(bootstrap, default_method_body_is_const)] fn lt(&self, other: &Rhs) -> bool { matches!(self.partial_cmp(other), Some(Less)) } @@ -1118,7 +1116,6 @@ pub trait PartialOrd<Rhs: ?Sized = Self>: PartialEq<Rhs> { #[inline] #[must_use] #[stable(feature = "rust1", since = "1.0.0")] - #[cfg_attr(bootstrap, default_method_body_is_const)] fn le(&self, other: &Rhs) -> bool { // Pattern `Some(Less | Eq)` optimizes worse than negating `None | Some(Greater)`. // FIXME: The root cause was fixed upstream in LLVM with: @@ -1141,7 +1138,6 @@ pub trait PartialOrd<Rhs: ?Sized = Self>: PartialEq<Rhs> { #[inline] #[must_use] #[stable(feature = "rust1", since = "1.0.0")] - #[cfg_attr(bootstrap, default_method_body_is_const)] fn gt(&self, other: &Rhs) -> bool { matches!(self.partial_cmp(other), Some(Greater)) } @@ -1161,7 +1157,6 @@ pub trait PartialOrd<Rhs: ?Sized = Self>: PartialEq<Rhs> { #[inline] #[must_use] #[stable(feature = "rust1", since = "1.0.0")] - #[cfg_attr(bootstrap, default_method_body_is_const)] fn ge(&self, other: &Rhs) -> bool { matches!(self.partial_cmp(other), Some(Greater | Equal)) } diff --git a/library/core/src/fmt/mod.rs b/library/core/src/fmt/mod.rs index 1d4be42b4a2..6c3bb7229e5 100644 --- a/library/core/src/fmt/mod.rs +++ b/library/core/src/fmt/mod.rs @@ -2562,7 +2562,7 @@ macro_rules! tuple { macro_rules! maybe_tuple_doc { ($a:ident @ #[$meta:meta] $item:item) => { - #[cfg_attr(not(bootstrap), doc(tuple_variadic))] + #[doc(tuple_variadic)] #[doc = "This trait is implemented for tuples up to twelve items long."] #[$meta] $item diff --git a/library/core/src/hash/mod.rs b/library/core/src/hash/mod.rs index 2c152fe1b2c..1e4c22aea10 100644 --- a/library/core/src/hash/mod.rs +++ b/library/core/src/hash/mod.rs @@ -900,7 +900,7 @@ mod impls { macro_rules! maybe_tuple_doc { ($a:ident @ #[$meta:meta] $item:item) => { - #[cfg_attr(not(bootstrap), doc(tuple_variadic))] + #[doc(tuple_variadic)] #[doc = "This trait is implemented for tuples up to twelve items long."] #[$meta] $item diff --git a/library/core/src/intrinsics.rs b/library/core/src/intrinsics.rs index d230c06a211..2895c923adc 100644 --- a/library/core/src/intrinsics.rs +++ b/library/core/src/intrinsics.rs @@ -2356,6 +2356,9 @@ pub(crate) fn is_nonoverlapping<T>(src: *const T, dst: *const T, count: usize) - /// `copy_nonoverlapping` is semantically equivalent to C's [`memcpy`], but /// with the argument order swapped. /// +/// The copy is "untyped" in the sense that data may be uninitialized or otherwise violate the +/// requirements of `T`. The initialization state is preserved exactly. +/// /// [`memcpy`]: https://en.cppreference.com/w/c/string/byte/memcpy /// /// # Safety @@ -2461,6 +2464,9 @@ pub const unsafe fn copy_nonoverlapping<T>(src: *const T, dst: *mut T, count: us /// order swapped. Copying takes place as if the bytes were copied from `src` /// to a temporary array and then copied from the array to `dst`. /// +/// The copy is "untyped" in the sense that data may be uninitialized or otherwise violate the +/// requirements of `T`. The initialization state is preserved exactly. +/// /// [`memmove`]: https://en.cppreference.com/w/c/string/byte/memmove /// /// # Safety diff --git a/library/core/src/iter/traits/exact_size.rs b/library/core/src/iter/traits/exact_size.rs index a476799b70d..1757e37ec0e 100644 --- a/library/core/src/iter/traits/exact_size.rs +++ b/library/core/src/iter/traits/exact_size.rs @@ -66,13 +66,15 @@ /// /// // And now we can use it! /// -/// let counter = Counter::new(); +/// let mut counter = Counter::new(); /// /// assert_eq!(5, counter.len()); +/// let _ = counter.next(); +/// assert_eq!(4, counter.len()); /// ``` #[stable(feature = "rust1", since = "1.0.0")] pub trait ExactSizeIterator: Iterator { - /// Returns the exact length of the iterator. + /// Returns the exact remaining length of the iterator. /// /// The implementation ensures that the iterator will return exactly `len()` /// more times a [`Some(T)`] value, before returning [`None`]. @@ -93,9 +95,11 @@ pub trait ExactSizeIterator: Iterator { /// /// ``` /// // a finite range knows exactly how many times it will iterate - /// let five = 0..5; + /// let mut range = 0..5; /// - /// assert_eq!(5, five.len()); + /// assert_eq!(5, range.len()); + /// let _ = range.next(); + /// assert_eq!(4, range.len()); /// ``` #[inline] #[stable(feature = "rust1", since = "1.0.0")] diff --git a/library/core/src/iter/traits/iterator.rs b/library/core/src/iter/traits/iterator.rs index 326b98ec947..275412b57b5 100644 --- a/library/core/src/iter/traits/iterator.rs +++ b/library/core/src/iter/traits/iterator.rs @@ -177,9 +177,11 @@ pub trait Iterator { /// /// ``` /// let a = [1, 2, 3]; - /// let iter = a.iter(); + /// let mut iter = a.iter(); /// /// assert_eq!((3, Some(3)), iter.size_hint()); + /// let _ = iter.next(); + /// assert_eq!((2, Some(2)), iter.size_hint()); /// ``` /// /// A more complex example: diff --git a/library/core/src/primitive_docs.rs b/library/core/src/primitive_docs.rs index 00793f7f920..401c8159988 100644 --- a/library/core/src/primitive_docs.rs +++ b/library/core/src/primitive_docs.rs @@ -996,7 +996,7 @@ impl<T> (T,) {} // Fake impl that's only really used for docs. #[cfg(doc)] #[stable(feature = "rust1", since = "1.0.0")] -#[cfg_attr(not(bootstrap), doc(tuple_variadic))] +#[doc(tuple_variadic)] /// This trait is implemented on arbitrary-length tuples. impl<T: Clone> Clone for (T,) { fn clone(&self) -> Self { @@ -1007,7 +1007,7 @@ impl<T: Clone> Clone for (T,) { // Fake impl that's only really used for docs. #[cfg(doc)] #[stable(feature = "rust1", since = "1.0.0")] -#[cfg_attr(not(bootstrap), doc(tuple_variadic))] +#[doc(tuple_variadic)] /// This trait is implemented on arbitrary-length tuples. impl<T: Copy> Copy for (T,) { // empty diff --git a/library/core/src/ptr/mod.rs b/library/core/src/ptr/mod.rs index 8fb0bfbe2e3..4f257f9de30 100644 --- a/library/core/src/ptr/mod.rs +++ b/library/core/src/ptr/mod.rs @@ -507,55 +507,12 @@ pub unsafe fn drop_in_place<T: ?Sized>(to_drop: *mut T) { #[stable(feature = "rust1", since = "1.0.0")] #[rustc_promotable] #[rustc_const_stable(feature = "const_ptr_null", since = "1.24.0")] -#[rustc_diagnostic_item = "ptr_null"] -#[cfg(bootstrap)] -pub const fn null<T>() -> *const T { - invalid(0) -} - -/// Creates a null raw pointer. -/// -/// # Examples -/// -/// ``` -/// use std::ptr; -/// -/// let p: *const i32 = ptr::null(); -/// assert!(p.is_null()); -/// ``` -#[inline(always)] -#[must_use] -#[stable(feature = "rust1", since = "1.0.0")] -#[rustc_promotable] -#[rustc_const_stable(feature = "const_ptr_null", since = "1.24.0")] #[rustc_allow_const_fn_unstable(ptr_metadata)] #[rustc_diagnostic_item = "ptr_null"] -#[cfg(not(bootstrap))] pub const fn null<T: ?Sized + Thin>() -> *const T { from_raw_parts(invalid(0), ()) } -/// Creates a null mutable raw pointer. -/// -/// # Examples -/// -/// ``` -/// use std::ptr; -/// -/// let p: *mut i32 = ptr::null_mut(); -/// assert!(p.is_null()); -/// ``` -#[inline(always)] -#[must_use] -#[stable(feature = "rust1", since = "1.0.0")] -#[rustc_promotable] -#[rustc_const_stable(feature = "const_ptr_null", since = "1.24.0")] -#[rustc_diagnostic_item = "ptr_null_mut"] -#[cfg(bootstrap)] -pub const fn null_mut<T>() -> *mut T { - invalid_mut(0) -} - /// Creates an invalid pointer with the given address. /// /// This is different from `addr as *const T`, which creates a pointer that picks up a previously @@ -707,7 +664,6 @@ where #[rustc_const_stable(feature = "const_ptr_null", since = "1.24.0")] #[rustc_allow_const_fn_unstable(ptr_metadata)] #[rustc_diagnostic_item = "ptr_null_mut"] -#[cfg(not(bootstrap))] pub const fn null_mut<T: ?Sized + Thin>() -> *mut T { from_raw_parts_mut(invalid_mut(0), ()) } @@ -774,7 +730,7 @@ pub const fn slice_from_raw_parts_mut<T>(data: *mut T, len: usize) -> *mut [T] { /// Swaps the values at two mutable locations of the same type, without /// deinitializing either. /// -/// But for the following two exceptions, this function is semantically +/// But for the following exceptions, this function is semantically /// equivalent to [`mem::swap`]: /// /// * It operates on raw pointers instead of references. When references are @@ -784,6 +740,9 @@ pub const fn slice_from_raw_parts_mut<T>(data: *mut T, len: usize) -> *mut [T] { /// overlapping region of memory from `x` will be used. This is demonstrated /// in the second example below. /// +/// * The operation is "untyped" in the sense that data may be uninitialized or otherwise violate +/// the requirements of `T`. The initialization state is preserved exactly. +/// /// # Safety /// /// Behavior is undefined if any of the following conditions are violated: @@ -860,6 +819,9 @@ pub const unsafe fn swap<T>(x: *mut T, y: *mut T) { /// Swaps `count * size_of::<T>()` bytes between the two regions of memory /// beginning at `x` and `y`. The two regions must *not* overlap. /// +/// The operation is "untyped" in the sense that data may be uninitialized or otherwise violate the +/// requirements of `T`. The initialization state is preserved exactly. +/// /// # Safety /// /// Behavior is undefined if any of the following conditions are violated: @@ -905,15 +867,15 @@ pub const unsafe fn swap_nonoverlapping<T>(x: *mut T, y: *mut T, count: usize) { if mem::align_of::<T>() >= mem::align_of::<$ChunkTy>() && mem::size_of::<T>() % mem::size_of::<$ChunkTy>() == 0 { - let x: *mut MaybeUninit<$ChunkTy> = x.cast(); - let y: *mut MaybeUninit<$ChunkTy> = y.cast(); + let x: *mut $ChunkTy = x.cast(); + let y: *mut $ChunkTy = y.cast(); let count = count * (mem::size_of::<T>() / mem::size_of::<$ChunkTy>()); // SAFETY: these are the same bytes that the caller promised were // ok, just typed as `MaybeUninit<ChunkTy>`s instead of as `T`s. // The `if` condition above ensures that we're not violating // alignment requirements, and that the division is exact so // that we don't lose any bytes off the end. - return unsafe { swap_nonoverlapping_simple(x, y, count) }; + return unsafe { swap_nonoverlapping_simple_untyped(x, y, count) }; } }; } @@ -946,7 +908,7 @@ pub const unsafe fn swap_nonoverlapping<T>(x: *mut T, y: *mut T, count: usize) { } // SAFETY: Same preconditions as this function - unsafe { swap_nonoverlapping_simple(x, y, count) } + unsafe { swap_nonoverlapping_simple_untyped(x, y, count) } } /// Same behaviour and safety conditions as [`swap_nonoverlapping`] @@ -955,17 +917,17 @@ pub const unsafe fn swap_nonoverlapping<T>(x: *mut T, y: *mut T, count: usize) { /// `swap_nonoverlapping` tries to use) so no need to manually SIMD it. #[inline] #[rustc_const_unstable(feature = "const_swap", issue = "83163")] -const unsafe fn swap_nonoverlapping_simple<T>(x: *mut T, y: *mut T, count: usize) { +const unsafe fn swap_nonoverlapping_simple_untyped<T>(x: *mut T, y: *mut T, count: usize) { + let x = x.cast::<MaybeUninit<T>>(); + let y = y.cast::<MaybeUninit<T>>(); let mut i = 0; while i < count { - let x: &mut T = - // SAFETY: By precondition, `i` is in-bounds because it's below `n` - unsafe { &mut *x.add(i) }; - let y: &mut T = - // SAFETY: By precondition, `i` is in-bounds because it's below `n` - // and it's distinct from `x` since the ranges are non-overlapping - unsafe { &mut *y.add(i) }; - mem::swap_simple(x, y); + // SAFETY: By precondition, `i` is in-bounds because it's below `n` + let x = unsafe { &mut *x.add(i) }; + // SAFETY: By precondition, `i` is in-bounds because it's below `n` + // and it's distinct from `x` since the ranges are non-overlapping + let y = unsafe { &mut *y.add(i) }; + mem::swap_simple::<MaybeUninit<T>>(x, y); i += 1; } diff --git a/library/core/src/sync/exclusive.rs b/library/core/src/sync/exclusive.rs new file mode 100644 index 00000000000..a7519ab5ab6 --- /dev/null +++ b/library/core/src/sync/exclusive.rs @@ -0,0 +1,173 @@ +//! Defines [`Exclusive`]. + +use core::fmt; +use core::future::Future; +use core::pin::Pin; +use core::task::{Context, Poll}; + +/// `Exclusive` provides only _mutable_ access, also referred to as _exclusive_ +/// access to the underlying value. It provides no _immutable_, or _shared_ +/// access to the underlying value. +/// +/// While this may seem not very useful, it allows `Exclusive` to _unconditionally_ +/// implement [`Sync`]. Indeed, the safety requirements of `Sync` state that for `Exclusive` +/// to be `Sync`, it must be sound to _share_ across threads, that is, it must be sound +/// for `&Exclusive` to cross thread boundaries. By design, a `&Exclusive` has no API +/// whatsoever, making it useless, thus harmless, thus memory safe. +/// +/// Certain constructs like [`Future`]s can only be used with _exclusive_ access, +/// and are often `Send` but not `Sync`, so `Exclusive` can be used as hint to the +/// rust compiler that something is `Sync` in practice. +/// +/// ## Examples +/// Using a non-`Sync` future prevents the wrapping struct from being `Sync` +/// ```compile_fail +/// use core::cell::Cell; +/// +/// async fn other() {} +/// fn assert_sync<T: Sync>(t: T) {} +/// struct State<F> { +/// future: F +/// } +/// +/// assert_sync(State { +/// future: async { +/// let cell = Cell::new(1); +/// let cell_ref = &cell; +/// other().await; +/// let value = cell_ref.get(); +/// } +/// }); +/// ``` +/// +/// `Exclusive` ensures the struct is `Sync` without stripping the future of its +/// functionality. +/// ``` +/// #![feature(exclusive_wrapper)] +/// use core::cell::Cell; +/// use core::sync::Exclusive; +/// +/// async fn other() {} +/// fn assert_sync<T: Sync>(t: T) {} +/// struct State<F> { +/// future: Exclusive<F> +/// } +/// +/// assert_sync(State { +/// future: Exclusive::new(async { +/// let cell = Cell::new(1); +/// let cell_ref = &cell; +/// other().await; +/// let value = cell_ref.get(); +/// }) +/// }); +/// ``` +/// +/// ## Parallels with a mutex +/// In some sense, `Exclusive` can be thought of as a _compile-time_ version of +/// a mutex, as the borrow-checker guarantees that only one `&mut` can exist +/// for any value. This is a parallel with the fact that +/// `&` and `&mut` references together can be thought of as a _compile-time_ +/// version of a read-write lock. +/// +/// +/// [`Sync`]: core::marker::Sync +#[unstable(feature = "exclusive_wrapper", issue = "98407")] +#[doc(alias = "SyncWrapper")] +#[doc(alias = "SyncCell")] +#[doc(alias = "Unique")] +// `Exclusive` can't have `PartialOrd`, `Clone`, etc. impls as they would +// use `&` access to the inner value, violating the `Sync` impl's safety +// requirements. +#[derive(Default)] +#[repr(transparent)] +pub struct Exclusive<T: ?Sized> { + inner: T, +} + +// See `Exclusive`'s docs for justification. +#[unstable(feature = "exclusive_wrapper", issue = "98407")] +unsafe impl<T: ?Sized> Sync for Exclusive<T> {} + +#[unstable(feature = "exclusive_wrapper", issue = "98407")] +impl<T: ?Sized> fmt::Debug for Exclusive<T> { + fn fmt(&self, f: &mut fmt::Formatter<'_>) -> Result<(), fmt::Error> { + f.debug_struct("Exclusive").finish_non_exhaustive() + } +} + +impl<T: Sized> Exclusive<T> { + /// Wrap a value in an `Exclusive` + #[unstable(feature = "exclusive_wrapper", issue = "98407")] + #[must_use] + pub const fn new(t: T) -> Self { + Self { inner: t } + } + + /// Unwrap the value contained in the `Exclusive` + #[unstable(feature = "exclusive_wrapper", issue = "98407")] + #[must_use] + pub const fn into_inner(self) -> T { + self.inner + } +} + +impl<T: ?Sized> Exclusive<T> { + /// Get exclusive access to the underlying value. + #[unstable(feature = "exclusive_wrapper", issue = "98407")] + #[must_use] + pub const fn get_mut(&mut self) -> &mut T { + &mut self.inner + } + + /// Get pinned exclusive access to the underlying value. + /// + /// `Exclusive` is considered to _structurally pin_ the underlying + /// value, which means _unpinned_ `Exclusive`s can produce _unpinned_ + /// access to the underlying value, but _pinned_ `Exclusive`s only + /// produce _pinned_ access to the underlying value. + #[unstable(feature = "exclusive_wrapper", issue = "98407")] + #[must_use] + pub const fn get_pin_mut(self: Pin<&mut Self>) -> Pin<&mut T> { + // SAFETY: `Exclusive` can only produce `&mut T` if itself is unpinned + // `Pin::map_unchecked_mut` is not const, so we do this conversion manually + unsafe { Pin::new_unchecked(&mut self.get_unchecked_mut().inner) } + } + + /// Build a _mutable_ references to an `Exclusive<T>` from + /// a _mutable_ reference to a `T`. This allows you to skip + /// building an `Exclusive` with [`Exclusive::new`]. + #[unstable(feature = "exclusive_wrapper", issue = "98407")] + #[must_use] + pub const fn from_mut(r: &'_ mut T) -> &'_ mut Exclusive<T> { + // SAFETY: repr is ≥ C, so refs have the same layout; and `Exclusive` properties are `&mut`-agnostic + unsafe { &mut *(r as *mut T as *mut Exclusive<T>) } + } + + /// Build a _pinned mutable_ references to an `Exclusive<T>` from + /// a _pinned mutable_ reference to a `T`. This allows you to skip + /// building an `Exclusive` with [`Exclusive::new`]. + #[unstable(feature = "exclusive_wrapper", issue = "98407")] + #[must_use] + pub const fn from_pin_mut(r: Pin<&'_ mut T>) -> Pin<&'_ mut Exclusive<T>> { + // SAFETY: `Exclusive` can only produce `&mut T` if itself is unpinned + // `Pin::map_unchecked_mut` is not const, so we do this conversion manually + unsafe { Pin::new_unchecked(Self::from_mut(r.get_unchecked_mut())) } + } +} + +#[unstable(feature = "exclusive_wrapper", issue = "98407")] +impl<T> From<T> for Exclusive<T> { + fn from(t: T) -> Self { + Self::new(t) + } +} + +#[unstable(feature = "exclusive_wrapper", issue = "98407")] +impl<T: Future + ?Sized> Future for Exclusive<T> { + type Output = T::Output; + + fn poll(self: Pin<&mut Self>, cx: &mut Context<'_>) -> Poll<Self::Output> { + self.get_pin_mut().poll(cx) + } +} diff --git a/library/core/src/sync/mod.rs b/library/core/src/sync/mod.rs index b635bae0a47..4365e4cb250 100644 --- a/library/core/src/sync/mod.rs +++ b/library/core/src/sync/mod.rs @@ -3,3 +3,6 @@ #![stable(feature = "rust1", since = "1.0.0")] pub mod atomic; +mod exclusive; +#[unstable(feature = "exclusive_wrapper", issue = "98407")] +pub use exclusive::Exclusive; diff --git a/library/core/src/tuple.rs b/library/core/src/tuple.rs index ab3763cbc41..b664b0bb866 100644 --- a/library/core/src/tuple.rs +++ b/library/core/src/tuple.rs @@ -107,7 +107,7 @@ macro_rules! tuple_impls { // Otherwise, it hides the docs entirely. macro_rules! maybe_tuple_doc { ($a:ident @ #[$meta:meta] $item:item) => { - #[cfg_attr(not(bootstrap), doc(tuple_variadic))] + #[doc(tuple_variadic)] #[doc = "This trait is implemented for tuples up to twelve items long."] #[$meta] $item diff --git a/library/core/tests/ptr.rs b/library/core/tests/ptr.rs index 187a7db7fcb..bab2b1792f6 100644 --- a/library/core/tests/ptr.rs +++ b/library/core/tests/ptr.rs @@ -96,17 +96,14 @@ fn test_is_null() { let nmi: *mut dyn ToString = null_mut::<isize>(); assert!(nmi.is_null()); - #[cfg(not(bootstrap))] - { - extern "C" { - type Extern; - } - let ec: *const Extern = null::<Extern>(); - assert!(ec.is_null()); - - let em: *mut Extern = null_mut::<Extern>(); - assert!(em.is_null()); + extern "C" { + type Extern; } + let ec: *const Extern = null::<Extern>(); + assert!(ec.is_null()); + + let em: *mut Extern = null_mut::<Extern>(); + assert!(em.is_null()); } #[test] @@ -785,6 +782,31 @@ fn nonnull_tagged_pointer_with_provenance() { } #[test] +fn swap_copy_untyped() { + // We call `{swap,copy}{,_nonoverlapping}` at `bool` type on data that is not a valid bool. + // These should all do untyped copies, so this should work fine. + let mut x = 5u8; + let mut y = 6u8; + + let ptr1 = &mut x as *mut u8 as *mut bool; + let ptr2 = &mut y as *mut u8 as *mut bool; + + unsafe { + ptr::swap(ptr1, ptr2); + ptr::swap_nonoverlapping(ptr1, ptr2, 1); + } + assert_eq!(x, 5); + assert_eq!(y, 6); + + unsafe { + ptr::copy(ptr1, ptr2, 1); + ptr::copy_nonoverlapping(ptr1, ptr2, 1); + } + assert_eq!(x, 5); + assert_eq!(y, 5); +} + +#[test] fn test_const_copy() { const { let ptr1 = &1; diff --git a/library/std/src/lib.rs b/library/std/src/lib.rs index 65b8df42996..298321f41e4 100644 --- a/library/std/src/lib.rs +++ b/library/std/src/lib.rs @@ -210,6 +210,8 @@ #![allow(unused_lifetimes)] // Tell the compiler to link to either panic_abort or panic_unwind #![needs_panic_runtime] +// Ensure that std can be linked against panic_abort despite compiled with `-C panic=unwind` +#![cfg_attr(not(bootstrap), deny(ffi_unwind_calls))] // std may use features in a platform-specific way #![allow(unused_features)] #![cfg_attr(test, feature(internal_output_capture, print_internals, update_panic_count))] @@ -249,7 +251,6 @@ #![feature(needs_panic_runtime)] #![feature(negative_impls)] #![feature(never_type)] -#![cfg_attr(bootstrap, feature(nll))] #![feature(platform_intrinsics)] #![feature(prelude_import)] #![feature(rustc_attrs)] @@ -270,6 +271,7 @@ #![feature(duration_checked_float)] #![feature(duration_constants)] #![feature(exact_size_is_empty)] +#![feature(exclusive_wrapper)] #![feature(extend_one)] #![feature(float_minimum_maximum)] #![feature(hasher_prefixfree_extras)] @@ -584,7 +586,7 @@ mod backtrace_rs; #[stable(feature = "rust1", since = "1.0.0")] #[allow(deprecated, deprecated_in_future)] pub use core::{ - assert_eq, assert_ne, debug_assert, debug_assert_eq, debug_assert_ne, matches, r#try, todo, + assert_eq, assert_ne, debug_assert, debug_assert_eq, debug_assert_ne, matches, todo, r#try, unimplemented, unreachable, write, writeln, }; diff --git a/library/std/src/net/tcp.rs b/library/std/src/net/tcp.rs index 06300035633..69b72a81c5b 100644 --- a/library/std/src/net/tcp.rs +++ b/library/std/src/net/tcp.rs @@ -7,6 +7,7 @@ use crate::io::prelude::*; use crate::fmt; use crate::io::{self, IoSlice, IoSliceMut}; +use crate::iter::FusedIterator; use crate::net::{Shutdown, SocketAddr, ToSocketAddrs}; use crate::sys_common::net as net_imp; use crate::sys_common::{AsInner, FromInner, IntoInner}; @@ -1009,6 +1010,9 @@ impl<'a> Iterator for Incoming<'a> { } } +#[stable(feature = "tcp_listener_incoming_fused_iterator", since = "1.64.0")] +impl FusedIterator for Incoming<'_> {} + #[unstable(feature = "tcplistener_into_incoming", issue = "88339")] impl Iterator for IntoIncoming { type Item = io::Result<TcpStream>; @@ -1017,6 +1021,9 @@ impl Iterator for IntoIncoming { } } +#[unstable(feature = "tcplistener_into_incoming", issue = "88339")] +impl FusedIterator for IntoIncoming {} + impl AsInner<net_imp::TcpListener> for TcpListener { fn as_inner(&self) -> &net_imp::TcpListener { &self.0 diff --git a/library/std/src/os/fd/owned.rs b/library/std/src/os/fd/owned.rs index dd965ddc01e..d661a13edc5 100644 --- a/library/std/src/os/fd/owned.rs +++ b/library/std/src/os/fd/owned.rs @@ -355,3 +355,34 @@ impl From<OwnedFd> for crate::net::UdpSocket { )))) } } + +#[stable(feature = "io_safety", since = "1.63.0")] +/// This impl allows implementing traits that require `AsFd` on Arc. +/// ``` +/// # #[cfg(any(unix, target_os = "wasi"))] mod group_cfg { +/// # #[cfg(target_os = "wasi")] +/// # use std::os::wasi::io::AsFd; +/// # #[cfg(unix)] +/// # use std::os::unix::io::AsFd; +/// use std::net::UdpSocket; +/// use std::sync::Arc; +/// +/// trait MyTrait: AsFd {} +/// impl MyTrait for Arc<UdpSocket> {} +/// impl MyTrait for Box<UdpSocket> {} +/// # } +/// ``` +impl<T: AsFd> AsFd for crate::sync::Arc<T> { + #[inline] + fn as_fd(&self) -> BorrowedFd<'_> { + (**self).as_fd() + } +} + +#[stable(feature = "io_safety", since = "1.63.0")] +impl<T: AsFd> AsFd for Box<T> { + #[inline] + fn as_fd(&self) -> BorrowedFd<'_> { + (**self).as_fd() + } +} diff --git a/library/std/src/os/fd/raw.rs b/library/std/src/os/fd/raw.rs index 47ee88d97fb..345beb1824d 100644 --- a/library/std/src/os/fd/raw.rs +++ b/library/std/src/os/fd/raw.rs @@ -222,3 +222,34 @@ impl<'a> AsRawFd for io::StderrLock<'a> { libc::STDERR_FILENO } } + +/// This impl allows implementing traits that require `AsRawFd` on Arc. +/// ``` +/// # #[cfg(any(unix, target_os = "wasi"))] mod group_cfg { +/// # #[cfg(target_os = "wasi")] +/// # use std::os::wasi::io::AsRawFd; +/// # #[cfg(unix)] +/// # use std::os::unix::io::AsRawFd; +/// use std::net::UdpSocket; +/// use std::sync::Arc; +/// trait MyTrait: AsRawFd { +/// } +/// impl MyTrait for Arc<UdpSocket> {} +/// impl MyTrait for Box<UdpSocket> {} +/// # } +/// ``` +#[stable(feature = "asrawfd_ptrs", since = "1.63.0")] +impl<T: AsRawFd> AsRawFd for crate::sync::Arc<T> { + #[inline] + fn as_raw_fd(&self) -> RawFd { + (**self).as_raw_fd() + } +} + +#[stable(feature = "asrawfd_ptrs", since = "1.63.0")] +impl<T: AsRawFd> AsRawFd for Box<T> { + #[inline] + fn as_raw_fd(&self) -> RawFd { + (**self).as_raw_fd() + } +} diff --git a/library/std/src/primitive_docs.rs b/library/std/src/primitive_docs.rs index 00793f7f920..401c8159988 100644 --- a/library/std/src/primitive_docs.rs +++ b/library/std/src/primitive_docs.rs @@ -996,7 +996,7 @@ impl<T> (T,) {} // Fake impl that's only really used for docs. #[cfg(doc)] #[stable(feature = "rust1", since = "1.0.0")] -#[cfg_attr(not(bootstrap), doc(tuple_variadic))] +#[doc(tuple_variadic)] /// This trait is implemented on arbitrary-length tuples. impl<T: Clone> Clone for (T,) { fn clone(&self) -> Self { @@ -1007,7 +1007,7 @@ impl<T: Clone> Clone for (T,) { // Fake impl that's only really used for docs. #[cfg(doc)] #[stable(feature = "rust1", since = "1.0.0")] -#[cfg_attr(not(bootstrap), doc(tuple_variadic))] +#[doc(tuple_variadic)] /// This trait is implemented on arbitrary-length tuples. impl<T: Copy> Copy for (T,) { // empty diff --git a/library/std/src/sync/mod.rs b/library/std/src/sync/mod.rs index 5fc18fda6a8..7b507a169b3 100644 --- a/library/std/src/sync/mod.rs +++ b/library/std/src/sync/mod.rs @@ -155,6 +155,8 @@ pub use alloc_crate::sync::{Arc, Weak}; #[stable(feature = "rust1", since = "1.0.0")] pub use core::sync::atomic; +#[unstable(feature = "exclusive_wrapper", issue = "98407")] +pub use core::sync::Exclusive; #[stable(feature = "rust1", since = "1.0.0")] pub use self::barrier::{Barrier, BarrierWaitResult}; diff --git a/library/std/src/thread/mod.rs b/library/std/src/thread/mod.rs index 0a6a7cfe976..c70ac8c9806 100644 --- a/library/std/src/thread/mod.rs +++ b/library/std/src/thread/mod.rs @@ -159,6 +159,7 @@ use crate::cell::UnsafeCell; use crate::ffi::{CStr, CString}; use crate::fmt; use crate::io; +use crate::marker::PhantomData; use crate::mem; use crate::num::NonZeroU64; use crate::num::NonZeroUsize; @@ -462,7 +463,7 @@ impl Builder { unsafe fn spawn_unchecked_<'a, 'scope, F, T>( self, f: F, - scope_data: Option<&'scope scoped::ScopeData>, + scope_data: Option<Arc<scoped::ScopeData>>, ) -> io::Result<JoinInner<'scope, T>> where F: FnOnce() -> T, @@ -479,8 +480,11 @@ impl Builder { })); let their_thread = my_thread.clone(); - let my_packet: Arc<Packet<'scope, T>> = - Arc::new(Packet { scope: scope_data, result: UnsafeCell::new(None) }); + let my_packet: Arc<Packet<'scope, T>> = Arc::new(Packet { + scope: scope_data, + result: UnsafeCell::new(None), + _marker: PhantomData, + }); let their_packet = my_packet.clone(); let output_capture = crate::io::set_output_capture(None); @@ -507,7 +511,7 @@ impl Builder { unsafe { *their_packet.result.get() = Some(try_result) }; }; - if let Some(scope_data) = scope_data { + if let Some(scope_data) = &my_packet.scope { scope_data.increment_num_running_threads(); } @@ -1298,8 +1302,9 @@ pub type Result<T> = crate::result::Result<T, Box<dyn Any + Send + 'static>>; // An Arc to the packet is stored into a `JoinInner` which in turns is placed // in `JoinHandle`. struct Packet<'scope, T> { - scope: Option<&'scope scoped::ScopeData>, + scope: Option<Arc<scoped::ScopeData>>, result: UnsafeCell<Option<Result<T>>>, + _marker: PhantomData<Option<&'scope scoped::ScopeData>>, } // Due to the usage of `UnsafeCell` we need to manually implement Sync. @@ -1330,7 +1335,7 @@ impl<'scope, T> Drop for Packet<'scope, T> { rtabort!("thread result panicked on drop"); } // Book-keeping so the scope knows when it's done. - if let Some(scope) = self.scope { + if let Some(scope) = &self.scope { // Now that there will be no more user code running on this thread // that can use 'scope, mark the thread as 'finished'. // It's important we only do this after the `result` has been dropped, diff --git a/library/std/src/thread/scoped.rs b/library/std/src/thread/scoped.rs index a387a09dc8b..e6dbf35bd02 100644 --- a/library/std/src/thread/scoped.rs +++ b/library/std/src/thread/scoped.rs @@ -11,7 +11,7 @@ use crate::sync::Arc; /// See [`scope`] for details. #[stable(feature = "scoped_threads", since = "1.63.0")] pub struct Scope<'scope, 'env: 'scope> { - data: ScopeData, + data: Arc<ScopeData>, /// Invariance over 'scope, to make sure 'scope cannot shrink, /// which is necessary for soundness. /// @@ -130,12 +130,14 @@ pub fn scope<'env, F, T>(f: F) -> T where F: for<'scope> FnOnce(&'scope Scope<'scope, 'env>) -> T, { + // We put the `ScopeData` into an `Arc` so that other threads can finish their + // `decrement_num_running_threads` even after this function returns. let scope = Scope { - data: ScopeData { + data: Arc::new(ScopeData { num_running_threads: AtomicUsize::new(0), main_thread: current(), a_thread_panicked: AtomicBool::new(false), - }, + }), env: PhantomData, scope: PhantomData, }; @@ -250,7 +252,7 @@ impl Builder { F: FnOnce() -> T + Send + 'scope, T: Send + 'scope, { - Ok(ScopedJoinHandle(unsafe { self.spawn_unchecked_(f, Some(&scope.data)) }?)) + Ok(ScopedJoinHandle(unsafe { self.spawn_unchecked_(f, Some(scope.data.clone())) }?)) } } diff --git a/library/unwind/src/lib.rs b/library/unwind/src/lib.rs index 52d737de7ae..4a6ba6e10c3 100644 --- a/library/unwind/src/lib.rs +++ b/library/unwind/src/lib.rs @@ -1,7 +1,6 @@ #![no_std] #![unstable(feature = "panic_unwind", issue = "32837")] #![feature(link_cfg)] -#![cfg_attr(bootstrap, feature(native_link_modifiers_bundle))] #![feature(staged_api)] #![feature(c_unwind)] #![feature(cfg_target_abi)] diff --git a/src/bootstrap/Cargo.lock b/src/bootstrap/Cargo.lock index 6fcbd7a2156..664ffa1ddd2 100644 --- a/src/bootstrap/Cargo.lock +++ b/src/bootstrap/Cargo.lock @@ -47,6 +47,7 @@ version = "0.0.0" dependencies = [ "cc", "cmake", + "fd-lock", "filetime", "getopts", "hex", @@ -202,6 +203,38 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "e78d4f1cc4ae33bbfc157ed5d5a5ef3bc29227303d595861deb238fcec4e9457" [[package]] +name = "errno" +version = "0.2.8" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f639046355ee4f37944e44f60642c6f3a7efa3cf6b78c78a0d989a8ce6c396a1" +dependencies = [ + "errno-dragonfly", + "libc", + "winapi", +] + +[[package]] +name = "errno-dragonfly" +version = "0.1.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "aa68f1b12764fab894d2755d2518754e71b4fd80ecfb822714a1206c2aab39bf" +dependencies = [ + "cc", + "libc", +] + +[[package]] +name = "fd-lock" +version = "3.0.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e11dcc7e4d79a8c89b9ab4c6f5c30b1fc4a83c420792da3542fd31179ed5f517" +dependencies = [ + "cfg-if", + "rustix", + "windows-sys", +] + +[[package]] name = "filetime" version = "0.2.16" source = "registry+https://github.com/rust-lang/crates.io-index" @@ -285,6 +318,12 @@ dependencies = [ ] [[package]] +name = "io-lifetimes" +version = "0.7.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "24c3f4eff5495aee4c0399d7b6a0dc2b6e81be84242ffbfcf253ebacccc1d0cb" + +[[package]] name = "itoa" version = "1.0.2" source = "registry+https://github.com/rust-lang/crates.io-index" @@ -303,6 +342,12 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "349d5a591cd28b49e1d1037471617a32ddcda5731b99419008085f72d5a53836" [[package]] +name = "linux-raw-sys" +version = "0.0.46" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d4d2456c373231a208ad294c33dc5bff30051eafd954cd4caae83a712b12854d" + +[[package]] name = "log" version = "0.4.17" source = "registry+https://github.com/rust-lang/crates.io-index" @@ -474,6 +519,20 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "49b3de9ec5dc0a3417da371aab17d729997c15010e7fd24ff707773a33bddb64" [[package]] +name = "rustix" +version = "0.35.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ef258c11e17f5c01979a10543a30a4e12faef6aab217a74266e747eefa3aed88" +dependencies = [ + "bitflags", + "errno", + "io-lifetimes", + "libc", + "linux-raw-sys", + "windows-sys", +] + +[[package]] name = "ryu" version = "1.0.10" source = "registry+https://github.com/rust-lang/crates.io-index" @@ -658,6 +717,49 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "712e227841d057c1ee1cd2fb22fa7e5a5461ae8e48fa2ca79ec42cfc1931183f" [[package]] +name = "windows-sys" +version = "0.36.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ea04155a16a59f9eab786fe12a4a450e75cdb175f9e0d80da1e17db09f55b8d2" +dependencies = [ + "windows_aarch64_msvc", + "windows_i686_gnu", + "windows_i686_msvc", + "windows_x86_64_gnu", + "windows_x86_64_msvc", +] + +[[package]] +name = "windows_aarch64_msvc" +version = "0.36.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9bb8c3fd39ade2d67e9874ac4f3db21f0d710bee00fe7cab16949ec184eeaa47" + +[[package]] +name = "windows_i686_gnu" +version = "0.36.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "180e6ccf01daf4c426b846dfc66db1fc518f074baa793aa7d9b9aaeffad6a3b6" + +[[package]] +name = "windows_i686_msvc" +version = "0.36.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e2e7917148b2812d1eeafaeb22a97e4813dfa60a3f8f78ebe204bcc88f12f024" + +[[package]] +name = "windows_x86_64_gnu" +version = "0.36.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4dcd171b8776c41b97521e5da127a2d86ad280114807d0b2ab1e462bc764d9e1" + +[[package]] +name = "windows_x86_64_msvc" +version = "0.36.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c811ca4a8c853ef420abd8592ba53ddbbac90410fab6903b3e79972a631f7680" + +[[package]] name = "xattr" version = "0.2.3" source = "registry+https://github.com/rust-lang/crates.io-index" diff --git a/src/bootstrap/Cargo.toml b/src/bootstrap/Cargo.toml index b9bd3d0cf78..84f6aaf99c1 100644 --- a/src/bootstrap/Cargo.toml +++ b/src/bootstrap/Cargo.toml @@ -36,6 +36,7 @@ test = false [dependencies] cmake = "0.1.38" +fd-lock = "3.0.6" filetime = "0.2" num_cpus = "1.0" getopts = "0.2.19" diff --git a/src/bootstrap/bin/main.rs b/src/bootstrap/bin/main.rs index 9c41ab69c8b..9b4861ccd95 100644 --- a/src/bootstrap/bin/main.rs +++ b/src/bootstrap/bin/main.rs @@ -7,12 +7,28 @@ use std::env; -use bootstrap::{Build, Config, Subcommand, VERSION}; +use bootstrap::{t, Build, Config, Subcommand, VERSION}; fn main() { let args = env::args().skip(1).collect::<Vec<_>>(); let config = Config::parse(&args); + let mut build_lock; + let _build_lock_guard; + if cfg!(any(unix, windows)) { + build_lock = fd_lock::RwLock::new(t!(std::fs::File::create(config.out.join("lock")))); + _build_lock_guard = match build_lock.try_write() { + Ok(lock) => lock, + err => { + println!("warning: build directory locked, waiting for lock"); + drop(err); + t!(build_lock.write()) + } + }; + } else { + println!("warning: file locking not supported for target, not locking build directory"); + } + // check_version warnings are not printed during setup let changelog_suggestion = if matches!(config.cmd, Subcommand::Setup { .. }) { None } else { check_version(&config) }; diff --git a/src/bootstrap/bin/rustdoc.rs b/src/bootstrap/bin/rustdoc.rs index 5f85fc5aa59..87c1d22e771 100644 --- a/src/bootstrap/bin/rustdoc.rs +++ b/src/bootstrap/bin/rustdoc.rs @@ -31,9 +31,7 @@ fn main() { let mut cmd = Command::new(rustdoc); - // cfg(bootstrap) - // NOTE: the `--test` special-casing can be removed when https://github.com/rust-lang/cargo/pull/10594 lands on beta. - if target.is_some() || args.iter().any(|x| x == "--test") { + if target.is_some() { // The stage0 compiler has a special sysroot distinct from what we // actually downloaded, so we just always pass the `--sysroot` option, // unless one is already set. diff --git a/src/bootstrap/bootstrap.py b/src/bootstrap/bootstrap.py index 8000e60f64d..9301c5a2ff3 100644 --- a/src/bootstrap/bootstrap.py +++ b/src/bootstrap/bootstrap.py @@ -15,44 +15,6 @@ import tempfile from time import time, sleep -# Acquire a lock on the build directory to make sure that -# we don't cause a race condition while building -# Lock is created in `build_dir/lock.db` -def acquire_lock(build_dir): - try: - import sqlite3 - - path = os.path.join(build_dir, "lock.db") - try: - con = sqlite3.Connection(path, timeout=0) - curs = con.cursor() - curs.execute("BEGIN EXCLUSIVE") - # The lock is released when the cursor is dropped - return curs - # If the database is busy then lock has already been acquired - # so we wait for the lock. - # We retry every quarter second so that execution is passed back to python - # so that it can handle signals - except sqlite3.OperationalError: - del con - del curs - print("Waiting for lock on build directory") - con = sqlite3.Connection(path, timeout=0.25) - curs = con.cursor() - while True: - try: - curs.execute("BEGIN EXCLUSIVE") - break - except sqlite3.OperationalError: - pass - sleep(0.25) - return curs - except ImportError: - print("warning: sqlite3 not available in python, skipping build directory lock") - print("please file an issue on rust-lang/rust") - print("this is not a problem for non-concurrent x.py invocations") - return None - def support_xz(): try: with tempfile.NamedTemporaryFile(delete=False) as temp_file: @@ -190,6 +152,10 @@ def run(args, verbose=False, exception=False, is_bootstrap=False, **kwargs): if verbose: print("running: " + ' '.join(args)) sys.stdout.flush() + # Ensure that the .exe is used on Windows just in case a Linux ELF has been + # compiled in the same directory. + if os.name == 'nt' and not args[0].endswith('.exe'): + args[0] += '.exe' # Use Popen here instead of call() as it apparently allows powershell on # Windows to not lock up waiting for input presumably. ret = subprocess.Popen(args, **kwargs) @@ -866,6 +832,7 @@ def bootstrap(help_triggered): parser = argparse.ArgumentParser(description='Build rust') parser.add_argument('--config') + parser.add_argument('--build-dir') parser.add_argument('--build') parser.add_argument('--color', choices=['always', 'never', 'auto']) parser.add_argument('--clean', action='store_true') @@ -915,7 +882,7 @@ def bootstrap(help_triggered): build.check_vendored_status() - build_dir = build.get_toml('build-dir', 'build') or 'build' + build_dir = args.build_dir or build.get_toml('build-dir', 'build') or 'build' build.build_dir = os.path.abspath(build_dir) with open(os.path.join(build.rust_root, "src", "stage0.json")) as f: @@ -927,11 +894,8 @@ def bootstrap(help_triggered): build.build = args.build or build.build_triple() - # Acquire the lock before doing any build actions - # The lock is released when `lock` is dropped if not os.path.exists(build.build_dir): os.makedirs(build.build_dir) - lock = acquire_lock(build.build_dir) # Fetch/build the bootstrap build.download_toolchain() diff --git a/src/bootstrap/builder.rs b/src/bootstrap/builder.rs index 62b5416cee8..dc6a0f6f241 100644 --- a/src/bootstrap/builder.rs +++ b/src/bootstrap/builder.rs @@ -13,7 +13,6 @@ use std::process::{Command, Stdio}; use std::time::{Duration, Instant}; use crate::cache::{Cache, Interned, INTERNER}; -use crate::compile; use crate::config::{SplitDebuginfo, TargetSelection}; use crate::dist; use crate::doc; @@ -26,6 +25,7 @@ use crate::tool::{self, SourceType}; use crate::util::{self, add_dylib_path, add_link_lib_path, exe, libdir, output, t}; use crate::EXTRA_CHECK_CFGS; use crate::{check, Config}; +use crate::{compile, Crate}; use crate::{Build, CLang, DocTests, GitRepo, Mode}; pub use crate::Compiler; @@ -304,9 +304,7 @@ impl StepDescription { if paths.is_empty() || builder.config.include_default_paths { for (desc, should_run) in v.iter().zip(&should_runs) { if desc.default && should_run.is_really_default() { - for pathset in &should_run.paths { - desc.maybe_run(builder, vec![pathset.clone()]); - } + desc.maybe_run(builder, should_run.paths.iter().cloned().collect()); } } } @@ -424,8 +422,16 @@ impl<'a> ShouldRun<'a> { /// any of its (local) dependencies. /// /// `make_run` will be called a single time with all matching command-line paths. - pub fn krate(mut self, name: &str) -> Self { - for krate in self.builder.in_tree_crates(name, None) { + pub fn crate_or_deps(self, name: &str) -> Self { + let crates = self.builder.in_tree_crates(name, None); + self.crates(crates) + } + + /// Indicates it should run if the command-line selects any of the given crates. + /// + /// `make_run` will be called a single time with all matching command-line paths. + pub(crate) fn crates(mut self, crates: Vec<&Crate>) -> Self { + for krate in crates { let path = krate.local_path(self.builder); self.paths.insert(PathSet::one(path, self.kind)); } @@ -581,6 +587,7 @@ impl<'a> Builder<'a> { match kind { Kind::Build => describe!( compile::Std, + compile::Rustc, compile::Assemble, compile::CodegenBackend, compile::StartupObjects, @@ -694,6 +701,7 @@ impl<'a> Builder<'a> { doc::RustcBook, doc::CargoBook, doc::Clippy, + doc::Miri, doc::EmbeddedBook, doc::EditionGuide, ), @@ -1760,7 +1768,8 @@ impl<'a> Builder<'a> { let needs_unstable_opts = target.contains("linux") || target.contains("windows") || target.contains("bsd") - || target.contains("dragonfly"); + || target.contains("dragonfly") + || target.contains("illumos"); if needs_unstable_opts { rustflags.arg("-Zunstable-options"); diff --git a/src/bootstrap/builder/tests.rs b/src/bootstrap/builder/tests.rs index 70cb0de7cce..c084e77d3a9 100644 --- a/src/bootstrap/builder/tests.rs +++ b/src/bootstrap/builder/tests.rs @@ -57,6 +57,24 @@ fn check_cli<const N: usize>(paths: [&str; N]) { ); } +macro_rules! std { + ($host:ident => $target:ident, stage = $stage:literal) => { + compile::Std::new( + Compiler { host: TargetSelection::from_user(stringify!($host)), stage: $stage }, + TargetSelection::from_user(stringify!($target)), + ) + }; +} + +macro_rules! rustc { + ($host:ident => $target:ident, stage = $stage:literal) => { + compile::Rustc::new( + Compiler { host: TargetSelection::from_user(stringify!($host)), stage: $stage }, + TargetSelection::from_user(stringify!($target)), + ) + }; +} + #[test] fn test_valid() { // make sure multi suite paths are accepted @@ -117,6 +135,17 @@ fn test_exclude_kind() { assert!(run_build(&[path], config).contains::<tool::CargoTest>()); } +/// Ensure that if someone passes both a single crate and `library`, all library crates get built. +#[test] +fn alias_and_path_for_library() { + let mut cache = + run_build(&["library".into(), "core".into()], configure("build", &["A"], &["A"])); + assert_eq!( + first(cache.all::<compile::Std>()), + &[std!(A => A, stage = 0), std!(A => A, stage = 1)] + ); +} + mod defaults { use super::{configure, first, run_build}; use crate::builder::*; @@ -130,10 +159,7 @@ mod defaults { let a = TargetSelection::from_user("A"); assert_eq!( first(cache.all::<compile::Std>()), - &[ - compile::Std { compiler: Compiler { host: a, stage: 0 }, target: a }, - compile::Std { compiler: Compiler { host: a, stage: 1 }, target: a }, - ] + &[std!(A => A, stage = 0), std!(A => A, stage = 1),] ); assert!(!cache.all::<compile::Assemble>().is_empty()); // Make sure rustdoc is only built once. @@ -143,10 +169,7 @@ mod defaults { // - this is the compiler it's _linked_ to, not built with. &[tool::Rustdoc { compiler: Compiler { host: a, stage: 1 } }], ); - assert_eq!( - first(cache.all::<compile::Rustc>()), - &[compile::Rustc { compiler: Compiler { host: a, stage: 0 }, target: a },] - ); + assert_eq!(first(cache.all::<compile::Rustc>()), &[rustc!(A => A, stage = 0)],); } #[test] @@ -155,10 +178,7 @@ mod defaults { let mut cache = run_build(&[], config); let a = TargetSelection::from_user("A"); - assert_eq!( - first(cache.all::<compile::Std>()), - &[compile::Std { compiler: Compiler { host: a, stage: 0 }, target: a },] - ); + assert_eq!(first(cache.all::<compile::Std>()), &[std!(A => A, stage = 0)]); assert!(!cache.all::<compile::Assemble>().is_empty()); assert_eq!( first(cache.all::<tool::Rustdoc>()), @@ -185,10 +205,10 @@ mod defaults { assert_eq!( first(cache.all::<compile::Std>()), &[ - compile::Std { compiler: Compiler { host: a, stage: 0 }, target: a }, - compile::Std { compiler: Compiler { host: a, stage: 1 }, target: a }, - compile::Std { compiler: Compiler { host: a, stage: 0 }, target: b }, - compile::Std { compiler: Compiler { host: a, stage: 1 }, target: b }, + std!(A => A, stage = 0), + std!(A => A, stage = 1), + std!(A => B, stage = 0), + std!(A => B, stage = 1), ] ); assert_eq!( @@ -208,10 +228,7 @@ mod defaults { ); assert_eq!( first(cache.all::<compile::Rustc>()), - &[ - compile::Rustc { compiler: Compiler { host: a, stage: 0 }, target: a }, - compile::Rustc { compiler: Compiler { host: a, stage: 0 }, target: b }, - ] + &[rustc!(A => A, stage = 0), rustc!(A => B, stage = 0),] ); } @@ -334,11 +351,11 @@ mod dist { assert_eq!( first(cache.all::<compile::Std>()), &[ - compile::Std { compiler: Compiler { host: a, stage: 0 }, target: a }, - compile::Std { compiler: Compiler { host: a, stage: 1 }, target: a }, - compile::Std { compiler: Compiler { host: a, stage: 2 }, target: a }, - compile::Std { compiler: Compiler { host: a, stage: 1 }, target: b }, - compile::Std { compiler: Compiler { host: a, stage: 2 }, target: b }, + std!(A => A, stage = 0), + std!(A => A, stage = 1), + std!(A => A, stage = 2), + std!(A => B, stage = 1), + std!(A => B, stage = 2), ], ); assert_eq!(first(cache.all::<dist::Src>()), &[dist::Src]); @@ -346,7 +363,6 @@ mod dist { #[test] fn dist_only_cross_host() { - let a = TargetSelection::from_user("A"); let b = TargetSelection::from_user("B"); let mut config = configure(&["A", "B"], &["A", "B"]); config.docs = false; @@ -360,10 +376,7 @@ mod dist { ); assert_eq!( first(cache.all::<compile::Rustc>()), - &[ - compile::Rustc { compiler: Compiler { host: a, stage: 0 }, target: a }, - compile::Rustc { compiler: Compiler { host: a, stage: 1 }, target: b }, - ] + &[rustc!(A => A, stage = 0), rustc!(A => B, stage = 1),] ); } @@ -450,11 +463,11 @@ mod dist { assert_eq!( first(cache.all::<compile::Std>()), &[ - compile::Std { compiler: Compiler { host: a, stage: 0 }, target: a }, - compile::Std { compiler: Compiler { host: a, stage: 1 }, target: a }, - compile::Std { compiler: Compiler { host: a, stage: 2 }, target: a }, - compile::Std { compiler: Compiler { host: a, stage: 1 }, target: b }, - compile::Std { compiler: Compiler { host: a, stage: 2 }, target: b }, + std!(A => A, stage = 0), + std!(A => A, stage = 1), + std!(A => A, stage = 2), + std!(A => B, stage = 1), + std!(A => B, stage = 2), ] ); assert_eq!( @@ -474,33 +487,29 @@ mod dist { let mut builder = Builder::new(&build); builder.run_step_descriptions( &Builder::get_step_descriptions(Kind::Build), - &["compiler/rustc".into(), "library/std".into()], + &["compiler/rustc".into(), "library".into()], ); - let a = TargetSelection::from_user("A"); - let b = TargetSelection::from_user("B"); - let c = TargetSelection::from_user("C"); - assert_eq!( first(builder.cache.all::<compile::Std>()), &[ - compile::Std { compiler: Compiler { host: a, stage: 0 }, target: a }, - compile::Std { compiler: Compiler { host: a, stage: 1 }, target: a }, - compile::Std { compiler: Compiler { host: a, stage: 2 }, target: a }, - compile::Std { compiler: Compiler { host: a, stage: 1 }, target: b }, - compile::Std { compiler: Compiler { host: a, stage: 2 }, target: b }, - compile::Std { compiler: Compiler { host: a, stage: 2 }, target: c }, + std!(A => A, stage = 0), + std!(A => A, stage = 1), + std!(A => A, stage = 2), + std!(A => B, stage = 1), + std!(A => B, stage = 2), + std!(A => C, stage = 2), ] ); - assert!(!builder.cache.all::<compile::Assemble>().is_empty()); + assert_eq!(builder.cache.all::<compile::Assemble>().len(), 5); assert_eq!( first(builder.cache.all::<compile::Rustc>()), &[ - compile::Rustc { compiler: Compiler { host: a, stage: 0 }, target: a }, - compile::Rustc { compiler: Compiler { host: a, stage: 1 }, target: a }, - compile::Rustc { compiler: Compiler { host: a, stage: 2 }, target: a }, - compile::Rustc { compiler: Compiler { host: a, stage: 1 }, target: b }, - compile::Rustc { compiler: Compiler { host: a, stage: 2 }, target: b }, + rustc!(A => A, stage = 0), + rustc!(A => A, stage = 1), + rustc!(A => A, stage = 2), + rustc!(A => B, stage = 1), + rustc!(A => B, stage = 2), ] ); } @@ -513,15 +522,10 @@ mod dist { builder.run_step_descriptions(&Builder::get_step_descriptions(Kind::Build), &[]); let a = TargetSelection::from_user("A"); - let c = TargetSelection::from_user("C"); assert_eq!( first(builder.cache.all::<compile::Std>()), - &[ - compile::Std { compiler: Compiler { host: a, stage: 0 }, target: a }, - compile::Std { compiler: Compiler { host: a, stage: 1 }, target: a }, - compile::Std { compiler: Compiler { host: a, stage: 2 }, target: c }, - ] + &[std!(A => A, stage = 0), std!(A => A, stage = 1), std!(A => C, stage = 2),] ); assert_eq!( first(builder.cache.all::<compile::Assemble>()), @@ -533,10 +537,7 @@ mod dist { ); assert_eq!( first(builder.cache.all::<compile::Rustc>()), - &[ - compile::Rustc { compiler: Compiler { host: a, stage: 0 }, target: a }, - compile::Rustc { compiler: Compiler { host: a, stage: 1 }, target: a }, - ] + &[rustc!(A => A, stage = 0), rustc!(A => A, stage = 1),] ); } diff --git a/src/bootstrap/cache.rs b/src/bootstrap/cache.rs index 97f0bfdc484..be5c9bb0788 100644 --- a/src/bootstrap/cache.rs +++ b/src/bootstrap/cache.rs @@ -4,13 +4,12 @@ use std::cell::RefCell; use std::cmp::{Ord, Ordering, PartialOrd}; use std::collections::HashMap; use std::convert::AsRef; -use std::ffi::OsStr; use std::fmt; use std::hash::{Hash, Hasher}; use std::marker::PhantomData; use std::mem; use std::ops::Deref; -use std::path::{Path, PathBuf}; +use std::path::PathBuf; use std::sync::Mutex; // FIXME: replace with std::lazy after it gets stabilized and reaches beta @@ -20,15 +19,9 @@ use crate::builder::Step; pub struct Interned<T>(usize, PhantomData<*const T>); -impl Default for Interned<String> { +impl<T: Internable + Default> Default for Interned<T> { fn default() -> Self { - INTERNER.intern_string(String::default()) - } -} - -impl Default for Interned<PathBuf> { - fn default() -> Self { - INTERNER.intern_path(PathBuf::default()) + T::default().intern() } } @@ -77,87 +70,48 @@ impl fmt::Display for Interned<String> { } } -impl fmt::Debug for Interned<String> { +impl<T, U: ?Sized + fmt::Debug> fmt::Debug for Interned<T> +where + Self: Deref<Target = U>, +{ fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { - let s: &str = &*self; - f.write_fmt(format_args!("{:?}", s)) - } -} -impl fmt::Debug for Interned<PathBuf> { - fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { - let s: &Path = &*self; + let s: &U = &*self; f.write_fmt(format_args!("{:?}", s)) } } -impl Hash for Interned<String> { +impl<T: Internable + Hash> Hash for Interned<T> { fn hash<H: Hasher>(&self, state: &mut H) { - let l = INTERNER.strs.lock().unwrap(); + let l = T::intern_cache().lock().unwrap(); l.get(*self).hash(state) } } -impl Hash for Interned<PathBuf> { - fn hash<H: Hasher>(&self, state: &mut H) { - let l = INTERNER.paths.lock().unwrap(); - l.get(*self).hash(state) +impl<T: Internable + Deref> Deref for Interned<T> { + type Target = T::Target; + fn deref(&self) -> &'static Self::Target { + let l = T::intern_cache().lock().unwrap(); + unsafe { mem::transmute::<&Self::Target, &'static Self::Target>(l.get(*self)) } } } -impl Deref for Interned<String> { - type Target = str; - fn deref(&self) -> &'static str { - let l = INTERNER.strs.lock().unwrap(); - unsafe { mem::transmute::<&str, &'static str>(l.get(*self)) } +impl<T: Internable + AsRef<U>, U: ?Sized> AsRef<U> for Interned<T> { + fn as_ref(&self) -> &'static U { + let l = T::intern_cache().lock().unwrap(); + unsafe { mem::transmute::<&U, &'static U>(l.get(*self).as_ref()) } } } -impl Deref for Interned<PathBuf> { - type Target = Path; - fn deref(&self) -> &'static Path { - let l = INTERNER.paths.lock().unwrap(); - unsafe { mem::transmute::<&Path, &'static Path>(l.get(*self)) } - } -} - -impl AsRef<Path> for Interned<PathBuf> { - fn as_ref(&self) -> &'static Path { - let l = INTERNER.paths.lock().unwrap(); - unsafe { mem::transmute::<&Path, &'static Path>(l.get(*self)) } - } -} - -impl AsRef<Path> for Interned<String> { - fn as_ref(&self) -> &'static Path { - let l = INTERNER.strs.lock().unwrap(); - unsafe { mem::transmute::<&Path, &'static Path>(l.get(*self).as_ref()) } - } -} - -impl AsRef<OsStr> for Interned<PathBuf> { - fn as_ref(&self) -> &'static OsStr { - let l = INTERNER.paths.lock().unwrap(); - unsafe { mem::transmute::<&OsStr, &'static OsStr>(l.get(*self).as_ref()) } - } -} - -impl AsRef<OsStr> for Interned<String> { - fn as_ref(&self) -> &'static OsStr { - let l = INTERNER.strs.lock().unwrap(); - unsafe { mem::transmute::<&OsStr, &'static OsStr>(l.get(*self).as_ref()) } - } -} - -impl PartialOrd<Interned<String>> for Interned<String> { +impl<T: Internable + PartialOrd> PartialOrd for Interned<T> { fn partial_cmp(&self, other: &Self) -> Option<Ordering> { - let l = INTERNER.strs.lock().unwrap(); + let l = T::intern_cache().lock().unwrap(); l.get(*self).partial_cmp(l.get(*other)) } } -impl Ord for Interned<String> { +impl<T: Internable + Ord> Ord for Interned<T> { fn cmp(&self, other: &Self) -> Ordering { - let l = INTERNER.strs.lock().unwrap(); + let l = T::intern_cache().lock().unwrap(); l.get(*self).cmp(l.get(*other)) } } @@ -208,6 +162,33 @@ impl<T: Hash + Clone + Eq> TyIntern<T> { pub struct Interner { strs: Mutex<TyIntern<String>>, paths: Mutex<TyIntern<PathBuf>>, + lists: Mutex<TyIntern<Vec<String>>>, +} + +trait Internable: Clone + Eq + Hash + 'static { + fn intern_cache() -> &'static Mutex<TyIntern<Self>>; + + fn intern(self) -> Interned<Self> { + Self::intern_cache().lock().unwrap().intern(self) + } +} + +impl Internable for String { + fn intern_cache() -> &'static Mutex<TyIntern<Self>> { + &INTERNER.strs + } +} + +impl Internable for PathBuf { + fn intern_cache() -> &'static Mutex<TyIntern<Self>> { + &INTERNER.paths + } +} + +impl Internable for Vec<String> { + fn intern_cache() -> &'static Mutex<TyIntern<Self>> { + &INTERNER.lists + } } impl Interner { @@ -221,6 +202,10 @@ impl Interner { pub fn intern_path(&self, s: PathBuf) -> Interned<PathBuf> { self.paths.lock().unwrap().intern(s) } + + pub fn intern_list(&self, v: Vec<String>) -> Interned<Vec<String>> { + self.lists.lock().unwrap().intern(v) + } } pub static INTERNER: Lazy<Interner> = Lazy::new(Interner::default); diff --git a/src/bootstrap/check.rs b/src/bootstrap/check.rs index 731ebc41bb9..4985b054678 100644 --- a/src/bootstrap/check.rs +++ b/src/bootstrap/check.rs @@ -184,8 +184,8 @@ impl Step for Rustc { // the sysroot for the compiler to find. Otherwise, we're going to // fail when building crates that need to generate code (e.g., build // scripts and their dependencies). - builder.ensure(crate::compile::Std { target: compiler.host, compiler }); - builder.ensure(crate::compile::Std { target, compiler }); + builder.ensure(crate::compile::Std::new(compiler, compiler.host)); + builder.ensure(crate::compile::Std::new(compiler, target)); } else { builder.ensure(Std { target }); } diff --git a/src/bootstrap/compile.rs b/src/bootstrap/compile.rs index b4807d1ab3a..399be26d5ac 100644 --- a/src/bootstrap/compile.rs +++ b/src/bootstrap/compile.rs @@ -29,10 +29,31 @@ use crate::util::{exe, is_debug_info, is_dylib, output, symlink_dir, t, up_to_da use crate::LLVM_TOOLS; use crate::{CLang, Compiler, DependencyType, GitRepo, Mode}; -#[derive(Debug, PartialOrd, Ord, Copy, Clone, PartialEq, Eq, Hash)] +#[derive(Debug, Copy, Clone, PartialEq, Eq, PartialOrd, Ord, Hash)] pub struct Std { pub target: TargetSelection, pub compiler: Compiler, + /// Whether to build only a subset of crates in the standard library. + /// + /// This shouldn't be used from other steps; see the comment on [`Rustc`]. + crates: Interned<Vec<String>>, +} + +impl Std { + pub fn new(compiler: Compiler, target: TargetSelection) -> Self { + Self { target, compiler, crates: Default::default() } + } +} + +/// Return a `-p=x -p=y` string suitable for passing to a cargo invocation. +fn build_crates_in_set(run: &RunConfig<'_>) -> Interned<Vec<String>> { + let mut crates = Vec::new(); + for krate in &run.paths { + let path = krate.assert_single_path(); + let crate_name = run.builder.crate_paths[&path.path]; + crates.push(format!("-p={crate_name}")); + } + INTERNER.intern_list(crates) } impl Step for Std { @@ -43,15 +64,22 @@ impl Step for Std { // When downloading stage1, the standard library has already been copied to the sysroot, so // there's no need to rebuild it. let builder = run.builder; - run.all_krates("test") + run.crate_or_deps("test") .path("library") .lazy_default_condition(Box::new(|| !builder.download_rustc())) } fn make_run(run: RunConfig<'_>) { + // Normally, people will pass *just* library if they pass it. + // But it's possible (although strange) to pass something like `library std core`. + // Build all crates anyway, as if they hadn't passed the other args. + let has_library = + run.paths.iter().any(|set| set.assert_single_path().path.ends_with("library")); + let crates = if has_library { Default::default() } else { build_crates_in_set(&run) }; run.builder.ensure(Std { compiler: run.builder.compiler(run.builder.top_stage, run.build_triple()), target: run.target, + crates, }); } @@ -86,7 +114,7 @@ impl Step for Std { let compiler_to_use = builder.compiler_for(compiler.stage, compiler.host, target); if compiler_to_use != compiler { - builder.ensure(Std { compiler: compiler_to_use, target }); + builder.ensure(Std::new(compiler_to_use, target)); builder.info(&format!("Uplifting stage1 std ({} -> {})", compiler_to_use.host, target)); // Even if we're not building std this stage, the new sysroot must @@ -115,7 +143,7 @@ impl Step for Std { run_cargo( builder, cargo, - vec![], + self.crates.to_vec(), &libstd_stamp(builder, compiler, target), target_deps, false, @@ -524,6 +552,18 @@ impl Step for StartupObjects { pub struct Rustc { pub target: TargetSelection, pub compiler: Compiler, + /// Whether to build a subset of crates, rather than the whole compiler. + /// + /// This should only be requested by the user, not used within rustbuild itself. + /// Using it within rustbuild can lead to confusing situation where lints are replayed + /// in two different steps. + crates: Interned<Vec<String>>, +} + +impl Rustc { + pub fn new(compiler: Compiler, target: TargetSelection) -> Self { + Self { target, compiler, crates: Default::default() } + } } impl Step for Rustc { @@ -532,13 +572,22 @@ impl Step for Rustc { const DEFAULT: bool = false; fn should_run(run: ShouldRun<'_>) -> ShouldRun<'_> { - run.never() + let mut crates = run.builder.in_tree_crates("rustc-main", None); + for (i, krate) in crates.iter().enumerate() { + if krate.name == "rustc-main" { + crates.swap_remove(i); + break; + } + } + run.crates(crates) } fn make_run(run: RunConfig<'_>) { + let crates = build_crates_in_set(&run); run.builder.ensure(Rustc { compiler: run.builder.compiler(run.builder.top_stage, run.build_triple()), target: run.target, + crates, }); } @@ -560,7 +609,7 @@ impl Step for Rustc { return; } - builder.ensure(Std { compiler, target }); + builder.ensure(Std::new(compiler, target)); if builder.config.keep_stage.contains(&compiler.stage) { builder.info("Warning: Using a potentially old librustc. This may not behave well."); @@ -571,7 +620,7 @@ impl Step for Rustc { let compiler_to_use = builder.compiler_for(compiler.stage, compiler.host, target); if compiler_to_use != compiler { - builder.ensure(Rustc { compiler: compiler_to_use, target }); + builder.ensure(Rustc::new(compiler_to_use, target)); builder .info(&format!("Uplifting stage1 rustc ({} -> {})", builder.config.build, target)); builder.ensure(RustcLink { @@ -583,10 +632,10 @@ impl Step for Rustc { } // Ensure that build scripts and proc macros have a std / libproc_macro to link against. - builder.ensure(Std { - compiler: builder.compiler(self.compiler.stage, builder.config.build), - target: builder.config.build, - }); + builder.ensure(Std::new( + builder.compiler(self.compiler.stage, builder.config.build), + builder.config.build, + )); let mut cargo = builder.cargo(compiler, Mode::Rustc, SourceType::InTree, target, "build"); rustc_cargo(builder, &mut cargo, target); @@ -633,7 +682,7 @@ impl Step for Rustc { run_cargo( builder, cargo, - vec![], + self.crates.to_vec(), &librustc_stamp(builder, compiler, target), vec![], false, @@ -821,7 +870,7 @@ impl Step for CodegenBackend { let target = self.target; let backend = self.backend; - builder.ensure(Rustc { compiler, target }); + builder.ensure(Rustc::new(compiler, target)); if builder.config.keep_stage.contains(&compiler.stage) { builder.info( @@ -1103,7 +1152,7 @@ impl Step for Assemble { // link to these. (FIXME: Is that correct? It seems to be correct most // of the time but I think we do link to these for stage2/bin compilers // when not performing a full bootstrap). - builder.ensure(Rustc { compiler: build_compiler, target: target_compiler.host }); + builder.ensure(Rustc::new(build_compiler, target_compiler.host)); for &backend in builder.config.rust_codegen_backends.iter() { if backend == "llvm" { diff --git a/src/bootstrap/config.rs b/src/bootstrap/config.rs index 14607741932..2fc18c9e79e 100644 --- a/src/bootstrap/config.rs +++ b/src/bootstrap/config.rs @@ -857,7 +857,7 @@ impl Config { let build = toml.build.unwrap_or_default(); set(&mut config.initial_rustc, build.rustc.map(PathBuf::from)); - set(&mut config.out, build.build_dir.map(PathBuf::from)); + set(&mut config.out, flags.build_dir.or_else(|| build.build_dir.map(PathBuf::from))); // NOTE: Bootstrap spawns various commands with different working directories. // To avoid writing to random places on the file system, `config.out` needs to be an absolute path. if !config.out.is_absolute() { diff --git a/src/bootstrap/dist.rs b/src/bootstrap/dist.rs index 8182d2bf8fb..4aadc3943c9 100644 --- a/src/bootstrap/dist.rs +++ b/src/bootstrap/dist.rs @@ -557,7 +557,7 @@ impl Step for Std { return None; } - builder.ensure(compile::Std { compiler, target }); + builder.ensure(compile::Std::new(compiler, target)); let mut tarball = Tarball::new(builder, "rust-std", &target.triple); tarball.include_target_in_component_name(true); @@ -603,7 +603,7 @@ impl Step for RustcDev { return None; } - builder.ensure(compile::Rustc { compiler, target }); + builder.ensure(compile::Rustc::new(compiler, target)); let tarball = Tarball::new(builder, "rustc-dev", &target.triple); @@ -666,7 +666,7 @@ impl Step for Analysis { return None; } - builder.ensure(compile::Std { compiler, target }); + builder.ensure(compile::Std::new(compiler, target)); let src = builder .stage_out(compiler, Mode::Std) .join(target.triple) @@ -1044,12 +1044,6 @@ impl Step for RustAnalyzer { } fn run(self, builder: &Builder<'_>) -> Option<GeneratedTarball> { - // This prevents rust-analyzer from being built for "dist" or "install" - // on the stable/beta channels. It is a nightly-only tool and should - // not be included. - if !builder.build.unstable_features() { - return None; - } let compiler = self.compiler; let target = self.target; @@ -2031,6 +2025,8 @@ impl Step for RustDev { let mut tarball = Tarball::new(builder, "rust-dev", &target.triple); tarball.set_overlay(OverlayKind::LLVM); + builder.ensure(crate::native::Llvm { target }); + let src_bindir = builder.llvm_out(target).join("bin"); // If updating this list, you likely want to change // src/bootstrap/download-ci-llvm-stamp as well, otherwise local users diff --git a/src/bootstrap/doc.rs b/src/bootstrap/doc.rs index be6655ddb61..5b961456076 100644 --- a/src/bootstrap/doc.rs +++ b/src/bootstrap/doc.rs @@ -534,7 +534,9 @@ impl Step for Rustc { fn should_run(run: ShouldRun<'_>) -> ShouldRun<'_> { let builder = run.builder; - run.krate("rustc-main").path("compiler").default_condition(builder.config.compiler_docs) + run.crate_or_deps("rustc-main") + .path("compiler") + .default_condition(builder.config.compiler_docs) } fn make_run(run: RunConfig<'_>) { @@ -567,7 +569,7 @@ impl Step for Rustc { // Build the standard library, so that proc-macros can use it. // (Normally, only the metadata would be necessary, but proc-macros are special since they run at compile-time.) let compiler = builder.compiler(stage, builder.config.build); - builder.ensure(compile::Std { compiler, target: builder.config.build }); + builder.ensure(compile::Std::new(compiler, builder.config.build)); builder.info(&format!("Documenting stage{} compiler ({})", stage, target)); @@ -643,7 +645,7 @@ impl Step for Rustc { } macro_rules! tool_doc { - ($tool: ident, $should_run: literal, $path: literal, [$($krate: literal),+ $(,)?] $(,)?) => { + ($tool: ident, $should_run: literal, $path: literal, [$($krate: literal),+ $(,)?], in_tree = $in_tree:expr $(,)?) => { #[derive(Debug, Copy, Clone, Hash, PartialEq, Eq)] pub struct $tool { target: TargetSelection, @@ -656,7 +658,7 @@ macro_rules! tool_doc { fn should_run(run: ShouldRun<'_>) -> ShouldRun<'_> { let builder = run.builder; - run.krate($should_run).default_condition(builder.config.compiler_docs) + run.crate_or_deps($should_run).default_condition(builder.config.compiler_docs) } fn make_run(run: RunConfig<'_>) { @@ -683,7 +685,7 @@ macro_rules! tool_doc { // FIXME: is there a way to only ensure `check::Rustc` here? Last time I tried it failed // with strange errors, but only on a full bors test ... let compiler = builder.compiler(stage, builder.config.build); - builder.ensure(compile::Rustc { compiler, target }); + builder.ensure(compile::Rustc::new(compiler, target)); builder.info( &format!( @@ -699,6 +701,12 @@ macro_rules! tool_doc { t!(fs::create_dir_all(&out_dir)); t!(symlink_dir_force(&builder.config, &out, &out_dir)); + let source_type = if $in_tree == true { + SourceType::InTree + } else { + SourceType::Submodule + }; + // Build cargo command. let mut cargo = prepare_tool_cargo( builder, @@ -707,7 +715,7 @@ macro_rules! tool_doc { target, "doc", $path, - SourceType::InTree, + source_type, &[], ); @@ -723,20 +731,38 @@ macro_rules! tool_doc { cargo.rustdocflag("--show-type-layout"); cargo.rustdocflag("--generate-link-to-definition"); cargo.rustdocflag("-Zunstable-options"); - builder.run(&mut cargo.into()); + if $in_tree == true { + builder.run(&mut cargo.into()); + } else { + // Allow out-of-tree docs to fail (since the tool might be in a broken state). + if !builder.try_run(&mut cargo.into()) { + builder.info(&format!( + "WARNING: tool {} failed to document; ignoring failure because it is an out-of-tree tool", + stringify!($tool).to_lowercase(), + )); + } + } } } } } -tool_doc!(Rustdoc, "rustdoc-tool", "src/tools/rustdoc", ["rustdoc", "rustdoc-json-types"]); +tool_doc!( + Rustdoc, + "rustdoc-tool", + "src/tools/rustdoc", + ["rustdoc", "rustdoc-json-types"], + in_tree = true +); tool_doc!( Rustfmt, "rustfmt-nightly", "src/tools/rustfmt", ["rustfmt-nightly", "rustfmt-config_proc_macro"], + in_tree = true ); -tool_doc!(Clippy, "clippy", "src/tools/clippy", ["clippy_utils"]); +tool_doc!(Clippy, "clippy", "src/tools/clippy", ["clippy_utils"], in_tree = true); +tool_doc!(Miri, "miri", "src/tools/miri", ["miri"], in_tree = false); #[derive(Ord, PartialOrd, Debug, Copy, Clone, Hash, PartialEq, Eq)] pub struct ErrorIndex { @@ -866,7 +892,7 @@ impl Step for RustcBook { let rustc = builder.rustc(self.compiler); // The tool runs `rustc` for extracting output examples, so it needs a // functional sysroot. - builder.ensure(compile::Std { compiler: self.compiler, target: self.target }); + builder.ensure(compile::Std::new(self.compiler, self.target)); let mut cmd = builder.tool_cmd(Tool::LintDocs); cmd.arg("--src"); cmd.arg(builder.src.join("compiler")); diff --git a/src/bootstrap/flags.rs b/src/bootstrap/flags.rs index 9d4bb978bdc..7ebae55efc1 100644 --- a/src/bootstrap/flags.rs +++ b/src/bootstrap/flags.rs @@ -51,6 +51,7 @@ pub struct Flags { pub host: Option<Vec<TargetSelection>>, pub target: Option<Vec<TargetSelection>>, pub config: Option<PathBuf>, + pub build_dir: Option<PathBuf>, pub jobs: Option<u32>, pub cmd: Subcommand, pub incremental: bool, @@ -174,6 +175,12 @@ To learn more about a subcommand, run `./x.py <subcommand> -h`", opts.optflagmulti("v", "verbose", "use verbose output (-vv for very verbose)"); opts.optflag("i", "incremental", "use incremental compilation"); opts.optopt("", "config", "TOML configuration file for build", "FILE"); + opts.optopt( + "", + "build-dir", + "Build directory, overrides `build.build-dir` in `config.toml`", + "DIR", + ); opts.optopt("", "build", "build target of the stage0 compiler", "BUILD"); opts.optmulti("", "host", "host targets to build", "HOST"); opts.optmulti("", "target", "target targets to build", "TARGET"); @@ -649,6 +656,7 @@ Arguments: None }, config: matches.opt_str("config").map(PathBuf::from), + build_dir: matches.opt_str("build-dir").map(PathBuf::from), jobs: matches.opt_str("jobs").map(|j| j.parse().expect("`jobs` should be a number")), cmd, incremental: matches.opt_present("incremental"), diff --git a/src/bootstrap/lib.rs b/src/bootstrap/lib.rs index 859d35b7d7b..73bd588472d 100644 --- a/src/bootstrap/lib.rs +++ b/src/bootstrap/lib.rs @@ -107,23 +107,18 @@ use std::cell::{Cell, RefCell}; use std::collections::{HashMap, HashSet}; use std::env; use std::fs::{self, File}; +use std::io; use std::path::{Path, PathBuf}; use std::process::{self, Command}; use std::str; -#[cfg(unix)] -use std::os::unix::fs::symlink as symlink_file; -#[cfg(windows)] -use std::os::windows::fs::symlink_file; - use filetime::FileTime; use once_cell::sync::OnceCell; use crate::builder::Kind; use crate::config::{LlvmLibunwind, TargetSelection}; use crate::util::{ - check_run, exe, libdir, mtime, output, run, run_suppressed, t, try_run, try_run_suppressed, - CiEnv, + check_run, exe, libdir, mtime, output, run, run_suppressed, try_run, try_run_suppressed, CiEnv, }; mod builder; @@ -1460,7 +1455,7 @@ impl Build { src = t!(fs::canonicalize(src)); } else { let link = t!(fs::read_link(src)); - t!(symlink_file(link, dst)); + t!(self.symlink_file(link, dst)); return; } } @@ -1585,6 +1580,14 @@ impl Build { iter.map(|e| t!(e)).collect::<Vec<_>>().into_iter() } + fn symlink_file<P: AsRef<Path>, Q: AsRef<Path>>(&self, src: P, link: Q) -> io::Result<()> { + #[cfg(unix)] + use std::os::unix::fs::symlink as symlink_file; + #[cfg(windows)] + use std::os::windows::fs::symlink_file; + if !self.config.dry_run { symlink_file(src.as_ref(), link.as_ref()) } else { Ok(()) } + } + fn remove(&self, f: &Path) { if self.config.dry_run { return; diff --git a/src/bootstrap/native.rs b/src/bootstrap/native.rs index 9cd8b6d1455..503a2fc469e 100644 --- a/src/bootstrap/native.rs +++ b/src/bootstrap/native.rs @@ -251,9 +251,7 @@ impl Step for Llvm { }; builder.update_submodule(&Path::new("src").join("llvm-project")); - if builder.llvm_link_shared() - && (target.contains("windows") || target.contains("apple-darwin")) - { + if builder.llvm_link_shared() && target.contains("windows") { panic!("shared linking to LLVM is not currently supported on {}", target.triple); } @@ -359,7 +357,9 @@ impl Step for Llvm { // // If we're not linking rustc to a dynamic LLVM, though, then don't link // tools to it. - if builder.llvm_link_tools_dynamically(target) && builder.llvm_link_shared() { + let llvm_link_shared = + builder.llvm_link_tools_dynamically(target) && builder.llvm_link_shared(); + if llvm_link_shared { cfg.define("LLVM_LINK_LLVM_DYLIB", "ON"); } @@ -438,18 +438,18 @@ impl Step for Llvm { ); } - if let Some(ref suffix) = builder.config.llvm_version_suffix { + let llvm_version_suffix = if let Some(ref suffix) = builder.config.llvm_version_suffix { // Allow version-suffix="" to not define a version suffix at all. - if !suffix.is_empty() { - cfg.define("LLVM_VERSION_SUFFIX", suffix); - } + if !suffix.is_empty() { Some(suffix.to_string()) } else { None } } else if builder.config.channel == "dev" { // Changes to a version suffix require a complete rebuild of the LLVM. // To avoid rebuilds during a time of version bump, don't include rustc // release number on the dev channel. - cfg.define("LLVM_VERSION_SUFFIX", "-rust-dev"); + Some("-rust-dev".to_string()) } else { - let suffix = format!("-rust-{}-{}", builder.version, builder.config.channel); + Some(format!("-rust-{}-{}", builder.version, builder.config.channel)) + }; + if let Some(ref suffix) = llvm_version_suffix { cfg.define("LLVM_VERSION_SUFFIX", suffix); } @@ -478,6 +478,25 @@ impl Step for Llvm { cfg.build(); + // When building LLVM with LLVM_LINK_LLVM_DYLIB for macOS, an unversioned + // libLLVM.dylib will be built. However, llvm-config will still look + // for a versioned path like libLLVM-14.dylib. Manually create a symbolic + // link to make llvm-config happy. + if llvm_link_shared && target.contains("apple-darwin") { + let mut cmd = Command::new(&build_llvm_config); + let version = output(cmd.arg("--version")); + let major = version.split('.').next().unwrap(); + let lib_name = match llvm_version_suffix { + Some(s) => format!("libLLVM-{}{}.dylib", major, s), + None => format!("libLLVM-{}.dylib", major), + }; + + let lib_llvm = out_dir.join("build").join("lib").join(lib_name); + if !lib_llvm.exists() { + t!(builder.symlink_file("libLLVM.dylib", &lib_llvm)); + } + } + t!(stamp.write()); build_llvm_config diff --git a/src/bootstrap/test.rs b/src/bootstrap/test.rs index 9958306b576..6be3da55291 100644 --- a/src/bootstrap/test.rs +++ b/src/bootstrap/test.rs @@ -225,7 +225,7 @@ impl Step for Cargotest { /// test` to ensure that we don't regress the test suites there. fn run(self, builder: &Builder<'_>) { let compiler = builder.compiler(self.stage, self.host); - builder.ensure(compile::Rustc { compiler, target: compiler.host }); + builder.ensure(compile::Rustc::new(compiler, compiler.host)); let cargo = builder.ensure(tool::Cargo { compiler, target: compiler.host }); // Note that this is a short, cryptic, and not scoped directory name. This @@ -603,7 +603,7 @@ impl Step for CompiletestTest { // We need `ToolStd` for the locally-built sysroot because // compiletest uses unstable features of the `test` crate. - builder.ensure(compile::Std { compiler, target: host }); + builder.ensure(compile::Std::new(compiler, host)); let cargo = tool::prepare_tool_cargo( builder, compiler, @@ -896,7 +896,7 @@ impl Step for RustdocGUI { let nodejs = builder.config.nodejs.as_ref().expect("nodejs isn't available"); let npm = builder.config.npm.as_ref().expect("npm isn't available"); - builder.ensure(compile::Std { compiler: self.compiler, target: self.target }); + builder.ensure(compile::Std::new(self.compiler, self.target)); // The goal here is to check if the necessary packages are installed, and if not, we // panic. @@ -1273,12 +1273,12 @@ note: if you're sure you want to do this, please open an issue as to why. In the } if suite.ends_with("fulldeps") { - builder.ensure(compile::Rustc { compiler, target }); + builder.ensure(compile::Rustc::new(compiler, target)); } - builder.ensure(compile::Std { compiler, target }); + builder.ensure(compile::Std::new(compiler, target)); // ensure that `libproc_macro` is available on the host. - builder.ensure(compile::Std { compiler, target: compiler.host }); + builder.ensure(compile::Std::new(compiler, compiler.host)); // Also provide `rust_test_helpers` for the host. builder.ensure(native::TestHelpers { target: compiler.host }); @@ -1363,13 +1363,10 @@ note: if you're sure you want to do this, please open an issue as to why. In the if let Some(ref npm) = builder.config.npm { cmd.arg("--npm").arg(npm); } - - let mut flags = if is_rustdoc { Vec::new() } else { vec!["-Crpath".to_string()] }; - if !is_rustdoc { - if builder.config.rust_optimize_tests { - flags.push("-O".to_string()); - } + if builder.config.rust_optimize_tests { + cmd.arg("--optimize-tests"); } + let mut flags = if is_rustdoc { Vec::new() } else { vec!["-Crpath".to_string()] }; flags.push(format!("-Cdebuginfo={}", builder.config.rust_debuginfo_level_tests)); flags.push(builder.config.cmd.rustc_args().join(" ")); @@ -1646,7 +1643,7 @@ impl BookTest { fn run_ext_doc(self, builder: &Builder<'_>) { let compiler = self.compiler; - builder.ensure(compile::Std { compiler, target: compiler.host }); + builder.ensure(compile::Std::new(compiler, compiler.host)); // mdbook just executes a binary named "rustdoc", so we need to update // PATH so that it points to our rustdoc. @@ -1674,7 +1671,7 @@ impl BookTest { fn run_local_doc(self, builder: &Builder<'_>) { let compiler = self.compiler; - builder.ensure(compile::Std { compiler, target: compiler.host }); + builder.ensure(compile::Std::new(compiler, compiler.host)); // Do a breadth-first traversal of the `src/doc` directory and just run // tests for all files that end in `*.md` @@ -1793,7 +1790,7 @@ impl Step for ErrorIndex { builder.run_quiet(&mut tool); // The tests themselves need to link to std, so make sure it is // available. - builder.ensure(compile::Std { compiler, target: compiler.host }); + builder.ensure(compile::Std::new(compiler, compiler.host)); markdown_test(builder, compiler, &output); } } @@ -1870,7 +1867,7 @@ impl Step for CrateLibrustc { const ONLY_HOSTS: bool = true; fn should_run(run: ShouldRun<'_>) -> ShouldRun<'_> { - run.krate("rustc-main") + run.crate_or_deps("rustc-main") } fn make_run(run: RunConfig<'_>) { @@ -1912,7 +1909,7 @@ impl Step for Crate { const DEFAULT: bool = true; fn should_run(run: ShouldRun<'_>) -> ShouldRun<'_> { - run.krate("test") + run.crate_or_deps("test") } fn make_run(run: RunConfig<'_>) { @@ -1943,7 +1940,7 @@ impl Step for Crate { let mode = self.mode; let test_kind = self.test_kind; - builder.ensure(compile::Std { compiler, target }); + builder.ensure(compile::Std::new(compiler, target)); builder.ensure(RemoteCopyLibs { compiler, target }); // If we're not doing a full bootstrap but we're testing a stage2 @@ -2065,7 +2062,7 @@ impl Step for CrateRustdoc { // isn't really necessary. builder.compiler_for(builder.top_stage, target, target) }; - builder.ensure(compile::Rustc { compiler, target }); + builder.ensure(compile::Rustc::new(compiler, target)); let mut cargo = tool::prepare_tool_cargo( builder, @@ -2180,7 +2177,7 @@ impl Step for CrateRustdocJsonTypes { // `compiler`, then it would cause rustdoc to be built *again*, which // isn't really necessary. let compiler = builder.compiler_for(builder.top_stage, target, target); - builder.ensure(compile::Rustc { compiler, target }); + builder.ensure(compile::Rustc::new(compiler, target)); let mut cargo = tool::prepare_tool_cargo( builder, @@ -2248,7 +2245,7 @@ impl Step for RemoteCopyLibs { return; } - builder.ensure(compile::Std { compiler, target }); + builder.ensure(compile::Std::new(compiler, target)); builder.info(&format!("REMOTE copy libs to emulator ({})", target)); @@ -2418,7 +2415,7 @@ impl Step for TierCheck { /// Tests the Platform Support page in the rustc book. fn run(self, builder: &Builder<'_>) { - builder.ensure(compile::Std { compiler: self.compiler, target: self.compiler.host }); + builder.ensure(compile::Std::new(self.compiler, self.compiler.host)); let mut cargo = tool::prepare_tool_cargo( builder, self.compiler, diff --git a/src/bootstrap/tool.rs b/src/bootstrap/tool.rs index 905fa431d29..74a793d257e 100644 --- a/src/bootstrap/tool.rs +++ b/src/bootstrap/tool.rs @@ -51,10 +51,10 @@ impl Step for ToolBuild { match self.mode { Mode::ToolRustc => { - builder.ensure(compile::Std { compiler, target: compiler.host }); - builder.ensure(compile::Rustc { compiler, target }); + builder.ensure(compile::Std::new(compiler, compiler.host)); + builder.ensure(compile::Rustc::new(compiler, target)); } - Mode::ToolStd => builder.ensure(compile::Std { compiler, target }), + Mode::ToolStd => builder.ensure(compile::Std::new(compiler, target)), Mode::ToolBootstrap => {} // uses downloaded stage0 compiler libs _ => panic!("unexpected Mode for tool build"), } @@ -512,8 +512,8 @@ impl Step for Rustdoc { // When using `download-rustc` and a stage0 build_compiler, copying rustc doesn't actually // build stage0 libstd (because the libstd in sysroot has the wrong ABI). Explicitly build // it. - builder.ensure(compile::Std { compiler: build_compiler, target: target_compiler.host }); - builder.ensure(compile::Rustc { compiler: build_compiler, target: target_compiler.host }); + builder.ensure(compile::Std::new(build_compiler, target_compiler.host)); + builder.ensure(compile::Rustc::new(build_compiler, target_compiler.host)); // NOTE: this implies that `download-rustc` is pretty useless when compiling with the stage0 // compiler, since you do just as much work. if !builder.config.dry_run && builder.download_rustc() && build_compiler.stage == 0 { @@ -780,7 +780,7 @@ tool_extended!((self, builder), // and this is close enough for now. RustDemangler, rust_demangler, "src/tools/rust-demangler", "rust-demangler", stable=false, in_tree=true, tool_std=true, {}; Rustfmt, rustfmt, "src/tools/rustfmt", "rustfmt", stable=true, in_tree=true, {}; - RustAnalyzer, rust_analyzer, "src/tools/rust-analyzer/crates/rust-analyzer", "rust-analyzer", stable=false, submodule="rust-analyzer", {}; + RustAnalyzer, rust_analyzer, "src/tools/rust-analyzer/crates/rust-analyzer", "rust-analyzer", stable=true, submodule="rust-analyzer", {}; ); impl<'a> Builder<'a> { diff --git a/src/bootstrap/util.rs b/src/bootstrap/util.rs index 4b2b058a780..6f4266a7f29 100644 --- a/src/bootstrap/util.rs +++ b/src/bootstrap/util.rs @@ -22,6 +22,7 @@ use crate::config::{Config, TargetSelection}; /// /// This is currently used judiciously throughout the build system rather than /// using a `Result` with `try!`, but this may change one day... +#[macro_export] macro_rules! t { ($e:expr) => { match $e { @@ -37,7 +38,7 @@ macro_rules! t { } }; } -pub(crate) use t; +pub use t; /// Given an executable called `name`, return the filename for the /// executable for a particular target. diff --git a/src/ci/docker/host-x86_64/dist-various-2/shared.sh b/src/ci/docker/host-x86_64/dist-various-2/shared.sh index 267d8b79cc2..291f26bdaeb 100644 --- a/src/ci/docker/host-x86_64/dist-various-2/shared.sh +++ b/src/ci/docker/host-x86_64/dist-various-2/shared.sh @@ -33,15 +33,3 @@ function retry { } done } - -# Copied from ../../init_repo.sh -function fetch_github_commit_archive { - local module=$1 - local cached="download-${module//\//-}.tar.gz" - retry sh -c "rm -f $cached && \ - curl -f -sSL -o $cached $2" - mkdir $module - touch "$module/.git" - tar -C $module --strip-components=1 -xf $cached - rm $cached -} diff --git a/src/ci/docker/host-x86_64/x86_64-gnu-tools/browser-ui-test.version b/src/ci/docker/host-x86_64/x86_64-gnu-tools/browser-ui-test.version index 9cf038687f1..bae256fd5b3 100644 --- a/src/ci/docker/host-x86_64/x86_64-gnu-tools/browser-ui-test.version +++ b/src/ci/docker/host-x86_64/x86_64-gnu-tools/browser-ui-test.version @@ -1 +1 @@ -0.9.6 \ No newline at end of file +0.9.7 \ No newline at end of file diff --git a/src/ci/init_repo.sh b/src/ci/init_repo.sh deleted file mode 100755 index e8c1e2b0f59..00000000000 --- a/src/ci/init_repo.sh +++ /dev/null @@ -1,83 +0,0 @@ -#!/usr/bin/env bash - -set -o errexit -set -o pipefail -set -o nounset - -ci_dir=$(cd $(dirname $0) && pwd) -. "$ci_dir/shared.sh" - -REPO_DIR="$1" -CACHE_DIR="$2" - -cache_src_dir="$CACHE_DIR/src" - -if [ ! -d "$REPO_DIR" -o ! -d "$REPO_DIR/.git" ]; then - echo "Error: $REPO_DIR does not exist or is not a git repo" - exit 1 -fi -cd $REPO_DIR -if [ ! -d "$CACHE_DIR" ]; then - echo "Error: $CACHE_DIR does not exist or is not an absolute path" - exit 1 -fi - -rm -rf "$CACHE_DIR" -mkdir "$CACHE_DIR" - -# On the beta channel we'll be automatically calculating the prerelease version -# via the git history, so unshallow our shallow clone from CI. -if [ "$(releaseChannel)" = "beta" ]; then - git fetch origin --unshallow beta master -fi - -# Duplicated in docker/dist-various-2/shared.sh -function fetch_github_commit_archive { - local module=$1 - local cached="download-${module//\//-}.tar.gz" - retry sh -c "rm -f $cached && \ - curl -f -sSL -o $cached $2" - mkdir $module - touch "$module/.git" - # On Windows, the default behavior is to emulate symlinks by copying - # files. However, that ends up being order-dependent while extracting, - # which can cause a failure if the symlink comes first. This env var - # causes tar to use real symlinks instead, which are allowed to dangle. - export MSYS=winsymlinks:nativestrict - tar -C $module --strip-components=1 -xf $cached - rm $cached -} - -# Archive downloads are temporarily disabled due to sudden 504 -# gateway timeout errors. -# included="src/llvm-project src/doc/book src/doc/rust-by-example" -included="" -modules="$(git config --file .gitmodules --get-regexp '\.path$' | cut -d' ' -f2)" -modules=($modules) -use_git="" -urls="$(git config --file .gitmodules --get-regexp '\.url$' | cut -d' ' -f2)" -urls=($urls) -# shellcheck disable=SC2068 -for i in ${!modules[@]}; do - module=${modules[$i]} - if [[ " $included " = *" $module "* ]]; then - commit="$(git ls-tree HEAD $module | awk '{print $3}')" - git rm $module - url=${urls[$i]} - url=${url/\.git/} - fetch_github_commit_archive $module "$url/archive/$commit.tar.gz" & - bg_pids[${i}]=$! - continue - else - use_git="$use_git $module" - fi -done -retry sh -c "git submodule deinit -f $use_git && \ - git submodule sync && \ - git submodule update -j 16 --init --recursive --depth 1 $use_git" -# STATUS=0 -# for pid in ${bg_pids[*]} -# do -# wait $pid || STATUS=1 -# done -# exit ${STATUS} diff --git a/src/ci/scripts/checkout-submodules.sh b/src/ci/scripts/checkout-submodules.sh index 0b44ea3c90b..3eb4b8f9058 100755 --- a/src/ci/scripts/checkout-submodules.sh +++ b/src/ci/scripts/checkout-submodules.sh @@ -2,16 +2,70 @@ # Check out all our submodules, but more quickly than using git by using one of # our custom scripts -set -euo pipefail -IFS=$'\n\t' +set -o errexit +set -o pipefail +set -o nounset -source "$(cd "$(dirname "$0")" && pwd)/../shared.sh" +if [ ! -d ".git" ]; then + echo "Error: This must run in the root of the repository" + exit 1 +fi + +ci_dir=$(cd $(dirname $0) && pwd)/.. +. "$ci_dir/shared.sh" -if isWindows; then - path="/c/cache/rustsrc" -else - path="${HOME}/rustsrc" +# On the beta channel we'll be automatically calculating the prerelease version +# via the git history, so unshallow our shallow clone from CI. +if [ "$(releaseChannel)" = "beta" ]; then + git fetch origin --unshallow beta master fi -mkdir -p "${path}" -"$(cd "$(dirname "$0")" && pwd)/../init_repo.sh" . "${path}" +function fetch_github_commit_archive { + local module=$1 + local cached="download-${module//\//-}.tar.gz" + retry sh -c "rm -f $cached && \ + curl -f -sSL -o $cached $2" + mkdir $module + touch "$module/.git" + # On Windows, the default behavior is to emulate symlinks by copying + # files. However, that ends up being order-dependent while extracting, + # which can cause a failure if the symlink comes first. This env var + # causes tar to use real symlinks instead, which are allowed to dangle. + export MSYS=winsymlinks:nativestrict + tar -C $module --strip-components=1 -xf $cached + rm $cached +} + +# Archive downloads are temporarily disabled due to sudden 504 +# gateway timeout errors. +# included="src/llvm-project src/doc/book src/doc/rust-by-example" +included="" +modules="$(git config --file .gitmodules --get-regexp '\.path$' | cut -d' ' -f2)" +modules=($modules) +use_git="" +urls="$(git config --file .gitmodules --get-regexp '\.url$' | cut -d' ' -f2)" +urls=($urls) +# shellcheck disable=SC2068 +for i in ${!modules[@]}; do + module=${modules[$i]} + if [[ " $included " = *" $module "* ]]; then + commit="$(git ls-tree HEAD $module | awk '{print $3}')" + git rm $module + url=${urls[$i]} + url=${url/\.git/} + fetch_github_commit_archive $module "$url/archive/$commit.tar.gz" & + bg_pids[${i}]=$! + continue + else + use_git="$use_git $module" + fi +done +retry sh -c "git submodule deinit -f $use_git && \ + git submodule sync && \ + git submodule update -j 16 --init --recursive --depth 1 $use_git" +# STATUS=0 +# for pid in ${bg_pids[*]} +# do +# wait $pid || STATUS=1 +# done +# exit ${STATUS} diff --git a/src/doc/book b/src/doc/book -Subproject efbafdba3618487fbc9305318fcab9775132ac1 +Subproject cf2653a5ca553cbbb4a17f1a7db1947820f6a77 diff --git a/src/doc/embedded-book b/src/doc/embedded-book -Subproject e17dcef5e96346ee3d7fa56820ddc7e5c39636b +Subproject 766979590da8100998f0d662499d4a901d8d164 diff --git a/src/doc/nomicon b/src/doc/nomicon -Subproject 3a43983b76174342b7dbd3e12ea2c49f762e52b +Subproject 70db9e4189f64d1d8e2451b1046111fb356b6dc diff --git a/src/doc/rust-by-example b/src/doc/rust-by-example -Subproject 1095df2a5850f2d345fad43a30633133365875b +Subproject 83724ca387a2a1cd3e8d848f62820020760e358 diff --git a/src/doc/rustc-dev-guide b/src/doc/rustc-dev-guide -Subproject 048d925f0a955aac601c4160c0e7f05771bcf63 +Subproject eb83839e903a0a8f1406f7e941886273f189b26 diff --git a/src/librustdoc/clean/mod.rs b/src/librustdoc/clean/mod.rs index 12467001271..6ee725edcfc 100644 --- a/src/librustdoc/clean/mod.rs +++ b/src/librustdoc/clean/mod.rs @@ -167,7 +167,7 @@ fn clean_poly_trait_ref_with_bindings<'tcx>( .collect_referenced_late_bound_regions(&poly_trait_ref) .into_iter() .filter_map(|br| match br { - ty::BrNamed(_, name) => Some(GenericParamDef { + ty::BrNamed(_, name) if name != kw::UnderscoreLifetime => Some(GenericParamDef { name, kind: GenericParamDefKind::Lifetime { outlives: vec![] }, }), diff --git a/src/librustdoc/clean/utils.rs b/src/librustdoc/clean/utils.rs index 16574f94c00..22b1e2335fd 100644 --- a/src/librustdoc/clean/utils.rs +++ b/src/librustdoc/clean/utils.rs @@ -340,17 +340,98 @@ pub(crate) fn is_literal_expr(tcx: TyCtxt<'_>, hir_id: hir::HirId) -> bool { false } +/// Build a textual representation of an unevaluated constant expression. +/// +/// If the const expression is too complex, an underscore `_` is returned. +/// For const arguments, it's `{ _ }` to be precise. +/// This means that the output is not necessarily valid Rust code. +/// +/// Currently, only +/// +/// * literals (optionally with a leading `-`) +/// * unit `()` +/// * blocks (`{ … }`) around simple expressions and +/// * paths without arguments +/// +/// are considered simple enough. Simple blocks are included since they are +/// necessary to disambiguate unit from the unit type. +/// This list might get extended in the future. +/// +/// Without this censoring, in a lot of cases the output would get too large +/// and verbose. Consider `match` expressions, blocks and deeply nested ADTs. +/// Further, private and `doc(hidden)` fields of structs would get leaked +/// since HIR datatypes like the `body` parameter do not contain enough +/// semantic information for this function to be able to hide them – +/// at least not without significant performance overhead. +/// +/// Whenever possible, prefer to evaluate the constant first and try to +/// use a different method for pretty-printing. Ideally this function +/// should only ever be used as a fallback. pub(crate) fn print_const_expr(tcx: TyCtxt<'_>, body: hir::BodyId) -> String { let hir = tcx.hir(); let value = &hir.body(body).value; - let snippet = if !value.span.from_expansion() { - tcx.sess.source_map().span_to_snippet(value.span).ok() - } else { - None - }; + #[derive(PartialEq, Eq)] + enum Classification { + Literal, + Simple, + Complex, + } - snippet.unwrap_or_else(|| rustc_hir_pretty::id_to_string(&hir, body.hir_id)) + use Classification::*; + + fn classify(expr: &hir::Expr<'_>) -> Classification { + match &expr.kind { + hir::ExprKind::Unary(hir::UnOp::Neg, expr) => { + if matches!(expr.kind, hir::ExprKind::Lit(_)) { Literal } else { Complex } + } + hir::ExprKind::Lit(_) => Literal, + hir::ExprKind::Tup([]) => Simple, + hir::ExprKind::Block(hir::Block { stmts: [], expr: Some(expr), .. }, _) => { + if classify(expr) == Complex { Complex } else { Simple } + } + // Paths with a self-type or arguments are too “complex” following our measure since + // they may leak private fields of structs (with feature `adt_const_params`). + // Consider: `<Self as Trait<{ Struct { private: () } }>>::CONSTANT`. + // Paths without arguments are definitely harmless though. + hir::ExprKind::Path(hir::QPath::Resolved(_, hir::Path { segments, .. })) => { + if segments.iter().all(|segment| segment.args.is_none()) { Simple } else { Complex } + } + // FIXME: Claiming that those kinds of QPaths are simple is probably not true if the Ty + // contains const arguments. Is there a *concise* way to check for this? + hir::ExprKind::Path(hir::QPath::TypeRelative(..)) => Simple, + // FIXME: Can they contain const arguments and thus leak private struct fields? + hir::ExprKind::Path(hir::QPath::LangItem(..)) => Simple, + _ => Complex, + } + } + + let classification = classify(value); + + if classification == Literal + && !value.span.from_expansion() + && let Ok(snippet) = tcx.sess.source_map().span_to_snippet(value.span) { + // For literals, we avoid invoking the pretty-printer and use the source snippet instead to + // preserve certain stylistic choices the user likely made for the sake legibility like + // + // * hexadecimal notation + // * underscores + // * character escapes + // + // FIXME: This passes through `-/*spacer*/0` verbatim. + snippet + } else if classification == Simple { + // Otherwise we prefer pretty-printing to get rid of extraneous whitespace, comments and + // other formatting artifacts. + rustc_hir_pretty::id_to_string(&hir, body.hir_id) + } else if tcx.def_kind(hir.body_owner_def_id(body).to_def_id()) == DefKind::AnonConst { + // FIXME: Omit the curly braces if the enclosing expression is an array literal + // with a repeated element (an `ExprKind::Repeat`) as in such case it + // would not actually need any disambiguation. + "{ _ }".to_owned() + } else { + "_".to_owned() + } } /// Given a type Path, resolve it to a Type using the TyCtxt diff --git a/src/librustdoc/config.rs b/src/librustdoc/config.rs index 50d154dd278..04638aa1af6 100644 --- a/src/librustdoc/config.rs +++ b/src/librustdoc/config.rs @@ -353,11 +353,7 @@ impl Options { 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 { @@ -439,15 +435,19 @@ impl Options { return Err(0); } - if matches.free.is_empty() { + let (lint_opts, describe_lints, lint_cap) = get_cmd_lint_options(matches, error_format); + + let input = PathBuf::from(if describe_lints { + "" // dummy, this won't be used + } else if matches.free.is_empty() { diag.struct_err("missing file operand").emit(); return Err(1); - } - if matches.free.len() > 1 { + } else if matches.free.len() > 1 { diag.struct_err("too many file operands").emit(); return Err(1); - } - let input = PathBuf::from(&matches.free[0]); + } else { + &matches.free[0] + }); let libs = matches .opt_strs("L") @@ -698,8 +698,6 @@ impl Options { let with_examples = matches.opt_strs("with-examples"); let call_locations = crate::scrape_examples::load_call_locations(with_examples, &diag)?; - let (lint_opts, describe_lints, lint_cap) = get_cmd_lint_options(matches, error_format); - Ok(Options { input, proc_macro_crate, diff --git a/src/librustdoc/doctest.rs b/src/librustdoc/doctest.rs index ab72f4a3f50..509c4253f0f 100644 --- a/src/librustdoc/doctest.rs +++ b/src/librustdoc/doctest.rs @@ -1003,8 +1003,10 @@ impl Tester for Collector { let outdir = if let Some(mut path) = rustdoc_options.persist_doctests.clone() { path.push(&test_id); - std::fs::create_dir_all(&path) - .expect("Couldn't create directory for doctest executables"); + if let Err(err) = std::fs::create_dir_all(&path) { + eprintln!("Couldn't create directory for doctest executables: {}", err); + panic::resume_unwind(box ()); + } DirState::Perm(path) } else { diff --git a/src/librustdoc/html/format.rs b/src/librustdoc/html/format.rs index 056eda089c1..0982c4b3ace 100644 --- a/src/librustdoc/html/format.rs +++ b/src/librustdoc/html/format.rs @@ -146,6 +146,10 @@ impl Buffer { pub(crate) fn reserve(&mut self, additional: usize) { self.buffer.reserve(additional) } + + pub(crate) fn len(&self) -> usize { + self.buffer.len() + } } fn comma_sep<T: fmt::Display>( @@ -1283,10 +1287,6 @@ impl clean::FnDecl { let mut args = Buffer::html(); let mut args_plain = Buffer::new(); for (i, input) in self.inputs.values.iter().enumerate() { - if i == 0 { - args.push_str("<br>"); - } - if let Some(selfty) = input.to_self() { match selfty { clean::SelfValue => { @@ -1312,8 +1312,7 @@ impl clean::FnDecl { } } else { if i > 0 { - args.push_str(" <br>"); - args_plain.push_str(" "); + args.push_str("<br>"); } if input.is_const { args.push_str("const "); @@ -1360,13 +1359,14 @@ impl clean::FnDecl { let full_pad = format!("<br>{}", " ".repeat(indent + 4)); let close_pad = format!("<br>{}", " ".repeat(indent)); format!( - "({args}{close}){arrow}", + "({pad}{args}{close}){arrow}", + pad = if self.inputs.values.is_empty() { "" } else { &full_pad }, args = args.replace("<br>", &full_pad), close = close_pad, arrow = arrow ) } else { - format!("({args}){arrow}", args = args.replace("<br>", ""), arrow = arrow) + format!("({args}){arrow}", args = args.replace("<br>", " "), arrow = arrow) }; if f.alternate() { diff --git a/src/librustdoc/html/render/mod.rs b/src/librustdoc/html/render/mod.rs index 1ef41d62e5e..548f6c3a987 100644 --- a/src/librustdoc/html/render/mod.rs +++ b/src/librustdoc/html/render/mod.rs @@ -716,12 +716,14 @@ fn assoc_const( ty = ty.print(cx), ); if let Some(default) = default { + write!(w, " = "); + // FIXME: `.value()` uses `clean::utils::format_integer_with_underscore_sep` under the // hood which adds noisy underscores and a type suffix to number literals. // This hurts readability in this context especially when more complex expressions // are involved and it doesn't add much of value. // Find a way to print constants here without all that jazz. - write!(w, " = {}", default.value(cx.tcx()).unwrap_or_else(|| default.expr(cx.tcx()))); + write!(w, "{}", Escape(&default.value(cx.tcx()).unwrap_or_else(|| default.expr(cx.tcx())))); } } diff --git a/src/librustdoc/html/render/print_item.rs b/src/librustdoc/html/render/print_item.rs index 0fe99463f1d..3525007baf3 100644 --- a/src/librustdoc/html/render/print_item.rs +++ b/src/librustdoc/html/render/print_item.rs @@ -62,6 +62,17 @@ struct ItemVars<'a> { src_href: Option<&'a str>, } +/// Calls `print_where_clause` and returns `true` if a `where` clause was generated. +fn print_where_clause_and_check<'a, 'tcx: 'a>( + buffer: &mut Buffer, + gens: &'a clean::Generics, + cx: &'a Context<'tcx>, +) -> bool { + let len_before = buffer.len(); + write!(buffer, "{}", print_where_clause(gens, cx, 0, true)); + len_before != buffer.len() +} + pub(super) fn print_item( cx: &mut Context<'_>, item: &clean::Item, @@ -1152,17 +1163,21 @@ fn item_enum(w: &mut Buffer, cx: &mut Context<'_>, it: &clean::Item, e: &clean:: render_attributes_in_pre(w, it, ""); write!( w, - "{}enum {}{}{}", + "{}enum {}{}", it.visibility.print_with_space(it.item_id, cx), it.name.unwrap(), e.generics.print(cx), - print_where_clause(&e.generics, cx, 0, true), ); + if !print_where_clause_and_check(w, &e.generics, cx) { + // If there wasn't a `where` clause, we add a whitespace. + w.write_str(" "); + } + let variants_stripped = e.has_stripped_entries(); if count_variants == 0 && !variants_stripped { - w.write_str(" {}"); + w.write_str("{}"); } else { - w.write_str(" {\n"); + w.write_str("{\n"); let toggle = should_hide_fields(count_variants); if toggle { toggle_open(w, format_args!("{} variants", count_variants)); @@ -1360,6 +1375,15 @@ fn item_constant(w: &mut Buffer, cx: &mut Context<'_>, it: &clean::Item, c: &cle typ = c.type_.print(cx), ); + // FIXME: The code below now prints + // ` = _; // 100i32` + // if the expression is + // `50 + 50` + // which looks just wrong. + // Should we print + // ` = 100i32;` + // instead? + let value = c.value(cx.tcx()); let is_literal = c.is_literal(cx.tcx()); let expr = c.expr(cx.tcx()); @@ -1634,13 +1658,21 @@ fn render_union( tab: &str, cx: &Context<'_>, ) { - write!(w, "{}union {}", it.visibility.print_with_space(it.item_id, cx), it.name.unwrap()); - if let Some(g) = g { - write!(w, "{}", g.print(cx)); - write!(w, "{}", print_where_clause(g, cx, 0, true)); + write!(w, "{}union {}", it.visibility.print_with_space(it.item_id, cx), it.name.unwrap(),); + + let where_displayed = g + .map(|g| { + write!(w, "{}", g.print(cx)); + print_where_clause_and_check(w, g, cx) + }) + .unwrap_or(false); + + // If there wasn't a `where` clause, we add a whitespace. + if !where_displayed { + w.write_str(" "); } - write!(w, " {{\n{}", tab); + write!(w, "{{\n{}", tab); let count_fields = fields.iter().filter(|f| matches!(*f.kind, clean::StructFieldItem(..))).count(); let toggle = should_hide_fields(count_fields); @@ -1692,10 +1724,14 @@ fn render_struct( } match ty { CtorKind::Fictive => { - if let Some(g) = g { - write!(w, "{}", print_where_clause(g, cx, 0, true),) + let where_diplayed = g.map(|g| print_where_clause_and_check(w, g, cx)).unwrap_or(false); + + // If there wasn't a `where` clause, we add a whitespace. + if !where_diplayed { + w.write_str(" {"); + } else { + w.write_str("{"); } - w.write_str(" {"); let count_fields = fields.iter().filter(|f| matches!(*f.kind, clean::StructFieldItem(..))).count(); let has_visible_fields = count_fields > 0; @@ -1750,7 +1786,7 @@ fn render_struct( } w.write_str(")"); if let Some(g) = g { - write!(w, "{}", print_where_clause(g, cx, 0, false),) + write!(w, "{}", print_where_clause(g, cx, 0, false)); } // We only want a ";" when we are displaying a tuple struct, not a variant tuple struct. if structhead { @@ -1760,7 +1796,7 @@ fn render_struct( CtorKind::Const => { // Needed for PhantomData. if let Some(g) = g { - write!(w, "{}", print_where_clause(g, cx, 0, false),) + write!(w, "{}", print_where_clause(g, cx, 0, false)); } w.write_str(";"); } diff --git a/src/librustdoc/html/static/.eslintrc.js b/src/librustdoc/html/static/.eslintrc.js index 2817a8fe144..fcd925bb358 100644 --- a/src/librustdoc/html/static/.eslintrc.js +++ b/src/librustdoc/html/static/.eslintrc.js @@ -91,5 +91,6 @@ module.exports = { "no-script-url": "error", "no-sequences": "error", "no-throw-literal": "error", + "no-div-regex": "error", } }; diff --git a/src/librustdoc/html/static/css/rustdoc.css b/src/librustdoc/html/static/css/rustdoc.css index 5d0756d30fb..b3dc60d880b 100644 --- a/src/librustdoc/html/static/css/rustdoc.css +++ b/src/librustdoc/html/static/css/rustdoc.css @@ -114,6 +114,9 @@ body { -webkit-font-feature-settings: "kern", "liga"; -moz-font-feature-settings: "kern", "liga"; font-feature-settings: "kern", "liga"; + + background-color: var(--main-background-color); + color: var(--main-color); } h1 { @@ -158,8 +161,8 @@ h1.fqn { Underlines elsewhere in the documentation break up visual flow and tend to invert section hierarchies. */ h2, -.top-doc h3, -.top-doc h4 { +.top-doc .docblock > h3, +.top-doc .docblock > h4 { border-bottom: 1px solid; } h3.code-header { @@ -214,6 +217,26 @@ a.srclink, font-family: "Fira Sans", Arial, NanumBarunGothic, sans-serif; } +h1, h2, h3, h4, +a#toggle-all-docs, +a.anchor, +.small-section-header a, +#source-sidebar a, +pre.rust a, +.sidebar h2 a, +.sidebar h3 a, +.mobile-topbar h2 a, +.in-band a, +.search-results a, +.module-item .stab, +.import-item .stab, +.result-name .primitive > i, .result-name .keyword > i, +.content .method .where, +.content .fn .where, +.content .where.fmt-newline { + color: var(--main-color); +} + ol, ul { padding-left: 24px; } @@ -391,6 +414,14 @@ nav.sub { display: none; } +.source .sidebar, #sidebar-toggle, #source-sidebar { + background-color: var(--sidebar-background-color); +} + +#sidebar-toggle > button:hover, #sidebar-toggle > button:focus { + background-color: var(--sidebar-background-color-hover); +} + .source .sidebar > *:not(#sidebar-toggle) { opacity: 0; visibility: hidden; @@ -629,11 +660,6 @@ h2.location a { display: block; } -.invisible { - width: 100%; - display: inline-block; -} - .content .in-band { flex-grow: 1; margin: 0px; @@ -1008,6 +1034,11 @@ table, top: -5px; } +.popover, .popover::before { + background-color: var(--main-background-color); + color: var(--main-color); +} + #help-button .popover { max-width: 600px; } @@ -1370,7 +1401,6 @@ pre.rust { position: sticky; top: 0; left: 0; - cursor: pointer; font-weight: bold; font-size: 1.25rem; border-bottom: 1px solid; @@ -1391,7 +1421,24 @@ pre.rust { border-bottom: 1px solid; margin-bottom: 6px; } - +#sidebar-toggle > button { + background: none; + color: inherit; + cursor: pointer; + text-align: center; + border: none; + outline: none; + position: absolute; + top: 0; + bottom: 0; + left: 0; + right: 0; + /* work around button layout strangeness: https://stackoverflow.com/q/7271561 */ + width: 100%; + /* iOS button gradient: https://stackoverflow.com/q/5438567 */ + -webkit-appearance: none; + opacity: 1; +} #settings-menu, #help-button { margin-left: 4px; outline: none; @@ -1428,6 +1475,25 @@ pre.rust { animation: rotating 2s linear infinite; } +.setting-line .radio-line input:checked { + box-shadow: inset 0 0 0 3px var(--main-background-color); + background-color: var(--settings-input-color); +} +.setting-line .radio-line input:focus { + box-shadow: 0 0 1px 1px var(--settings-input-color); +} +/* In here we combine both `:focus` and `:checked` properties. */ +.setting-line .radio-line input:checked:focus { + box-shadow: inset 0 0 0 3px var(--main-background-color), + 0 0 2px 2px var(--settings-input-color); +} +.setting-line .radio-line input:hover { + border-color: var(--settings-input-color) !important; +} +input:checked + .slider { + background-color: var(--settings-input-color); +} + #help-button > button { font-family: "Fira Sans", Arial, sans-serif; text-align: center; @@ -1528,38 +1594,23 @@ kbd { margin-bottom: 1em; } -div.children { - padding-left: 27px; - display: none; +details.dir-entry { + padding-left: 4px; } -div.name { + +details.dir-entry > summary { + margin: 0 0 0 13px; + list-style-position: outside; cursor: pointer; - position: relative; - margin-left: 16px; } -div.files > a { - display: block; - padding: 0 3px; -} -div.files > a:hover, div.name:hover { - background-color: #a14b4b; + +details.dir-entry div.folders, details.dir-entry div.files { + padding-left: 23px; } -div.name.expand + .children { + +details.dir-entry a { display: block; } -div.name::before { - content: "\25B6"; - padding-left: 4px; - font-size: 0.625rem; - position: absolute; - left: -16px; - top: 4px; -} -div.name.expand::before { - transform: rotate(90deg); - left: -15px; - top: 2px; -} /* The hideme class is used on summary tags that contain a span with placeholder text shown only when the toggle is closed. For instance, @@ -1681,8 +1732,18 @@ details.rustdoc-toggle[open] > summary.hideme::after { content: "Collapse"; } +/* This is needed in docblocks to have the "▶" element to be on the same line. */ +.docblock summary > * { + display: inline-block; +} + /* Media Queries */ +/* +WARNING: RUSTDOC_MOBILE_BREAKPOINT MEDIA QUERY; +If you update this line, then you also need to update the line with the same warning +in storage.js plus the media query with (max-width: 700px) +*/ @media (min-width: 701px) { /* In case there is no documentation before a code block, we need to add some margin at the top to prevent an overlay between the "collapse toggle" and the information tooltip. @@ -1703,6 +1764,11 @@ details.rustdoc-toggle[open] > summary.hideme::after { } } +/* +WARNING: RUSTDOC_MOBILE_BREAKPOINT MEDIA QUERY +If you update this line, then you also need to update the line with the same warning +in storage.js plus the media query with (min-width: 701px) +*/ @media (max-width: 700px) { /* When linking to an item with an `id` (for instance, by clicking a link in the sidebar, or visiting a URL with a fragment like `#method.new`, we don't want the item to be obscured @@ -1772,9 +1838,11 @@ details.rustdoc-toggle[open] > summary.hideme::after { /* The source view uses a different design for the sidebar toggle, and doesn't have a topbar, so don't bump down the main content or the sidebar. */ .source main, - .source .sidebar { + .rustdoc.source .sidebar { top: 0; padding: 0; + height: 100vh; + border: 0; } .sidebar.shown, @@ -1924,6 +1992,9 @@ details.rustdoc-toggle[open] > summary.hideme::after { width: unset; border-top-right-radius: unset; border-bottom-right-radius: unset; + position: sticky; + border: 0; + border-bottom: 1px solid; } #source-sidebar { diff --git a/src/librustdoc/html/static/css/themes/ayu.css b/src/librustdoc/html/static/css/themes/ayu.css index b7d0db1f002..b25f5e9fdb1 100644 --- a/src/librustdoc/html/static/css/themes/ayu.css +++ b/src/librustdoc/html/static/css/themes/ayu.css @@ -3,30 +3,12 @@ Based off of the Ayu theme Original by Dempfi (https://github.com/dempfi/ayu) */ -/* General structure and fonts */ - -body, .popover, .popover::before { - background-color: #0f1419; - color: #c5c5c5; -} - -.setting-line .radio-line input { - border-color: #c5c5c5; -} -.setting-line .radio-line input:checked { - box-shadow: inset 0 0 0 3px #0f1419; - background-color: #ffb454; -} -.setting-line .radio-line input:focus { - box-shadow: 0 0 1px 1px #ffb454; -} -/* In here we combine both `:focus` and `:checked` properties. */ -.setting-line .radio-line input:checked:focus { - box-shadow: inset 0 0 0 3px 0f1419, - 0 0 2px 2px #ffb454; -} -.setting-line .radio-line input:hover { - border-color: #ffb454 !important; +:root { + --main-background-color: #0f1419; + --main-color: #c5c5c5; + --settings-input-color: #ffb454; + --sidebar-background-color: #14191f; + --sidebar-background-color-hover: rgba(70, 70, 70, 0.33); } .slider { @@ -35,9 +17,6 @@ body, .popover, .popover::before { .slider:before { background-color: white; } -input:checked + .slider { - background-color: #ffb454; -} input:focus + .slider { box-shadow: 0 0 0 2px #0a84ff, 0 0 0 6px rgba(10, 132, 255, 0.3); } @@ -62,10 +41,6 @@ h4 { background-color: #0f1419; } -.invisible { - background: rgba(0, 0, 0, 0); -} - .docblock code { color: #ffb454; } @@ -129,10 +104,6 @@ pre, .rustdoc.source .example-wrap { color: #ffb44c; } -.source .sidebar { - background-color: #14191f; -} - .sidebar-elems .location { color: #ff7733; } @@ -153,12 +124,6 @@ pre, .rustdoc.source .example-wrap { border-color: #5c6773; } -.content .method .where, -.content .fn .where, -.content .where.fmt-newline { - color: #c5c5c5; -} - .search-results a:hover { background-color: #777; } @@ -233,17 +198,6 @@ a { color: #39AFD7; } -a#toggle-all-docs, -a.anchor, -.small-section-header a, -#source-sidebar a, -pre.rust a, -.sidebar h2 a, -.sidebar h3 a, -.mobile-topbar h2 a, -.in-band a { - color: #c5c5c5; -} .sidebar h2 a, .sidebar h3 a { color: white; @@ -617,24 +571,16 @@ kbd { color: #999; } -#sidebar-toggle { - background-color: #14191f; -} -#sidebar-toggle:hover { - background-color: rgba(70, 70, 70, 0.33); -} -#source-sidebar { - background-color: #14191f; -} #source-sidebar > .title { color: #fff; border-bottom-color: #5c6773; } -#source-sidebar div.files > a:hover, div.name:hover { +#source-sidebar div.files > a:hover, details.dir-entry summary:hover, +#source-sidebar div.files > a:focus, details.dir-entry summary:focus { background-color: #14191f; color: #ffb44c; } -#source-sidebar div.files > .selected { +#source-sidebar div.files > a.selected { background-color: #14191f; color: #ffb44c; } diff --git a/src/librustdoc/html/static/css/themes/dark.css b/src/librustdoc/html/static/css/themes/dark.css index eb64ef3e771..a678ec1e1c1 100644 --- a/src/librustdoc/html/static/css/themes/dark.css +++ b/src/librustdoc/html/static/css/themes/dark.css @@ -1,25 +1,9 @@ -body, .popover, .popover::before { - background-color: #353535; - color: #ddd; -} - -.setting-line .radio-line input { - border-color: #ddd; -} -.setting-line .radio-line input:checked { - box-shadow: inset 0 0 0 3px #353535; - background-color: #2196f3; -} -.setting-line .radio-line input:focus { - box-shadow: 0 0 1px 1px #2196f3; -} -/* In here we combine both `:focus` and `:checked` properties. */ -.setting-line .radio-line input:checked:focus { - box-shadow: inset 0 0 0 3px #353535, - 0 0 2px 2px #2196f3; -} -.setting-line .radio-line input:hover { - border-color: #2196f3 !important; +:root { + --main-background-color: #353535; + --main-color: #ddd; + --settings-input-color: #2196f3; + --sidebar-background-color: #565656; + --sidebar-background-color-hover: #676767; } .slider { @@ -28,16 +12,10 @@ body, .popover, .popover::before { .slider:before { background-color: white; } -input:checked + .slider { - background-color: #2196F3; -} input:focus + .slider { box-shadow: 0 0 0 2px #0a84ff, 0 0 0 6px rgba(10, 132, 255, 0.3); } -h1, h2, h3, h4 { - color: #ddd; -} h1.fqn { border-bottom-color: #d2d2d2; } @@ -49,10 +27,6 @@ h2, h3, h4 { background-color: #353535; } -.invisible { - background: rgba(0, 0, 0, 0); -} - .docblock code, .docblock-short code { background-color: #2A2A2A; } @@ -98,10 +72,6 @@ pre, .rustdoc.source .example-wrap { background: #444; } -.source .sidebar { - background-color: #565656; -} - .line-numbers span { color: #3B91E2; } .line-numbers .line-highlighted { background-color: #0a042f !important; @@ -115,12 +85,6 @@ pre, .rustdoc.source .example-wrap { border-color: #ddd; } -.content .method .where, -.content .fn .where, -.content .where.fmt-newline { - color: #ddd; -} - .search-results a:hover { background-color: #777; } @@ -214,20 +178,6 @@ a { color: #D2991D; } -a#toggle-all-docs, -a.anchor, -.small-section-header a, -#source-sidebar a, -pre.rust a, -.sidebar h2 a, -.sidebar h3 a, -.mobile-topbar h2 a, -.in-band a { - color: #ddd; -} -.search-results a { - color: #ddd; -} a.test-arrow { color: #dedede; } @@ -261,11 +211,6 @@ details.undocumented > summary::before { border-color: #008dfd; } -.module-item .stab, -.import-item .stab { - color: #ddd; -} - .stab.empty-impl { background: #FFF5D6; border-color: #FFC600; color: #2f2f2f; } .stab.unstable { background: #FFF5D6; border-color: #FFC600; color: #2f2f2f; } .stab.deprecated { background: #ffc4c4; border-color: #db7b7b; color: #2f2f2f; } @@ -291,10 +236,6 @@ details.undocumented > summary::before { color: grey; } -.result-name .primitive > i, .result-name .keyword > i { - color: #ddd; -} - .line-numbers :target { background-color: transparent; } /* Code highlighting */ @@ -488,22 +429,14 @@ kbd { color: #ccc; } -#sidebar-toggle { - background-color: #565656; -} -#sidebar-toggle:hover { - background-color: #676767; -} -#source-sidebar { - background-color: #565656; -} #source-sidebar > .title { border-bottom-color: #ccc; } -#source-sidebar div.files > a:hover, div.name:hover { +#source-sidebar div.files > a:hover, details.dir-entry summary:hover, +#source-sidebar div.files > a:focus, details.dir-entry summary:focus { background-color: #444; } -#source-sidebar div.files > .selected { +#source-sidebar div.files > a.selected { background-color: #333; } diff --git a/src/librustdoc/html/static/css/themes/light.css b/src/librustdoc/html/static/css/themes/light.css index 00cdf835897..e8770ac2124 100644 --- a/src/librustdoc/html/static/css/themes/light.css +++ b/src/librustdoc/html/static/css/themes/light.css @@ -1,27 +1,9 @@ -/* General structure and fonts */ - -body, .popover, .popover::before { - background-color: white; - color: black; -} - -.setting-line .radio-line input { - border-color: black; -} -.setting-line .radio-line input:checked { - box-shadow: inset 0 0 0 3px white; - background-color: #2196f3; -} -.setting-line .radio-line input:focus { - box-shadow: 0 0 1px 1px #2196f3; -} -/* In here we combine both `:focus` and `:checked` properties. */ -.setting-line .radio-line input:checked:focus { - box-shadow: inset 0 0 0 3px white, - 0 0 2px 2px #2196f3; -} -.setting-line .radio-line input:hover { - border-color: #2196f3 !important; +:root { + --main-background-color: white; + --main-color: black; + --settings-input-color: #2196f3; + --sidebar-background-color: #F5F5F5; + --sidebar-background-color-hover: #E0E0E0; } .slider { @@ -30,16 +12,10 @@ body, .popover, .popover::before { .slider:before { background-color: white; } -input:checked + .slider { - background-color: #2196F3; -} input:focus + .slider { box-shadow: 0 0 0 2px #0a84ff, 0 0 0 6px rgba(10, 132, 255, 0.3); } -h1, h2, h3, h4 { - color: black; -} h1.fqn { border-bottom-color: #DDDDDD; } @@ -51,10 +27,6 @@ h2, h3, h4 { background-color: white; } -.invisible { - background: rgba(0, 0, 0, 0); -} - .docblock code, .docblock-short code { background-color: #F5F5F5; } @@ -100,10 +72,6 @@ pre, .rustdoc.source .example-wrap { background-color: #fff; } -.source .sidebar { - background-color: #f1f1f1; -} - .line-numbers span { color: #c67e2d; } .line-numbers .line-highlighted { background-color: #FDFFD3 !important; @@ -117,12 +85,6 @@ pre, .rustdoc.source .example-wrap { border-color: #ddd; } -.content .method .where, -.content .fn .where, -.content .where.fmt-newline { - color: #4E4C4C; -} - .search-results a:hover { background-color: #ddd; } @@ -213,20 +175,6 @@ a { color: #3873AD; } -a#toggle-all-docs, -a.anchor, -.small-section-header a, -#source-sidebar a, -pre.rust a, -.sidebar h2 a, -.sidebar h3 a, -.mobile-topbar h2 a, -.in-band a { - color: #000; -} -.search-results a { - color: initial; -} a.test-arrow { color: #f5f5f5; } @@ -250,11 +198,6 @@ details.undocumented > summary::before { border-color: #66afe9; } -.module-item .stab, -.import-item .stab { - color: #000; -} - .stab.empty-impl { background: #FFF5D6; border-color: #FFC600; } .stab.unstable { background: #FFF5D6; border-color: #FFC600; } .stab.deprecated { background: #ffc4c4; border-color: #db7b7b; } @@ -275,10 +218,6 @@ details.undocumented > summary::before { color: grey; } -.result-name .primitive > i, .result-name .keyword > i { - color: black; -} - .line-numbers :target { background-color: transparent; } /* Code highlighting */ @@ -472,25 +411,16 @@ kbd { color: #999; } -#sidebar-toggle { - background-color: #F5F5F5; -} -#sidebar-toggle:hover { - background-color: #E0E0E0; -} -#source-sidebar { - background-color: #F5F5F5; -} #source-sidebar > .title { border-bottom-color: #ccc; } -#source-sidebar div.files > a:hover, div.name:hover { +#source-sidebar div.files > a:hover, details.dir-entry summary:hover, +#source-sidebar div.files > a:focus, details.dir-entry summary:focus { background-color: #E0E0E0; } -#source-sidebar div.files > .selected { +#source-sidebar div.files > a.selected { background-color: #fff; } - .scraped-example-list .scrape-help { border-color: #555; color: #333; diff --git a/src/librustdoc/html/static/js/main.js b/src/librustdoc/html/static/js/main.js index c33e2727744..6658f07ce01 100644 --- a/src/librustdoc/html/static/js/main.js +++ b/src/librustdoc/html/static/js/main.js @@ -4,40 +4,6 @@ "use strict"; -if (!String.prototype.startsWith) { - String.prototype.startsWith = function(searchString, position) { - position = position || 0; - return this.indexOf(searchString, position) === position; - }; -} -if (!String.prototype.endsWith) { - String.prototype.endsWith = function(suffix, length) { - const l = length || this.length; - return this.indexOf(suffix, l - suffix.length) !== -1; - }; -} - -if (!DOMTokenList.prototype.add) { - DOMTokenList.prototype.add = function(className) { - if (className && !hasClass(this, className)) { - if (this.className && this.className.length > 0) { - this.className += " " + className; - } else { - this.className = className; - } - } - }; -} - -if (!DOMTokenList.prototype.remove) { - DOMTokenList.prototype.remove = function(className) { - if (className && this.className) { - this.className = (" " + this.className + " ").replace(" " + className + " ", " ") - .trim(); - } - }; -} - // Get a value from the rustdoc-vars div, which is used to convey data from // Rust to the JS. If there is no such element, return null. function getVar(name) { diff --git a/src/librustdoc/html/static/js/source-script.js b/src/librustdoc/html/static/js/source-script.js index 290c29d3141..1e9bfa5cc89 100644 --- a/src/librustdoc/html/static/js/source-script.js +++ b/src/librustdoc/html/static/js/source-script.js @@ -2,7 +2,7 @@ /* global sourcesIndex */ // Local js definitions: -/* global addClass, getCurrentValue, hasClass, onEachLazy, removeClass, browserSupportsHistoryApi */ +/* global addClass, getCurrentValue, onEachLazy, removeClass, browserSupportsHistoryApi */ /* global updateLocalStorage */ "use strict"; @@ -10,35 +10,36 @@ (function() { const rootPath = document.getElementById("rustdoc-vars").attributes["data-root-path"].value; +let oldScrollPosition = 0; + +function closeSidebarIfMobile() { + if (window.innerWidth < window.RUSTDOC_MOBILE_BREAKPOINT) { + updateLocalStorage("source-sidebar-show", "false"); + } +} function createDirEntry(elem, parent, fullPath, hasFoundFile) { - const name = document.createElement("div"); - name.className = "name"; + const dirEntry = document.createElement("details"); + const summary = document.createElement("summary"); + + dirEntry.className = "dir-entry"; fullPath += elem["name"] + "/"; - name.onclick = ev => { - if (hasClass(ev.target, "expand")) { - removeClass(ev.target, "expand"); - } else { - addClass(ev.target, "expand"); - } - }; - name.innerText = elem["name"]; + summary.innerText = elem["name"]; + dirEntry.appendChild(summary); - const children = document.createElement("div"); - children.className = "children"; const folders = document.createElement("div"); folders.className = "folders"; if (elem.dirs) { for (const dir of elem.dirs) { if (createDirEntry(dir, folders, fullPath, hasFoundFile)) { - addClass(name, "expand"); + dirEntry.open = true; hasFoundFile = true; } } } - children.appendChild(folders); + dirEntry.appendChild(folders); const files = document.createElement("div"); files.className = "files"; @@ -47,28 +48,42 @@ function createDirEntry(elem, parent, fullPath, hasFoundFile) { const file = document.createElement("a"); file.innerText = file_text; file.href = rootPath + "src/" + fullPath + file_text + ".html"; + file.addEventListener("click", closeSidebarIfMobile); const w = window.location.href.split("#")[0]; if (!hasFoundFile && w === file.href) { file.className = "selected"; - addClass(name, "expand"); + dirEntry.open = true; hasFoundFile = true; } files.appendChild(file); } } - children.appendChild(files); - parent.appendChild(name); - parent.appendChild(children); + dirEntry.appendChild(files); + parent.appendChild(dirEntry); return hasFoundFile; } function toggleSidebar() { - const child = this.children[0]; + const child = this.parentNode.children[0]; if (child.innerText === ">") { + if (window.innerWidth < window.RUSTDOC_MOBILE_BREAKPOINT) { + // This is to keep the scroll position on mobile. + oldScrollPosition = window.scrollY; + document.body.style.position = "fixed"; + document.body.style.top = `-${oldScrollPosition}px`; + } addClass(document.documentElement, "source-sidebar-expanded"); child.innerText = "<"; updateLocalStorage("source-sidebar-show", "true"); } else { + if (window.innerWidth < window.RUSTDOC_MOBILE_BREAKPOINT) { + // This is to keep the scroll position on mobile. + document.body.style.position = ""; + document.body.style.top = ""; + // The scroll position is lost when resetting the style, hence why we store it in + // `oldScroll`. + window.scrollTo(0, oldScrollPosition); + } removeClass(document.documentElement, "source-sidebar-expanded"); child.innerText = ">"; updateLocalStorage("source-sidebar-show", "false"); @@ -78,15 +93,15 @@ function toggleSidebar() { function createSidebarToggle() { const sidebarToggle = document.createElement("div"); sidebarToggle.id = "sidebar-toggle"; - sidebarToggle.onclick = toggleSidebar; - const inner = document.createElement("div"); + const inner = document.createElement("button"); if (getCurrentValue("source-sidebar-show") === "true") { inner.innerText = "<"; } else { inner.innerText = ">"; } + inner.onclick = toggleSidebar; sidebarToggle.appendChild(inner); return sidebarToggle; diff --git a/src/librustdoc/html/static/js/storage.js b/src/librustdoc/html/static/js/storage.js index 1c4c8834488..0c5389d45e5 100644 --- a/src/librustdoc/html/static/js/storage.js +++ b/src/librustdoc/html/static/js/storage.js @@ -9,6 +9,11 @@ const darkThemes = ["dark", "ayu"]; window.currentTheme = document.getElementById("themeStyle"); window.mainTheme = document.getElementById("mainThemeStyle"); +// WARNING: RUSTDOC_MOBILE_BREAKPOINT MEDIA QUERY +// If you update this line, then you also need to update the two media queries with the same +// warning in rustdoc.css +window.RUSTDOC_MOBILE_BREAKPOINT = 701; + const settingsDataset = (function() { const settingsElement = document.getElementById("default-settings"); if (settingsElement === null) { diff --git a/src/librustdoc/lib.rs b/src/librustdoc/lib.rs index db4c3d10237..ded3d9951bd 100644 --- a/src/librustdoc/lib.rs +++ b/src/librustdoc/lib.rs @@ -11,7 +11,6 @@ #![feature(drain_filter)] #![feature(let_chains)] #![feature(let_else)] -#![cfg_attr(bootstrap, feature(nll))] #![feature(test)] #![feature(never_type)] #![feature(once_cell)] @@ -76,7 +75,7 @@ use std::env::{self, VarError}; use std::io; use std::process; -use rustc_driver::{abort_on_err, describe_lints}; +use rustc_driver::abort_on_err; use rustc_errors::ErrorGuaranteed; use rustc_interface::interface; use rustc_middle::ty::TyCtxt; @@ -771,15 +770,24 @@ fn main_options(options: config::Options) -> MainResult { let config = core::create_config(options); interface::create_compiler_and_run(config, |compiler| { - compiler.enter(|queries| { - let sess = compiler.session(); + let sess = compiler.session(); - if sess.opts.describe_lints { - let (_, lint_store) = &*queries.register_plugins()?.peek(); - describe_lints(sess, lint_store, true); - return Ok(()); - } + if sess.opts.describe_lints { + let mut lint_store = rustc_lint::new_lint_store( + sess.opts.debugging_opts.no_interleave_lints, + sess.unstable_options(), + ); + let registered_lints = if let Some(register_lints) = compiler.register_lints() { + register_lints(sess, &mut lint_store); + true + } else { + false + }; + rustc_driver::describe_lints(sess, &lint_store, registered_lints); + return Ok(()); + } + compiler.enter(|queries| { // We need to hold on to the complete resolver, so we cause everything to be // cloned for the analysis passes to use. Suboptimal, but necessary in the // current architecture. diff --git a/src/librustdoc/passes/check_code_block_syntax.rs b/src/librustdoc/passes/check_code_block_syntax.rs index e3b349af661..8bf0971ccb5 100644 --- a/src/librustdoc/passes/check_code_block_syntax.rs +++ b/src/librustdoc/passes/check_code_block_syntax.rs @@ -1,7 +1,8 @@ //! Validates syntax inside Rust code blocks (\`\`\`rust). use rustc_data_structures::sync::{Lock, Lrc}; -use rustc_errors::{emitter::Emitter, Applicability, Diagnostic, Handler, LazyFallbackBundle}; -use rustc_middle::lint::LintDiagnosticBuilder; +use rustc_errors::{ + emitter::Emitter, Applicability, Diagnostic, Handler, LazyFallbackBundle, LintDiagnosticBuilder, +}; use rustc_parse::parse_stream_from_source_str; use rustc_session::parse::ParseSess; use rustc_span::hygiene::{AstPass, ExpnData, ExpnKind, LocalExpnId}; diff --git a/src/llvm-project b/src/llvm-project -Subproject d1ddc34c4b23468f6d2bf553084834b104e16dd +Subproject 8b6b5014fdad3a750f7242a6bfdcad83619498d diff --git a/src/stage0.json b/src/stage0.json index b6b502f4cf0..64b8aca3960 100644 --- a/src/stage0.json +++ b/src/stage0.json @@ -16,349 +16,349 @@ "tool is executed." ], "compiler": { - "date": "2022-05-20", + "date": "2022-06-29", "version": "beta" }, "rustfmt": { - "date": "2022-05-20", + "date": "2022-06-29", "version": "nightly" }, "checksums_sha256": { - "dist/2022-05-20/cargo-beta-aarch64-apple-darwin.tar.gz": "a07568445804e70f92f8b022a7397d44ac1a4ffc10633715a6ec5d48c27ea45a", - "dist/2022-05-20/cargo-beta-aarch64-apple-darwin.tar.xz": "574cb9ee69d5132317b159fa15a0651207361c1673d4c41b839bfd0f5c905b4e", - "dist/2022-05-20/cargo-beta-aarch64-pc-windows-msvc.tar.gz": "68e566b8d4d022b4f88771d7784e092e7c78b0e2198ad901048b5831b5a1a5d4", - "dist/2022-05-20/cargo-beta-aarch64-pc-windows-msvc.tar.xz": "f2808f120588bdf97fe5551150eaef2658967fef3e5e5ae3c531156a7312e883", - "dist/2022-05-20/cargo-beta-aarch64-unknown-linux-gnu.tar.gz": "92f31b6ccf0953a07c71e43b898273ad2e304afe840e4b03769122e4a6758553", - "dist/2022-05-20/cargo-beta-aarch64-unknown-linux-gnu.tar.xz": "6da85884371a794de85953b48d03549badb86684e2008491064ce120afab31ad", - "dist/2022-05-20/cargo-beta-aarch64-unknown-linux-musl.tar.gz": "34c9ead4dcc520424ba281ec99466b921970f64320dd051ea73a09cd39f012bf", - "dist/2022-05-20/cargo-beta-aarch64-unknown-linux-musl.tar.xz": "ab59385f4c61976f8f2fb31b6463b007eeaa0a71ca8dbbe884e33de4a0143c9d", - "dist/2022-05-20/cargo-beta-arm-unknown-linux-gnueabi.tar.gz": "68fc1f164b9f7a5c1f44d62e37c8c71a6518eff70d3397333c2fb268960ddc45", - "dist/2022-05-20/cargo-beta-arm-unknown-linux-gnueabi.tar.xz": "159e5e293afa533bb0259157fb2e32145d8c87921c253e45aad64c27a765df3a", - "dist/2022-05-20/cargo-beta-arm-unknown-linux-gnueabihf.tar.gz": "aa05252a10605158ae9baca676e9ca755fb6d042d4db9121d3e933c610fe8afa", - "dist/2022-05-20/cargo-beta-arm-unknown-linux-gnueabihf.tar.xz": "d6d090a90bf9c96a3955813ccdd956bf1ef1ee5c1431090f3ca4002f63703ab5", - "dist/2022-05-20/cargo-beta-armv7-unknown-linux-gnueabihf.tar.gz": "52bd65f5d845a4ca51b055e1e0e340b07a82aa7269730fef27d1c151bb0a25cd", - "dist/2022-05-20/cargo-beta-armv7-unknown-linux-gnueabihf.tar.xz": "c1f96a5d59c3c93be54d82e0b2082651347e53e10ef664332f74bd6f8189849c", - "dist/2022-05-20/cargo-beta-i686-pc-windows-gnu.tar.gz": "2ce5513fb746305d61ea301301e93f4879b3cf794298ac77aec0e3eb8dea072d", - "dist/2022-05-20/cargo-beta-i686-pc-windows-gnu.tar.xz": "64a800315d0e0555c1c9fb24312c9f6375f4a3ac02b975ed413e764d238c4698", - "dist/2022-05-20/cargo-beta-i686-pc-windows-msvc.tar.gz": "1c3464b48509b0e5dee428ecb3ea27c6ec463cc0148f1d04d7d2778b0d654295", - "dist/2022-05-20/cargo-beta-i686-pc-windows-msvc.tar.xz": "89f1072af529ea55884882c11f15f8109a3790407903c6f8026b27b21d2fe0fb", - "dist/2022-05-20/cargo-beta-i686-unknown-linux-gnu.tar.gz": "57f76852b21ff37e98f441f8b7f81bb8ced7dbc310df0f03a19c907220dd6bfc", - "dist/2022-05-20/cargo-beta-i686-unknown-linux-gnu.tar.xz": "2b8885f946f9dce27098318b7c5b9095c6e62a109614355fb176c33a6cd6451f", - "dist/2022-05-20/cargo-beta-mips-unknown-linux-gnu.tar.gz": "8b39dd25f1d3a26ec6f8fc1af32f848a0e71ed408f6f2a3f6489eead634f44d9", - "dist/2022-05-20/cargo-beta-mips-unknown-linux-gnu.tar.xz": "36c47221f6c80a6e8ff3c1fb8310decfe4a8a6a247d9ad4eceb61f82cc82fdf4", - "dist/2022-05-20/cargo-beta-mips64-unknown-linux-gnuabi64.tar.gz": "eac280aae12b8825bd6dc39a674e27cc6b46f830ef3fc6887b1afcc6b75728eb", - "dist/2022-05-20/cargo-beta-mips64-unknown-linux-gnuabi64.tar.xz": "80577e2157820a70107c55102a251a08c94f3fef3841262f55f85d276ec3bac5", - "dist/2022-05-20/cargo-beta-mips64el-unknown-linux-gnuabi64.tar.gz": "4c29ad8defc9b59f401da078452f9f9a7c0beb75f5edf1b91f4ac4270c707d3a", - "dist/2022-05-20/cargo-beta-mips64el-unknown-linux-gnuabi64.tar.xz": "78831636bf6e2d95d7172dfa3e811ad09c363b4178f2359fc597f8470e0981d5", - "dist/2022-05-20/cargo-beta-mipsel-unknown-linux-gnu.tar.gz": "aaf75a7ea07f00888d394d69a6d438aa5c18f8e3afd93c35fd0323ac01c14064", - "dist/2022-05-20/cargo-beta-mipsel-unknown-linux-gnu.tar.xz": "026535dae96b5aed3e435d1b4d6297aeb8430587d90c074b15215a91e59a719d", - "dist/2022-05-20/cargo-beta-powerpc-unknown-linux-gnu.tar.gz": "a3c7d6bfb93f9d15d1a5bd183c985ae939c6f39ce060e177cefbe4fd7e66c48c", - "dist/2022-05-20/cargo-beta-powerpc-unknown-linux-gnu.tar.xz": "a060b3581966433d2d874e75e4f94a180a8296b23401dd41d60fd8d633f96910", - "dist/2022-05-20/cargo-beta-powerpc64-unknown-linux-gnu.tar.gz": "77dc67bc9663de62e26752e2658468d859546f3b3dff4f33c2f2efec18a48a13", - "dist/2022-05-20/cargo-beta-powerpc64-unknown-linux-gnu.tar.xz": "cd44e2a0a68f83f9f714f6c7142a20e244b19c2a15b136cb58d71578393bcfab", - "dist/2022-05-20/cargo-beta-powerpc64le-unknown-linux-gnu.tar.gz": "0e296167172d82604e9dd36e3369662086903edf07ca4b9fd307d89b1051c8c3", - "dist/2022-05-20/cargo-beta-powerpc64le-unknown-linux-gnu.tar.xz": "28577c0e0dc0a9aae045bd834f3f5f9e4e9b3828528b1d702310baba8a8f77d6", - "dist/2022-05-20/cargo-beta-riscv64gc-unknown-linux-gnu.tar.gz": "83e3f41b7b32b77343bdc3776cd372d730eb20c382b73df84b3a427f24673814", - "dist/2022-05-20/cargo-beta-riscv64gc-unknown-linux-gnu.tar.xz": "1ee99bae6c41bbcd461c26d117424f338e55dd020dbdc9481c76b407593740b4", - "dist/2022-05-20/cargo-beta-s390x-unknown-linux-gnu.tar.gz": "529e3f38f37505ba406c3a77cbf0745dddbc87fc1296889e724194c56f5d7064", - "dist/2022-05-20/cargo-beta-s390x-unknown-linux-gnu.tar.xz": "304b8e4c493d9429bb8723a7e002a04405d2a67087cfd601f140827b8069bd4c", - "dist/2022-05-20/cargo-beta-x86_64-apple-darwin.tar.gz": "93583a3eb5f77ea810e5938bf5c172279122d4ddedab116da507256444d0df7c", - "dist/2022-05-20/cargo-beta-x86_64-apple-darwin.tar.xz": "98e75e460994b723c31a0efc7467b0ff59d57e08692ef472d95f66b5fbd57ac7", - "dist/2022-05-20/cargo-beta-x86_64-pc-windows-gnu.tar.gz": "652e67a93015f18b66b9cf938c1d8465498024d5c9e2f1f00eaac45500e0c1ff", - "dist/2022-05-20/cargo-beta-x86_64-pc-windows-gnu.tar.xz": "84d3d0a3bd0c8f7f68796cac7fa27aa7054fb47fee5199d1fd3d1dd62d80fe99", - "dist/2022-05-20/cargo-beta-x86_64-pc-windows-msvc.tar.gz": "9316dec3a49621107945f62688cea261b85ea85bce77368a44d1e69e1afe7b1b", - "dist/2022-05-20/cargo-beta-x86_64-pc-windows-msvc.tar.xz": "8abaf2a07bbeee46421bb2a261507cda1e4c50384b0cd1008754ae34bb2b89cc", - "dist/2022-05-20/cargo-beta-x86_64-unknown-freebsd.tar.gz": "17c47c467fa31e1807f76ade9e7b9eee991808b713dcd5f27f38cd11cd24fb7e", - "dist/2022-05-20/cargo-beta-x86_64-unknown-freebsd.tar.xz": "00ca9259f5f881427e1284f60b81a0b0b9dffd6f6b63428995ac2eb8d16eeac7", - "dist/2022-05-20/cargo-beta-x86_64-unknown-illumos.tar.gz": "c83811cb7bd17e612aa74218b260d4090a4ab375b3dffd6109b4544a2f0894d0", - "dist/2022-05-20/cargo-beta-x86_64-unknown-illumos.tar.xz": "c8b8ba1cd11ee76a909540132f44b9969273287231e6014eaf71e9b72bf6931a", - "dist/2022-05-20/cargo-beta-x86_64-unknown-linux-gnu.tar.gz": "77decd4386bf91bf39e9f3608d6ded89c88dbb009d685913d2e7f4ebc9d6d64c", - "dist/2022-05-20/cargo-beta-x86_64-unknown-linux-gnu.tar.xz": "6268bfcf05e9dfb5e0d24490e4150908a233536e5c76edc3506fa174c84482ea", - "dist/2022-05-20/cargo-beta-x86_64-unknown-linux-musl.tar.gz": "68d689586123f3f26fac77436c8f760e39afdc099a6eaf3ab8e3e000eb5db195", - "dist/2022-05-20/cargo-beta-x86_64-unknown-linux-musl.tar.xz": "dc2d76e52bf422bcc7e65b632252970659cb416af3f7f8e0f060d8e93d94ddc6", - "dist/2022-05-20/cargo-beta-x86_64-unknown-netbsd.tar.gz": "98389a862cef3f4b0cfe1e26dac8c125be4b138441dec3aa72e1ad2215c0920a", - "dist/2022-05-20/cargo-beta-x86_64-unknown-netbsd.tar.xz": "7fe62803ee7ad464d26ad33ffe1c4babce4dd129392c9b64ddbfc58df07791a6", - "dist/2022-05-20/rust-std-beta-aarch64-apple-darwin.tar.gz": "d45607fb802929f9b61a83348141f18ec50af949bb474d22c08431e2628a90e4", - "dist/2022-05-20/rust-std-beta-aarch64-apple-darwin.tar.xz": "978bab21c453918e00cd7a61741696eb34e7099da4a69c03ad9badabba62b9b1", - "dist/2022-05-20/rust-std-beta-aarch64-apple-ios-sim.tar.gz": "df3e94d9f805a6424bde33d3a56c8ff849c1f697f7df2ff041718e0ef3b89721", - "dist/2022-05-20/rust-std-beta-aarch64-apple-ios-sim.tar.xz": "60fa331aba8e90db42be0540c2f274355a662dab6d184484c5be1797eb56f6d2", - "dist/2022-05-20/rust-std-beta-aarch64-apple-ios.tar.gz": "3dabf5b1046221d9d3d933bab7c5e10b001173c0388a51324631420aa0ac7d29", - "dist/2022-05-20/rust-std-beta-aarch64-apple-ios.tar.xz": "d09cab1c57cc755c01d844da79a1579410e55bfcade5fbc5ecd74c5356278828", - "dist/2022-05-20/rust-std-beta-aarch64-fuchsia.tar.gz": "94f7de28d908e919ded94e3789cd2da7e13f86ec2c141134260b531627956fed", - "dist/2022-05-20/rust-std-beta-aarch64-fuchsia.tar.xz": "789019d7dcf82403fb17e3c833f708547ec6aec51e054b9cebf783a4a0dbba02", - "dist/2022-05-20/rust-std-beta-aarch64-linux-android.tar.gz": "f8d70b9f15b1177796d0b2f7fb3273e154f70601b638d3f28fd67058b714575e", - "dist/2022-05-20/rust-std-beta-aarch64-linux-android.tar.xz": "65b50ffc7ca059df5391d2eba3b0aad6fb14ca1ffec879e5df59cf220d2aa48b", - "dist/2022-05-20/rust-std-beta-aarch64-pc-windows-msvc.tar.gz": "04c897d04111dfa2dfcf236bbe460cf3839943ae2da2112b4a2ccdbe7f0a3f39", - "dist/2022-05-20/rust-std-beta-aarch64-pc-windows-msvc.tar.xz": "8a93c339b1bf9b861497101c9e35622fb750d6e0d909eee87d012c424e06d415", - "dist/2022-05-20/rust-std-beta-aarch64-unknown-linux-gnu.tar.gz": "5664d843370fdf6d5460f8fd6deaaf6da3c019f6d11375a35952b101c0dbc0cd", - "dist/2022-05-20/rust-std-beta-aarch64-unknown-linux-gnu.tar.xz": "051922c23e96812354a2a4ad46ec0a02e901f9bf1ad9ee1960aa043c2b88fb0e", - "dist/2022-05-20/rust-std-beta-aarch64-unknown-linux-musl.tar.gz": "26ee4cefcf20efc100d345d657c76d24b0cfdd404f1d20cfeca831a65565eab9", - "dist/2022-05-20/rust-std-beta-aarch64-unknown-linux-musl.tar.xz": "4e11588e86fcd7f80218cbf7d5fb3be2c54b7058f29e76b0cf26a3a72fa290a4", - "dist/2022-05-20/rust-std-beta-aarch64-unknown-none-softfloat.tar.gz": "b1dd1f1c1aded585c6d202f4fe1a275caf96b5ce4fc7f0be620fa36a05fafc72", - "dist/2022-05-20/rust-std-beta-aarch64-unknown-none-softfloat.tar.xz": "9103f4c7ff155671e5d2df6faaf4776b08fbe655f5e94928ace212b888aa6aea", - "dist/2022-05-20/rust-std-beta-aarch64-unknown-none.tar.gz": "65a03cf02a1ca34e2235717d517dba4b80de6bfaa42434ab12e50fe81ec27cfd", - "dist/2022-05-20/rust-std-beta-aarch64-unknown-none.tar.xz": "ff0492a699428be3136c8050155bfb7960bd21d1e4b8a53cf3620365c36983a9", - "dist/2022-05-20/rust-std-beta-arm-linux-androideabi.tar.gz": "983f3505a4313fa90556ecc48b8a793d3585ca7a429a7dd837270e8161f6b34a", - "dist/2022-05-20/rust-std-beta-arm-linux-androideabi.tar.xz": "6facf6686308af39ff29c9aad192aa563652cbc697e4d7a43935ee9f965ffc8a", - "dist/2022-05-20/rust-std-beta-arm-unknown-linux-gnueabi.tar.gz": "c77e94254c7236ec9127f3dda57845ce6f7162569d6d124d72ce6d41c10268e0", - "dist/2022-05-20/rust-std-beta-arm-unknown-linux-gnueabi.tar.xz": "772c7569d1da63842a2f6a851f9aa0adfbd9499b3596e77e76d82ac93099adb3", - "dist/2022-05-20/rust-std-beta-arm-unknown-linux-gnueabihf.tar.gz": "2dcdc29b939d651534664fcdb1653933a2500dc98ff59b90cd988fc12f4832c7", - "dist/2022-05-20/rust-std-beta-arm-unknown-linux-gnueabihf.tar.xz": "a75a25b06820990b4720a60caa9d4f4b4b5a85a34078b552c52380db4239756c", - "dist/2022-05-20/rust-std-beta-arm-unknown-linux-musleabi.tar.gz": "f75de884f9219e2cd8a233b80c1aaedea1fae5a7d7b64a899b1c067c5072005e", - "dist/2022-05-20/rust-std-beta-arm-unknown-linux-musleabi.tar.xz": "69c5795861212db53e2761319ea2d408a80aef8632d8c55748be49d648a42c85", - "dist/2022-05-20/rust-std-beta-arm-unknown-linux-musleabihf.tar.gz": "2809b4223232acaaba171f3d7551ac581ae5e5e848abaf7fcc0b859f04ccb830", - "dist/2022-05-20/rust-std-beta-arm-unknown-linux-musleabihf.tar.xz": "94d389e8bec1bd6037dc1dfcd2758aee3d831ca037827018779a4da5e07dec53", - "dist/2022-05-20/rust-std-beta-armebv7r-none-eabi.tar.gz": "589e78687bafb13eb5ae1140c21a23b26fb549671c97ecde5ba8bd1549508ae0", - "dist/2022-05-20/rust-std-beta-armebv7r-none-eabi.tar.xz": "e9a81de6ceca0c0a38135e42a0ab92ab05275b594f9c03422c613f09d754054c", - "dist/2022-05-20/rust-std-beta-armebv7r-none-eabihf.tar.gz": "5805e2f656f1d5aca95977d82dcf4d08f073e3639c965d35df8e74785c29f158", - "dist/2022-05-20/rust-std-beta-armebv7r-none-eabihf.tar.xz": "64baad7526366882ae4aa9b837c9949b8382e2affdecd5dc514aea141a755804", - "dist/2022-05-20/rust-std-beta-armv5te-unknown-linux-gnueabi.tar.gz": "be7e91e7c96d2e6c7c11677f6abbc92e6efd16941a5307baaa1d16b91d527fbd", - "dist/2022-05-20/rust-std-beta-armv5te-unknown-linux-gnueabi.tar.xz": "bdb77d554f7971dbc2a42ddeb6ca4104344ef00dd803e099898ff0c70c47d165", - "dist/2022-05-20/rust-std-beta-armv5te-unknown-linux-musleabi.tar.gz": "fa12aaf9db48d22dd3e2dd025a1738badf92ecb0659ebbbf9a530f909ce569fa", - "dist/2022-05-20/rust-std-beta-armv5te-unknown-linux-musleabi.tar.xz": "c9eb5998f89efb8bafa247a36b9377e6df06a6e0532bc3c231893d9917840180", - "dist/2022-05-20/rust-std-beta-armv7-linux-androideabi.tar.gz": "cb0d6f97d5f688d2e027e325af383274cddd78a890363dd78234cd249f33a274", - "dist/2022-05-20/rust-std-beta-armv7-linux-androideabi.tar.xz": "82491be82ab194aa8f7138985b0f071036c717b012f45c366b01d2d176b8b700", - "dist/2022-05-20/rust-std-beta-armv7-unknown-linux-gnueabi.tar.gz": "2805da58cbeb8254184bf652e2bc761bd20affd083473538da90386259885901", - "dist/2022-05-20/rust-std-beta-armv7-unknown-linux-gnueabi.tar.xz": "d04641e9efee308dc9348ab0a10fc297e9c2e1981dd683285b4b908279e07b94", - "dist/2022-05-20/rust-std-beta-armv7-unknown-linux-gnueabihf.tar.gz": "6c1db32221e1b75495de1730e7aa4c705cea0849bb5ce8ff297dc7cbe2cb22c6", - "dist/2022-05-20/rust-std-beta-armv7-unknown-linux-gnueabihf.tar.xz": "c7acf447bbb3ed25c7d97558787496987c9df8e628629b2ddb5bf47407af6bf1", - "dist/2022-05-20/rust-std-beta-armv7-unknown-linux-musleabi.tar.gz": "32446694a280adde3224466f0b0d8dfeb88cee5d480f51ef324847189526ac87", - "dist/2022-05-20/rust-std-beta-armv7-unknown-linux-musleabi.tar.xz": "43c54c38c7cf200d0cf7c0c9319ef0f1a21dcd700e0c1230dcd144e15361833e", - "dist/2022-05-20/rust-std-beta-armv7-unknown-linux-musleabihf.tar.gz": "c036a956f0db31aa089e1da0cc9deda358bc2ec3f6cad02061ba7e44e03c426c", - "dist/2022-05-20/rust-std-beta-armv7-unknown-linux-musleabihf.tar.xz": "90eee1c9a8150542beb429f910219e9eecd1b77672b29c5319b070fa5b6595bf", - "dist/2022-05-20/rust-std-beta-armv7a-none-eabi.tar.gz": "7472b16814ce29a30af4be48c0ec2711e590999521d1a519a6f12168beddff7c", - "dist/2022-05-20/rust-std-beta-armv7a-none-eabi.tar.xz": "2d01cd24d609f3f0d4d126dc4a966b0360144ba0234776e3586bf466a8878627", - "dist/2022-05-20/rust-std-beta-armv7r-none-eabi.tar.gz": "25a2f1bf856274a899fef8579a8b6efa816333fc054fe3e05e0e5d344d35977b", - "dist/2022-05-20/rust-std-beta-armv7r-none-eabi.tar.xz": "63bf6e02d710511d0f3aba7b692d5f5f66a670ea78922310f5469bf4027b4ea6", - "dist/2022-05-20/rust-std-beta-armv7r-none-eabihf.tar.gz": "0077251287e4ba5941744ce767a13c7223488488d6351ed22edb272c7d4f0153", - "dist/2022-05-20/rust-std-beta-armv7r-none-eabihf.tar.xz": "8d516d72d1315350b977057ba16aaccfce5ceeb7a5038e12071c60bb108f0b64", - "dist/2022-05-20/rust-std-beta-asmjs-unknown-emscripten.tar.gz": "7b722a519009706c966c4eb6174fba5e858066040cbe72f6f85241c2b5ad0fdb", - "dist/2022-05-20/rust-std-beta-asmjs-unknown-emscripten.tar.xz": "446bf5b91e4a8cfa88b788dedb273d9f315603c6db635df35c137a860406709c", - "dist/2022-05-20/rust-std-beta-i586-pc-windows-msvc.tar.gz": "b800024142e8239741e6ae2ed2ce04221699e4c688ed57cdddad4e71acc7f70b", - "dist/2022-05-20/rust-std-beta-i586-pc-windows-msvc.tar.xz": "de369ed404dc314d13ee852330718fa0a5166a255cccc7475636d5568e39398f", - "dist/2022-05-20/rust-std-beta-i586-unknown-linux-gnu.tar.gz": "bda798e76de2751674b02c5621d077bc0d6988d97be6943e348ad69eaedf5626", - "dist/2022-05-20/rust-std-beta-i586-unknown-linux-gnu.tar.xz": "990e63391addba79972b5cfcc8fb3a9a5ddaa6bde69816e3f55844d1923306f8", - "dist/2022-05-20/rust-std-beta-i586-unknown-linux-musl.tar.gz": "2400768ca0b4324d1a4fff2c9333296729b62beae4ea818ab63994e8850c6a7e", - "dist/2022-05-20/rust-std-beta-i586-unknown-linux-musl.tar.xz": "6ccfc6fff1738d3622f6395205dc3665f604bf91812683cdba51f72df0a81c01", - "dist/2022-05-20/rust-std-beta-i686-linux-android.tar.gz": "4511c2edf4df83a10b5953737f5e048072b0c1419a49bddd8518a5866026c3cd", - "dist/2022-05-20/rust-std-beta-i686-linux-android.tar.xz": "d22d2cb39b861dcec63d3c0f0a46367e0c4a3dee03fae2fad8f8311ce38b72dd", - "dist/2022-05-20/rust-std-beta-i686-pc-windows-gnu.tar.gz": "df4abe458226a5812bfcc382e82d1c1432bbbf4c14501121397eb26b2f1b37d8", - "dist/2022-05-20/rust-std-beta-i686-pc-windows-gnu.tar.xz": "4416d4704bdfa42213434f8b1272a4ca20ea461be0f15de581e2e79af8837ec4", - "dist/2022-05-20/rust-std-beta-i686-pc-windows-msvc.tar.gz": "8ff11e61449c5a4e7395f9caa803057ac630259532efb666921a279bd32e09ed", - "dist/2022-05-20/rust-std-beta-i686-pc-windows-msvc.tar.xz": "d31c0cfec27086ffb2f257b204eb6fb2d8950c73383137be5590ad39e3473d5e", - "dist/2022-05-20/rust-std-beta-i686-unknown-freebsd.tar.gz": "0461fda259436063bbb4605c6c933bf07650091e745e0e435f0033f315177a70", - "dist/2022-05-20/rust-std-beta-i686-unknown-freebsd.tar.xz": "7c781c344b2d11a46fbfa5166645b8d851d7d7d1a8552b53cea8ee0c09098a9a", - "dist/2022-05-20/rust-std-beta-i686-unknown-linux-gnu.tar.gz": "2cb9052d6a9e5cadde06c45dc97e2fac06f6aaa92a04cf83599944d8f8eb2d63", - "dist/2022-05-20/rust-std-beta-i686-unknown-linux-gnu.tar.xz": "3a17856fd2c95553e0cb38619dac7417d9aa09d2062ed20aa230425e41351126", - "dist/2022-05-20/rust-std-beta-i686-unknown-linux-musl.tar.gz": "cff1e6bf0f2d959d7ae18975e0f453b801eba70a9f1e28929628e57e5fbe3c98", - "dist/2022-05-20/rust-std-beta-i686-unknown-linux-musl.tar.xz": "27507f85b579e2cf6f405d45b5efd91719d4d13cfb2244b81a198b6fe1eca9a9", - "dist/2022-05-20/rust-std-beta-mips-unknown-linux-gnu.tar.gz": "b5f0992efce6efda759f2a05c2f87218c3831d26ef1a30629bfc047be07a252a", - "dist/2022-05-20/rust-std-beta-mips-unknown-linux-gnu.tar.xz": "125ada363a57b69def167673791877213128fac96ca07c48b812922c8032797b", - "dist/2022-05-20/rust-std-beta-mips-unknown-linux-musl.tar.gz": "d0ecdf9b14faeaaa1260bcabe76c4b0f6e7b6b81d5efb920fa7d0ff4c2ca3320", - "dist/2022-05-20/rust-std-beta-mips-unknown-linux-musl.tar.xz": "5b5b4df31260e89ad4e3f927c1999e716b6b47a6cccb9e4e9cc8728afabe8af8", - "dist/2022-05-20/rust-std-beta-mips64-unknown-linux-gnuabi64.tar.gz": "03c9e0df29ac2dc87ad5f10f1e4ca8e1faca86e9db1e14dc111ec6466c18e3d9", - "dist/2022-05-20/rust-std-beta-mips64-unknown-linux-gnuabi64.tar.xz": "71e3e3f092c20a782873f0ccab896c825985dd37382d431b19be104356772a1b", - "dist/2022-05-20/rust-std-beta-mips64-unknown-linux-muslabi64.tar.gz": "a3d5b7d50d3df53072de703a86e45f7d933449eaaba1da5d99ec62432746d4fe", - "dist/2022-05-20/rust-std-beta-mips64-unknown-linux-muslabi64.tar.xz": "0281d7f8325ada1b46ce077dd1466a0dc60e3ed2fdbc187d3e3d709fe1971fba", - "dist/2022-05-20/rust-std-beta-mips64el-unknown-linux-gnuabi64.tar.gz": "6a88c79fd895450425f110346c9edea479602179d743b52870e5de63d136fe5a", - "dist/2022-05-20/rust-std-beta-mips64el-unknown-linux-gnuabi64.tar.xz": "57648390e7a58188cf53578733ae7e6b56171457e1f733ab53f2b33817201a90", - "dist/2022-05-20/rust-std-beta-mips64el-unknown-linux-muslabi64.tar.gz": "1367e998ddfe049f0c7127076c934000aae07739af264b7a42932b216c968a79", - "dist/2022-05-20/rust-std-beta-mips64el-unknown-linux-muslabi64.tar.xz": "08eea3c826005e9c0f3017c71200e25c360dc72906e14a1460692230557b40d0", - "dist/2022-05-20/rust-std-beta-mipsel-unknown-linux-gnu.tar.gz": "1c39e3d2296a35c9ffe50cdacc804ae6c8f2cfa07b1fcb62bd054fa6b5ed8d79", - "dist/2022-05-20/rust-std-beta-mipsel-unknown-linux-gnu.tar.xz": "0390c75c7e685ba962698a1499cdd4f4bdaa5557a3e1c18f978d9741906841b2", - "dist/2022-05-20/rust-std-beta-mipsel-unknown-linux-musl.tar.gz": "913baebce845df4e6f31904be1bd983a677fefdcab37b60e1dd3dd2ae8e8154c", - "dist/2022-05-20/rust-std-beta-mipsel-unknown-linux-musl.tar.xz": "327d3fbe131028aee1c29ea3372e0cf38a4eb8ef34d536efc7f804c6d5f40ab6", - "dist/2022-05-20/rust-std-beta-nvptx64-nvidia-cuda.tar.gz": "38800fe3874563ca61643fb3782c54e369d6731454520e1245f24daf60f6acbd", - "dist/2022-05-20/rust-std-beta-nvptx64-nvidia-cuda.tar.xz": "23a497126301502347dc35a75cef01f31fe994879b04862b571432e1549be85b", - "dist/2022-05-20/rust-std-beta-powerpc-unknown-linux-gnu.tar.gz": "2bb6b51cbd83f3cc14e00bdc2133a14e0abe735cad30f7e1b001535784f98dd5", - "dist/2022-05-20/rust-std-beta-powerpc-unknown-linux-gnu.tar.xz": "02894b90eaed0ae7712c3818498800a0da089969c3f9ff21d309aab6e47e857f", - "dist/2022-05-20/rust-std-beta-powerpc64-unknown-linux-gnu.tar.gz": "d889d93be28ee0b28832543691a15c2849726ec87dc3fccaea9465f7447f176f", - "dist/2022-05-20/rust-std-beta-powerpc64-unknown-linux-gnu.tar.xz": "c980f3a1d45cca85fe32123dd142776d4b6684ca1625f6e1d249ac5d8ea27d6d", - "dist/2022-05-20/rust-std-beta-powerpc64le-unknown-linux-gnu.tar.gz": "d3e8359eb9a35ac442a613f6fd82e8d5c9d681e8af7063798227eaab3e72604d", - "dist/2022-05-20/rust-std-beta-powerpc64le-unknown-linux-gnu.tar.xz": "eea426cb15d15a0eb06e9c3b0e2e96cd2626c9f50d2b185c0c99d5aebc9bd3a5", - "dist/2022-05-20/rust-std-beta-riscv32i-unknown-none-elf.tar.gz": "d0974d9b70b464ae3172c15e8fb304424b591d7f06dbbf49137a80819ae7334f", - "dist/2022-05-20/rust-std-beta-riscv32i-unknown-none-elf.tar.xz": "30bc0890da242ea54cfd498cd45c0616d3c1c812b92a149ac10881e53d976295", - "dist/2022-05-20/rust-std-beta-riscv32imac-unknown-none-elf.tar.gz": "6c33e98b2bc61aedd5eda2a321f4e7e94709709c450fe0958197cdc82b2810ae", - "dist/2022-05-20/rust-std-beta-riscv32imac-unknown-none-elf.tar.xz": "43cabe1ab3c37c4d62286c0e9ed34eb736c63d9fb4c36199965b10b20ca80b85", - "dist/2022-05-20/rust-std-beta-riscv32imc-unknown-none-elf.tar.gz": "59ff30ca51024a6e1bba2171ec48af591acb03359200a0c1affe7834e02052aa", - "dist/2022-05-20/rust-std-beta-riscv32imc-unknown-none-elf.tar.xz": "5d1ae0d7fac3f2b0e5192faddbd7c78a1a8c08faa056750625043513bc6235fe", - "dist/2022-05-20/rust-std-beta-riscv64gc-unknown-linux-gnu.tar.gz": "86a083dd8ac10659b70db9fdf6d26b4d4c17a170582ae42d58d88840e75baf17", - "dist/2022-05-20/rust-std-beta-riscv64gc-unknown-linux-gnu.tar.xz": "284144e4c8bb3dcfbbc67274b78db1a9bd0945bac757b99b2bcd1c365d7fb020", - "dist/2022-05-20/rust-std-beta-riscv64gc-unknown-none-elf.tar.gz": "0f3c7ee9df5a967f1cee60a41c5f0e6e52f47c30b47f2e0b55efb0c05c0817fe", - "dist/2022-05-20/rust-std-beta-riscv64gc-unknown-none-elf.tar.xz": "4ca5336d556f9b925731f1f39bc644f7393faeedf6abedce2ed0cd30736051d0", - "dist/2022-05-20/rust-std-beta-riscv64imac-unknown-none-elf.tar.gz": "37e9f9dae9ef0fea6bb223d62cb4090549a8f0ea8e316729204de87e120a46f9", - "dist/2022-05-20/rust-std-beta-riscv64imac-unknown-none-elf.tar.xz": "295bd6649e36489b14851002f082621cb5f2eaa7a1ab99dc7553413f50ff9e48", - "dist/2022-05-20/rust-std-beta-s390x-unknown-linux-gnu.tar.gz": "e0eb8ed3f1e078a2b0061f3f73add38a7a5d977d2c1545d1d1c6b7432efccbfb", - "dist/2022-05-20/rust-std-beta-s390x-unknown-linux-gnu.tar.xz": "3e119885f8d9d72e3cfeacca1c0bcd734000a61d0b3336d3010ee306650f78c9", - "dist/2022-05-20/rust-std-beta-sparc64-unknown-linux-gnu.tar.gz": "ecd2046ead142d3629a5a0316e56dc03df3cc9e995fb1ab9e347d0dd2f563ee7", - "dist/2022-05-20/rust-std-beta-sparc64-unknown-linux-gnu.tar.xz": "4288ee173cf81a72b4f9a45360734bdb8c880de7899cbe0c990ff3ec1cb2ec5a", - "dist/2022-05-20/rust-std-beta-sparcv9-sun-solaris.tar.gz": "4a7090a8d82f1f2c46437ad38c2659deac691c2fd179bd47ecdecdfac57a72ea", - "dist/2022-05-20/rust-std-beta-sparcv9-sun-solaris.tar.xz": "17daaaf6e17a237a8d4effc1ba09e50feeebbe21dced1f89249dc116abc141ff", - "dist/2022-05-20/rust-std-beta-thumbv6m-none-eabi.tar.gz": "7a7bf1342c8ab564ea29f7745515c0272435704ba1f9bc56875fbdb957286231", - "dist/2022-05-20/rust-std-beta-thumbv6m-none-eabi.tar.xz": "5ec32ef9e0633f78c5f4f74c7e572749c523c8e294fd0c3b012925ee871a2cff", - "dist/2022-05-20/rust-std-beta-thumbv7em-none-eabi.tar.gz": "36ff832f4c190ceb2f5d241ca45dc3137fe0dc1c111fa70d310908e1ecfcad86", - "dist/2022-05-20/rust-std-beta-thumbv7em-none-eabi.tar.xz": "dcbf2a0e4da89ef8fd60b9e334c3d6964e795a949cdcdbe90bf5624124979076", - "dist/2022-05-20/rust-std-beta-thumbv7em-none-eabihf.tar.gz": "299b6c26d623babb5720962b5b08a7495514373646bfcfe25f32f1118a149d05", - "dist/2022-05-20/rust-std-beta-thumbv7em-none-eabihf.tar.xz": "dcd19b9b8d52acaf36281d1927aea01b581c62d6575ed8913b01822cb36f73b1", - "dist/2022-05-20/rust-std-beta-thumbv7m-none-eabi.tar.gz": "0f81c759b3843994f01e00e86f0fb17f203be11d085e6e118e0032215cad0366", - "dist/2022-05-20/rust-std-beta-thumbv7m-none-eabi.tar.xz": "ef240ba96fc9c1cfc87e49d562d34e323bbd2b703ad72416189d588800993798", - "dist/2022-05-20/rust-std-beta-thumbv7neon-linux-androideabi.tar.gz": "9e6f2fbd877f3549caf65a7bee05dc338939775b9df3e55b3261aa56ebb783be", - "dist/2022-05-20/rust-std-beta-thumbv7neon-linux-androideabi.tar.xz": "23e81f67930983344401785226c5e52f02986b8d2cefc580cbe3a39727e8c190", - "dist/2022-05-20/rust-std-beta-thumbv7neon-unknown-linux-gnueabihf.tar.gz": "1a34d653ada70fa611e159d4ceec689884ba1a5f4c44822d0175c7a7a37a7de3", - "dist/2022-05-20/rust-std-beta-thumbv7neon-unknown-linux-gnueabihf.tar.xz": "eee5b5c5a686f8de92535cd291c0ecd7ec861033460ae2f2dd047025acb10f27", - "dist/2022-05-20/rust-std-beta-thumbv8m.base-none-eabi.tar.gz": "56cfde72d635c72648d6bac79a7a9dbd1621474804df82b23cd6e4b3df327f6d", - "dist/2022-05-20/rust-std-beta-thumbv8m.base-none-eabi.tar.xz": "105a3991cd8d9013b22d5bb6bd9d8bb1a95597341c042985a589390219a1cb22", - "dist/2022-05-20/rust-std-beta-thumbv8m.main-none-eabi.tar.gz": "0ae3c43289f939fc8d0fe365bc1bd17e3adaa05942c4e6f65e989de925bff5e5", - "dist/2022-05-20/rust-std-beta-thumbv8m.main-none-eabi.tar.xz": "be973d27b5a73ea40b60a8e1b281323ac557d35d0f20b69eceecd89c98b6a8a7", - "dist/2022-05-20/rust-std-beta-thumbv8m.main-none-eabihf.tar.gz": "8630bf9e2082512441961ba0e970dcf1a2cec2b957938be3e671cabbd98fc5e3", - "dist/2022-05-20/rust-std-beta-thumbv8m.main-none-eabihf.tar.xz": "ff33377187bdafd55ef8eae0a10255a306e7e0ad06f8326c26495169e7099a6c", - "dist/2022-05-20/rust-std-beta-wasm32-unknown-emscripten.tar.gz": "a6b50581a4269fb83accc468f5f6fc697ecb0060852f3c1aca347465bd9631f4", - "dist/2022-05-20/rust-std-beta-wasm32-unknown-emscripten.tar.xz": "1a9b35e8270048be5e44ec318669acff1c1348d5086f43d67d230be7089db920", - "dist/2022-05-20/rust-std-beta-wasm32-unknown-unknown.tar.gz": "bb01aef0726534fd606456e38fc999c6683555bf8fadf1a5f390491a8a288b22", - "dist/2022-05-20/rust-std-beta-wasm32-unknown-unknown.tar.xz": "36b0f7c5bd3ba18e1a32dead937fe0bb3d28c864e2aa3d4bab4bee61ea6730a8", - "dist/2022-05-20/rust-std-beta-wasm32-wasi.tar.gz": "188265a7ef61ce9c3676ff28edce226196945b681f6ad333837759a82a2a608c", - "dist/2022-05-20/rust-std-beta-wasm32-wasi.tar.xz": "5abb86cfe2be1d1b631f33b7601dd66d9a0f7aa01a37c88b3eafabf49bab84a5", - "dist/2022-05-20/rust-std-beta-x86_64-apple-darwin.tar.gz": "b605e10547a5a82375030606986f8ca69c4c03e87526a6eb4ef967ed173d36b0", - "dist/2022-05-20/rust-std-beta-x86_64-apple-darwin.tar.xz": "70274d4a46996db65c40cf2391d162fe09426b1c1aeaa988f48bdcc39740cad3", - "dist/2022-05-20/rust-std-beta-x86_64-apple-ios.tar.gz": "494b20caa398346eddd66a3df6f10601d96dac4204c7a235823e4627534111d4", - "dist/2022-05-20/rust-std-beta-x86_64-apple-ios.tar.xz": "1c62f0df4b9b7661c4dab30f501bf01956934480d0d47bc9d0be591e2c73c8be", - "dist/2022-05-20/rust-std-beta-x86_64-fortanix-unknown-sgx.tar.gz": "4083489fecd16a34541670a2df9e5182fc0a15b6204d0a9af973676e691e49a6", - "dist/2022-05-20/rust-std-beta-x86_64-fortanix-unknown-sgx.tar.xz": "5a65b9d25d04e7d0fbbadd188fbb013fb1034fe273e2b85cebaeb6aaebe06ec6", - "dist/2022-05-20/rust-std-beta-x86_64-fuchsia.tar.gz": "447eff000d01bff74a4da75b12317979adb07e21a6a81c35170f5d9e7dda8419", - "dist/2022-05-20/rust-std-beta-x86_64-fuchsia.tar.xz": "34e6f5225985d454d55f9c22828ab46cd560c7108e259a6aac0e9932d079c7b2", - "dist/2022-05-20/rust-std-beta-x86_64-linux-android.tar.gz": "67478f922ba588f4f0e0fcff23e254115898266bcb8868ccec8494ee680af6f5", - "dist/2022-05-20/rust-std-beta-x86_64-linux-android.tar.xz": "08c3330a0b25365e8c7404119def5ca630a370e832a0dd62c54fd2409be96650", - "dist/2022-05-20/rust-std-beta-x86_64-pc-solaris.tar.gz": "e293bed46bf31439f8a87eff36046a12c439b1f6f8c7a67030b44523999b39b2", - "dist/2022-05-20/rust-std-beta-x86_64-pc-solaris.tar.xz": "0e03e0c918cdaf94a33ad8225b483e4174085239ebe406d906a4cb95b44d227d", - "dist/2022-05-20/rust-std-beta-x86_64-pc-windows-gnu.tar.gz": "73d66833913d4606453b89b7f72b5b4c417c9baaa09b854c6217441b5d8893f8", - "dist/2022-05-20/rust-std-beta-x86_64-pc-windows-gnu.tar.xz": "6500d80a332e27d235d562dee7d48a0baf05876595d813818f46de61ef75f60a", - "dist/2022-05-20/rust-std-beta-x86_64-pc-windows-msvc.tar.gz": "80459e06662ca8789ec35793832b0df912b51ede0a62c46f52a3fd2a94bc6488", - "dist/2022-05-20/rust-std-beta-x86_64-pc-windows-msvc.tar.xz": "14a073ddedcfa34ecca58e53467ef874fbed4eb10003f3b2663f49c77890418c", - "dist/2022-05-20/rust-std-beta-x86_64-sun-solaris.tar.gz": "f3939d1e526f9cd8e1114ce9f4521c563d4e4b43f2f6889c292b2e02bba79c0b", - "dist/2022-05-20/rust-std-beta-x86_64-sun-solaris.tar.xz": "65ec686465eb4d2b3013da46cc83f1f80cddcdb70d8449d423464368c024881b", - "dist/2022-05-20/rust-std-beta-x86_64-unknown-freebsd.tar.gz": "878f6de25e6934c91138a2257b81338a0da4a83dd8233d2ceff2e26e9bad8bad", - "dist/2022-05-20/rust-std-beta-x86_64-unknown-freebsd.tar.xz": "ffab6364f6af477b074774a9e1915636f07b0659231c61bb7c75cbde31277986", - "dist/2022-05-20/rust-std-beta-x86_64-unknown-illumos.tar.gz": "52b0580aa5a036526100b6032e104f1f790c1b7346494ca44f017cd8957aff07", - "dist/2022-05-20/rust-std-beta-x86_64-unknown-illumos.tar.xz": "58da0d760adc61b63d72851ae602927ac9c71795df103a6b6342f210425eb5dc", - "dist/2022-05-20/rust-std-beta-x86_64-unknown-linux-gnu.tar.gz": "53e3312b8f96723319f791d54a3215d427fefaa353485bd7940e1ffd875bdeb2", - "dist/2022-05-20/rust-std-beta-x86_64-unknown-linux-gnu.tar.xz": "0194620a7501c555d157b37759b1d97c35a78a5561cb3859688ceb12184e0636", - "dist/2022-05-20/rust-std-beta-x86_64-unknown-linux-gnux32.tar.gz": "17939ba3d5aaed0e79246378bdb2694e830b02b4c56941f7cca30400d3213d09", - "dist/2022-05-20/rust-std-beta-x86_64-unknown-linux-gnux32.tar.xz": "1acd94d6881951001ace4bf76c46775199097710064d3a0da03cd5979d23bcc8", - "dist/2022-05-20/rust-std-beta-x86_64-unknown-linux-musl.tar.gz": "bdcd08dc5dff810b28ca466e4984f1ef2e8f079d233d1b9933ac719b9a2e5a14", - "dist/2022-05-20/rust-std-beta-x86_64-unknown-linux-musl.tar.xz": "d7629d65c4908a7a74aedac7f7fa52c2308dcfcd6c8e541a0fa418dff3304152", - "dist/2022-05-20/rust-std-beta-x86_64-unknown-netbsd.tar.gz": "02c2e64930f37200125415e7212577cf25dbd5c76929bc629313e856960beb68", - "dist/2022-05-20/rust-std-beta-x86_64-unknown-netbsd.tar.xz": "2fecb5336a79c62cf1e17df7d65604c3df19b8cc9c490a2fc918dac1ab843989", - "dist/2022-05-20/rust-std-beta-x86_64-unknown-none.tar.gz": "b37f013037673d8f405900170d3c5c94476946df6c6eaea9e3f98354e05ffb22", - "dist/2022-05-20/rust-std-beta-x86_64-unknown-none.tar.xz": "53d4a5aaebc4a8fa39ac5157a90dc80ee168df51b70f21e01c26b20d00df94dd", - "dist/2022-05-20/rust-std-beta-x86_64-unknown-redox.tar.gz": "d7e8ef1e4655bcfed48081cd59b78d08585b9c9141601128efb8081ec908f2f8", - "dist/2022-05-20/rust-std-beta-x86_64-unknown-redox.tar.xz": "8117ed18c3742af2c9f193458540b700d2eaeb98c7774b52942fca3a605e98f9", - "dist/2022-05-20/rustc-beta-aarch64-apple-darwin.tar.gz": "5da43198c82b323534fd7163e202daa6256dcd2ce1c6001f07f1746c43738216", - "dist/2022-05-20/rustc-beta-aarch64-apple-darwin.tar.xz": "35fe159afe40b969f948590313be24f3c626e6dfe53211dcc57ca63d930903b9", - "dist/2022-05-20/rustc-beta-aarch64-pc-windows-msvc.tar.gz": "878aecc6259747dbdb64b62eb741ab4c77215475b5ba2ab707be772f33c65370", - "dist/2022-05-20/rustc-beta-aarch64-pc-windows-msvc.tar.xz": "e43637e5ec68302e6d652b1296fa86b5dd0d3163298ad7db298b2185d2faebad", - "dist/2022-05-20/rustc-beta-aarch64-unknown-linux-gnu.tar.gz": "496ff30ba1820bbb27d62307e1e74352dfe39fdce5be1abe96370df059507131", - "dist/2022-05-20/rustc-beta-aarch64-unknown-linux-gnu.tar.xz": "ff679573cac7cc417ee90773e378453a41f5a67ee422957d03293e90c7ccd0b7", - "dist/2022-05-20/rustc-beta-aarch64-unknown-linux-musl.tar.gz": "8440a56c20b9f999e577c30c04bf57500b1faa5f4d6794cdf94682202d072f41", - "dist/2022-05-20/rustc-beta-aarch64-unknown-linux-musl.tar.xz": "318569c2e30ec047f870727f849d07e21133f04ce9d9f6ef71b6db91745102db", - "dist/2022-05-20/rustc-beta-arm-unknown-linux-gnueabi.tar.gz": "ef226baa0d484a8a4426570f8556e50ea0d6cebe4cd8662b78cdaa6b32645712", - "dist/2022-05-20/rustc-beta-arm-unknown-linux-gnueabi.tar.xz": "7aeb63e2390fe4043a047bf1309f9e39dcbe7745540fbdff4572b24d5e084ea8", - "dist/2022-05-20/rustc-beta-arm-unknown-linux-gnueabihf.tar.gz": "30f65131a29bb094eba2d8d7171fa6da8159d4d8f33af6f930b605119e393563", - "dist/2022-05-20/rustc-beta-arm-unknown-linux-gnueabihf.tar.xz": "70555b5fe9ef11d6aeda526832a187be3e37cbffe9757b2d0690f2c0673057ba", - "dist/2022-05-20/rustc-beta-armv7-unknown-linux-gnueabihf.tar.gz": "55d7031a9e47b9b782c4ab2c8c4b2c4fe98c44eab6b0c059236a1d1c8dcfd0b8", - "dist/2022-05-20/rustc-beta-armv7-unknown-linux-gnueabihf.tar.xz": "cef673c540259008168a8f23bb8a6574196f4ba8b802c07f5474f6fe733667bd", - "dist/2022-05-20/rustc-beta-i686-pc-windows-gnu.tar.gz": "8598a985340414f8176728d79d6ef602fb3283668b2bc3f1e8b3933e8cb25030", - "dist/2022-05-20/rustc-beta-i686-pc-windows-gnu.tar.xz": "2df61a11a8f688a4f3bdb7298f3a7e929a2c737295414c033405e5bf55522729", - "dist/2022-05-20/rustc-beta-i686-pc-windows-msvc.tar.gz": "280894eb39a07ef35c2eb76fab8e77b25b54bbcf4a03a49e21edc528a14912a4", - "dist/2022-05-20/rustc-beta-i686-pc-windows-msvc.tar.xz": "01260ef26a28c21a76187cd84a7d1195137d3f871d51e559422dd017f8cc6920", - "dist/2022-05-20/rustc-beta-i686-unknown-linux-gnu.tar.gz": "ce35952f8a49a4f2706e8fbb62e21d5419f90058b66b057e669f69c522bfbca8", - "dist/2022-05-20/rustc-beta-i686-unknown-linux-gnu.tar.xz": "32dc234a4dacdddd80cd23c9e64d2f45b1854651493958f0789b3ea58800d9b8", - "dist/2022-05-20/rustc-beta-mips-unknown-linux-gnu.tar.gz": "e5b1f27084d8082840fa76222e48b1a55c28209f100cf55769375e72ee5f7298", - "dist/2022-05-20/rustc-beta-mips-unknown-linux-gnu.tar.xz": "8a56067a0c6910ccc822f87b7eb0f12834d00c9840e9a937928a519093ed5041", - "dist/2022-05-20/rustc-beta-mips64-unknown-linux-gnuabi64.tar.gz": "fc51757845b46433ff6a53a2a783df1810072a456c9611c7eb24ccd97a99845c", - "dist/2022-05-20/rustc-beta-mips64-unknown-linux-gnuabi64.tar.xz": "1c29e7f1519275a88a48ad2687e9368e4633f9bbc6b1467dd064000a6315163d", - "dist/2022-05-20/rustc-beta-mips64el-unknown-linux-gnuabi64.tar.gz": "29cab4f76a3b2c916280eefd8a72b9b9014174b2de8cd62f18add7207f387821", - "dist/2022-05-20/rustc-beta-mips64el-unknown-linux-gnuabi64.tar.xz": "eb234b6bc941757ad31f5f4ae08083846101697dd8ff2ccb6f62a728eeb0a4b1", - "dist/2022-05-20/rustc-beta-mipsel-unknown-linux-gnu.tar.gz": "107d59c38607e0b0c4853d08b5a05e1e7dfa01a1ea42eae88180b27d0cade79e", - "dist/2022-05-20/rustc-beta-mipsel-unknown-linux-gnu.tar.xz": "248a58d873bf4aa9872ebd7b1d903f84f713266abfa40c2f24b2a2125247f2b1", - "dist/2022-05-20/rustc-beta-powerpc-unknown-linux-gnu.tar.gz": "1b91a2ccae1eaf8654d5338aff78c630bed772b6960349dd54b71a769e1fb7da", - "dist/2022-05-20/rustc-beta-powerpc-unknown-linux-gnu.tar.xz": "4cd2421996965d58cd1318761301b2a5b9ae852f5518091a27eb64818f5b6982", - "dist/2022-05-20/rustc-beta-powerpc64-unknown-linux-gnu.tar.gz": "c892a97b55f6f67803f23f1a59fe084a06f31973cb8ee244836c00210a323095", - "dist/2022-05-20/rustc-beta-powerpc64-unknown-linux-gnu.tar.xz": "774aec0f0543255e948ce3aac921b7d1eff054aabe5478c285e08312b4fb0023", - "dist/2022-05-20/rustc-beta-powerpc64le-unknown-linux-gnu.tar.gz": "deb42e8f3e18206fc4795829e13f68be17ef7074196fe4880addce40adbb2825", - "dist/2022-05-20/rustc-beta-powerpc64le-unknown-linux-gnu.tar.xz": "502b33478bdc56ff705ef4001c59017f6a7057f370d388b42ca697aeef696b3e", - "dist/2022-05-20/rustc-beta-riscv64gc-unknown-linux-gnu.tar.gz": "4bd2e1d502b9f0b6bb1672c94c54650e63b3b28845be4a7148f6a15e062a4c95", - "dist/2022-05-20/rustc-beta-riscv64gc-unknown-linux-gnu.tar.xz": "51fd5c0841d6f9881a6f1fdc3b261a085eac64a5521546f2b18756cae4472e15", - "dist/2022-05-20/rustc-beta-s390x-unknown-linux-gnu.tar.gz": "209fe3fbf4632517921723e67857c1697e6cb0c8b56ecd8678205909b586c156", - "dist/2022-05-20/rustc-beta-s390x-unknown-linux-gnu.tar.xz": "27c66acc0c71d232d0c43ad15a8953b34dfadb87073727eb1b574b1debabb9f8", - "dist/2022-05-20/rustc-beta-x86_64-apple-darwin.tar.gz": "bfb46c4a6864fde3b4edf3500713d423404ef39ba8849b229e823adda5a638a0", - "dist/2022-05-20/rustc-beta-x86_64-apple-darwin.tar.xz": "bce0d4dcd41b8a4d79718238355b0fe682b83620ebaf4a134fe5b7e7c2620c32", - "dist/2022-05-20/rustc-beta-x86_64-pc-windows-gnu.tar.gz": "6c281db4eaa67c74bd07e56efff6fe63e750aa9a5dbd92edbc86c68f69964381", - "dist/2022-05-20/rustc-beta-x86_64-pc-windows-gnu.tar.xz": "5c4f1bd38095e9c34c5357a76fa5090bf82a030fcc1b18a2935b9fabf02f9f57", - "dist/2022-05-20/rustc-beta-x86_64-pc-windows-msvc.tar.gz": "0e4e6b6c236cf3ed4c5de5ad909f060bba6ba9fc41aa3d5bbe72d90a7a3c8976", - "dist/2022-05-20/rustc-beta-x86_64-pc-windows-msvc.tar.xz": "a526b05166251ddc646961388e24827c05b86e7d61d8cbd0015f6a98b742f9ea", - "dist/2022-05-20/rustc-beta-x86_64-unknown-freebsd.tar.gz": "1cd1d3a1a37bca47f7a00182e5c0a08275091a8d36771504a84052c1a72dec4a", - "dist/2022-05-20/rustc-beta-x86_64-unknown-freebsd.tar.xz": "460aa68d922df97fac6d6052a8680d514fd4ce32fca7c44ae22d7c05e0c5b51f", - "dist/2022-05-20/rustc-beta-x86_64-unknown-illumos.tar.gz": "d992c3d0b088d359dafce1ce143e698b81c5bd49c9537e035ad8734fae7ba671", - "dist/2022-05-20/rustc-beta-x86_64-unknown-illumos.tar.xz": "28234a4d0417b1d7bb112775fc3827115777d288a6c40628d234f2724c94a8ba", - "dist/2022-05-20/rustc-beta-x86_64-unknown-linux-gnu.tar.gz": "169a34b8288c5cb9d79c225a6b890d936942ceda046823b50ffc8c0ba6dc9d1f", - "dist/2022-05-20/rustc-beta-x86_64-unknown-linux-gnu.tar.xz": "9a4963614650e4f3d7a24f4e89f100aeb96d8faca3ab9e912fc66d92364c50db", - "dist/2022-05-20/rustc-beta-x86_64-unknown-linux-musl.tar.gz": "493ac76b6e2324a4c0ffc7136f22a6b5c651bd464b240814e4de42d2d52db737", - "dist/2022-05-20/rustc-beta-x86_64-unknown-linux-musl.tar.xz": "f430f5eb951d367543f65ed9fdb7de2bca8e8f06b6f7c10c8a97a35f9787ca39", - "dist/2022-05-20/rustc-beta-x86_64-unknown-netbsd.tar.gz": "ae878bc9dc0d7788d2098cdbf5b564a624b1bc1419f8c0d574f5fc3a0cb13511", - "dist/2022-05-20/rustc-beta-x86_64-unknown-netbsd.tar.xz": "de65cd47cb84cc446121cf85af77e8f50e8e3ce82db1fc66c88686334b8541a8", - "dist/2022-05-20/rustfmt-nightly-aarch64-apple-darwin.tar.gz": "016ff92402d8095a9a58e82dbe435fe5b8f64ff63ecdbc8b48968f10f8c94947", - "dist/2022-05-20/rustfmt-nightly-aarch64-apple-darwin.tar.xz": "7c2c2d3a6cae8633d0013312a1dcf24e583261ff88f582760df81c298d848cb0", - "dist/2022-05-20/rustfmt-nightly-aarch64-pc-windows-msvc.tar.gz": "e27dde14fd9bf882e8714628de56e9877c56d31d889c7d2ea03713cc8158a4ff", - "dist/2022-05-20/rustfmt-nightly-aarch64-pc-windows-msvc.tar.xz": "b58836984c2fd54054fe436fc49cbd7570bf6b1534ef030acf29e3cc4c70d58e", - "dist/2022-05-20/rustfmt-nightly-aarch64-unknown-linux-gnu.tar.gz": "33dacee51735139ace6af54c853304ef2d9f3917eaf5c84ebb69ca3555d23c42", - "dist/2022-05-20/rustfmt-nightly-aarch64-unknown-linux-gnu.tar.xz": "2ea9b4e7a0fc641b1fe54b21c415277e43df9d7a958b0c3b02f60b38a06c8ebe", - "dist/2022-05-20/rustfmt-nightly-aarch64-unknown-linux-musl.tar.gz": "829ca9581d19adbaad12a77d1e318bd5d08daefc928c6c6a48f3b5276039b518", - "dist/2022-05-20/rustfmt-nightly-aarch64-unknown-linux-musl.tar.xz": "e9a8030c2a065da4e0ba61b57747cd8dd40cd3d4bfcf8ab5873618620dcdd07c", - "dist/2022-05-20/rustfmt-nightly-arm-unknown-linux-gnueabi.tar.gz": "e2e389076858a5fdf02c85d036b07c3fbdeddf1b526de8d8e72223241cf2f5c7", - "dist/2022-05-20/rustfmt-nightly-arm-unknown-linux-gnueabi.tar.xz": "21df340cc4741e1b6265f67e8068e81e255fab82f1c18070b24245e52022753d", - "dist/2022-05-20/rustfmt-nightly-arm-unknown-linux-gnueabihf.tar.gz": "681b47f3e5cdead36f12ca8af4b996d4aa90e4ca471c604de13faa70ca22258b", - "dist/2022-05-20/rustfmt-nightly-arm-unknown-linux-gnueabihf.tar.xz": "e842733f877c401f55924fa1c5c608087aef9901c79664afd4bbb53e6af9e46e", - "dist/2022-05-20/rustfmt-nightly-armv7-unknown-linux-gnueabihf.tar.gz": "7c43e97e824fcb2595b416f50cf3bfd6930f3fd066e8d27673db478ec87667d1", - "dist/2022-05-20/rustfmt-nightly-armv7-unknown-linux-gnueabihf.tar.xz": "fa13900df7709c8258d7e2ecfd5d9d4a620af957604d2544f5114ce9333961b7", - "dist/2022-05-20/rustfmt-nightly-i686-pc-windows-gnu.tar.gz": "7378857f9d524eff3fa81f7724b687e7b53f686c22bc40825bb9df06e5fc2652", - "dist/2022-05-20/rustfmt-nightly-i686-pc-windows-gnu.tar.xz": "6c4cc08f7474e3415b78dd5f3c7554b6af7af3e9c0143cef24dd2803b19bfa24", - "dist/2022-05-20/rustfmt-nightly-i686-pc-windows-msvc.tar.gz": "b75b7226c3601d6e3c701ebe4e53f042754d9bf37ed933548093a2de782b4e7e", - "dist/2022-05-20/rustfmt-nightly-i686-pc-windows-msvc.tar.xz": "628ee041610c8f70a7e033cf5f997cee0974dfebefbd2867a4b55aad0e72ecad", - "dist/2022-05-20/rustfmt-nightly-i686-unknown-linux-gnu.tar.gz": "62e1293032535dd706efea3ed395da3756ab2db74b1eb1aa12333f9d3cdcbe20", - "dist/2022-05-20/rustfmt-nightly-i686-unknown-linux-gnu.tar.xz": "0b4bb25aabe8915ef3e3ef5822dea1ce55ea3f07e2196552abe058df91600722", - "dist/2022-05-20/rustfmt-nightly-mips-unknown-linux-gnu.tar.gz": "aa80e17777a3b5eeb94bb14fd42df24dc0a7fd01d5b497c8ea904e2f8990ab20", - "dist/2022-05-20/rustfmt-nightly-mips-unknown-linux-gnu.tar.xz": "a18cd7d9bfc9b51ea3cf722a4b6da3897bbf29710bb837bce2a493601210c749", - "dist/2022-05-20/rustfmt-nightly-mips64-unknown-linux-gnuabi64.tar.gz": "5b50d88dcede9527a133352a0af57609f5ab035e5080298bc6e4472dd8def994", - "dist/2022-05-20/rustfmt-nightly-mips64-unknown-linux-gnuabi64.tar.xz": "5f7c9544eb83dedce2c0f34fa4492b68453a49ce69dcae6d20b23e4f5658b674", - "dist/2022-05-20/rustfmt-nightly-mips64el-unknown-linux-gnuabi64.tar.gz": "d8282c23352c4a84da032af5286e7d4dd478c721efab1a87a0c6d78d5b810cb3", - "dist/2022-05-20/rustfmt-nightly-mips64el-unknown-linux-gnuabi64.tar.xz": "8b6137beebe10ada8c152edd6d2e59c8e348b79cddd72d55704e65375bfc1363", - "dist/2022-05-20/rustfmt-nightly-mipsel-unknown-linux-gnu.tar.gz": "5ee13136a127ede81125cfbf3cb5a5e01f4c628f6905964253555ba93abd7d68", - "dist/2022-05-20/rustfmt-nightly-mipsel-unknown-linux-gnu.tar.xz": "44732a16066b78ff12c87d09bd4e409630c16e89f6666e4d0feb4fac7291610c", - "dist/2022-05-20/rustfmt-nightly-powerpc-unknown-linux-gnu.tar.gz": "c5c4246bda76e04f9f6e0d2bd6b9d0697da91a5714b5bbcd20f005f51c2133ba", - "dist/2022-05-20/rustfmt-nightly-powerpc-unknown-linux-gnu.tar.xz": "62aed94d82667d952a5199549d92e10ef3b0fa0fca50cca1e1ef8148939de7a4", - "dist/2022-05-20/rustfmt-nightly-powerpc64-unknown-linux-gnu.tar.gz": "5cabed546a4e47408870815df117d1679eb55498d124d74ba59ce5d3a2365856", - "dist/2022-05-20/rustfmt-nightly-powerpc64-unknown-linux-gnu.tar.xz": "27eadfa90c307e32b7bde08935a3d3f6710fe2c134138f8972e73d52fd42f2dc", - "dist/2022-05-20/rustfmt-nightly-powerpc64le-unknown-linux-gnu.tar.gz": "d0b9466a62f79e00000e53dd23889ce148b157b2450b9cdcf072fa1d0ef0d9c5", - "dist/2022-05-20/rustfmt-nightly-powerpc64le-unknown-linux-gnu.tar.xz": "b18b418cdc40a46020ed4b4bdc001d1f53d564e31b2d7163c4b8d4c2b0858cda", - "dist/2022-05-20/rustfmt-nightly-riscv64gc-unknown-linux-gnu.tar.gz": "b1ebacd2f47471dcbb2d4503de85cb89f30182842ca985aad152ca7d58ed990f", - "dist/2022-05-20/rustfmt-nightly-riscv64gc-unknown-linux-gnu.tar.xz": "caad69f3c84bab683907252a9c50b7d54ac61062282e3eb5c5033f2bb8611cac", - "dist/2022-05-20/rustfmt-nightly-s390x-unknown-linux-gnu.tar.gz": "afd79b45aaebafaeb4de5a8e018549e5d21f37e1aa025943103264ac011296c6", - "dist/2022-05-20/rustfmt-nightly-s390x-unknown-linux-gnu.tar.xz": "7a7c5e50b4423800f489386f1c049190a79a34e472aee932193f32577321d94e", - "dist/2022-05-20/rustfmt-nightly-x86_64-apple-darwin.tar.gz": "7d85e16802a0c38ce2beac5ca01f9921e9ca1df5bc413bfc8d129143228bdda9", - "dist/2022-05-20/rustfmt-nightly-x86_64-apple-darwin.tar.xz": "7ebb79d71ed525e6324ea7e1840fa88c76a37e8082ada2a02532aff696b2623a", - "dist/2022-05-20/rustfmt-nightly-x86_64-pc-windows-gnu.tar.gz": "823bba430cd01425c207e1ad58689b1c79143d4365dce40322c59462d658f3ab", - "dist/2022-05-20/rustfmt-nightly-x86_64-pc-windows-gnu.tar.xz": "13b92baa7393f6f2a2e6743366189a6518f2233de98a09c3d7a1f4e3159214e7", - "dist/2022-05-20/rustfmt-nightly-x86_64-pc-windows-msvc.tar.gz": "ee9407a567b12a4fa6b0c596d1a775d45d016badec8f9e73ef66ff324aba0d87", - "dist/2022-05-20/rustfmt-nightly-x86_64-pc-windows-msvc.tar.xz": "7cd8f5b0a256574c04b4a4b79e19a53899f89884c3f34b11ee6352be89ced09a", - "dist/2022-05-20/rustfmt-nightly-x86_64-unknown-freebsd.tar.gz": "9a40bee5b8ef9305de4075595ccb9b698574cd8ca4d355b7474ea7009f7e924e", - "dist/2022-05-20/rustfmt-nightly-x86_64-unknown-freebsd.tar.xz": "80a5d830e5e2750aa9b1c5e46cc1f97910473cca0ff20a93a5b81d5c664431d0", - "dist/2022-05-20/rustfmt-nightly-x86_64-unknown-illumos.tar.gz": "b3e45e2b6b984838dd156bc00d0d9178793d1c7a895fa016bd18f1c15fb65111", - "dist/2022-05-20/rustfmt-nightly-x86_64-unknown-illumos.tar.xz": "dfbba7787c57cf47b75033b81523de52c1be3072a1f68564e9bf5f93378d18a1", - "dist/2022-05-20/rustfmt-nightly-x86_64-unknown-linux-gnu.tar.gz": "913000f2bd4787ebf301d7d0b80cd480d4afd362f3728c9886ef898b0286575f", - "dist/2022-05-20/rustfmt-nightly-x86_64-unknown-linux-gnu.tar.xz": "7ebc5f8f6fccb5eab1eeffb724baf320ffebb653bce813841115b7e67144b2c1", - "dist/2022-05-20/rustfmt-nightly-x86_64-unknown-linux-musl.tar.gz": "6a4550b5a5dd7d91f9767954c8a7fab31e3a782d34d524823f1add8679b19a26", - "dist/2022-05-20/rustfmt-nightly-x86_64-unknown-linux-musl.tar.xz": "b3e9ab1bd65ca0957235f1ce946c7893a5c1ff4276193ccb1763819ae1e053b0", - "dist/2022-05-20/rustfmt-nightly-x86_64-unknown-netbsd.tar.gz": "b52a56a4195e41496b9a96ea41a05f9fa27b3c47851ae3aafffbd37711a522f2", - "dist/2022-05-20/rustfmt-nightly-x86_64-unknown-netbsd.tar.xz": "accd31a4772443dfa87121f30f501a53cf8f2be5553b1d7fcdf0405d2baf2149" + "dist/2022-06-29/cargo-beta-aarch64-apple-darwin.tar.gz": "8e50ef7a6fbc0e7212621e124de66d123b9c772a04cdb04b5528cb68543f89d0", + "dist/2022-06-29/cargo-beta-aarch64-apple-darwin.tar.xz": "f74e110c8740321406acde67c37fc3dbb47e9d98e25bf20f5ad19790b89b9b9c", + "dist/2022-06-29/cargo-beta-aarch64-pc-windows-msvc.tar.gz": "14067f4013c5e112531ee4f76e7ba61149b46a67d1d8bf0256dc2ee1410f44c9", + "dist/2022-06-29/cargo-beta-aarch64-pc-windows-msvc.tar.xz": "9252a221a244308228a16f5e9729755d9f09421e2e316ea82f64da1d9a8c4725", + "dist/2022-06-29/cargo-beta-aarch64-unknown-linux-gnu.tar.gz": "38c0b9186fb251a6ac15ced667d3cd719e81acc0eb7a92303c6422c92b701842", + "dist/2022-06-29/cargo-beta-aarch64-unknown-linux-gnu.tar.xz": "b328753578ecb5ca9578f9ac89107804249eb4f802ca0f07c9bdd063aab931b5", + "dist/2022-06-29/cargo-beta-aarch64-unknown-linux-musl.tar.gz": "747d836695e7a385e6af22911966f72410abafe8b400b33690804e4290e750ee", + "dist/2022-06-29/cargo-beta-aarch64-unknown-linux-musl.tar.xz": "94cb8c5e70ba4da6de86777c3c2092ab0616da9d12fbff6928e901fd6c48c099", + "dist/2022-06-29/cargo-beta-arm-unknown-linux-gnueabi.tar.gz": "d3fa253a3a470d65f726dd59201c3b6e90e8d2343d3b5a1d27ba395d16ebe025", + "dist/2022-06-29/cargo-beta-arm-unknown-linux-gnueabi.tar.xz": "84f4684cb6e86e58279b768e8cc00c55da09a0ee8cdad77dfe4153748eaa3b60", + "dist/2022-06-29/cargo-beta-arm-unknown-linux-gnueabihf.tar.gz": "58c3faea04e4a21425555afa5486e2f7704c8e5d5773cda73d618b1049e0575d", + "dist/2022-06-29/cargo-beta-arm-unknown-linux-gnueabihf.tar.xz": "6b16b89b4e7b3ca9ba6ca7b0ae881aeb7c81a450ff4f32eca3d0907aadf10fd1", + "dist/2022-06-29/cargo-beta-armv7-unknown-linux-gnueabihf.tar.gz": "eb504aea2b96402b371e7b7bba7cbc5fdeb9f470be70927b11a340b5937513be", + "dist/2022-06-29/cargo-beta-armv7-unknown-linux-gnueabihf.tar.xz": "c78dba1f0c58a7e8817ee9d5ddeb377e087432a1375ea3d99ee27b4a9f7d0ba2", + "dist/2022-06-29/cargo-beta-i686-pc-windows-gnu.tar.gz": "4d29aed70bd5df7525c8c8e8d88cdabee235c229821a9adba08c38a3a7e3b967", + "dist/2022-06-29/cargo-beta-i686-pc-windows-gnu.tar.xz": "2fdb9c3c42a3c97d3f8eec7b0e4bcd7a6db24abdf928d51a3c645f24aa7e41a4", + "dist/2022-06-29/cargo-beta-i686-pc-windows-msvc.tar.gz": "afdb95f020eb318ea66b3150593787ead14f1e8590ab950bec5516d1641c39da", + "dist/2022-06-29/cargo-beta-i686-pc-windows-msvc.tar.xz": "f1156f6f02262d12c777cee11d02b9c5cf9b4f28a27f4f9de9c154a8843d3d4b", + "dist/2022-06-29/cargo-beta-i686-unknown-linux-gnu.tar.gz": "aa972fcd1411e69464233fc54f34ac09aa04eb593410c7345718495e2ba684f9", + "dist/2022-06-29/cargo-beta-i686-unknown-linux-gnu.tar.xz": "ffa60e4ef87e7bb7229be6cd14f562d652e30e5badaa5892c0a7bc9563c56fbe", + "dist/2022-06-29/cargo-beta-mips-unknown-linux-gnu.tar.gz": "cb827715805de35449a17b190e1cb978bcd7d8b0a5501fe06d8f4313dce5b06d", + "dist/2022-06-29/cargo-beta-mips-unknown-linux-gnu.tar.xz": "63bc1122b296a89371d4a3560c06e1ce2f3a00482879d0ded87bd52f87fdec9e", + "dist/2022-06-29/cargo-beta-mips64-unknown-linux-gnuabi64.tar.gz": "b4d4222040865e4aa1d034f85511f436e08a1502c5213b6eacaf103d417755c6", + "dist/2022-06-29/cargo-beta-mips64-unknown-linux-gnuabi64.tar.xz": "e1d19f8de4278c01914d3999038c49001c214ab9ec5286beab327322d30fb564", + "dist/2022-06-29/cargo-beta-mips64el-unknown-linux-gnuabi64.tar.gz": "b82d0a96510ca9933540bd8fc1534a1f91f92f92512a018b10cc007240ea13f1", + "dist/2022-06-29/cargo-beta-mips64el-unknown-linux-gnuabi64.tar.xz": "e4805b270f9763adef25a0f970d28d2d69a92ddd9ab6d7f14fa746ad61b4e635", + "dist/2022-06-29/cargo-beta-mipsel-unknown-linux-gnu.tar.gz": "f3f9ed7f57299511610bf0d44abc79d9a0cf994c979546895b9a42b72b17734f", + "dist/2022-06-29/cargo-beta-mipsel-unknown-linux-gnu.tar.xz": "08c1c3cef4f257841f9600bfe2f67312cd76fbeca1e4326963715ca77668a0eb", + "dist/2022-06-29/cargo-beta-powerpc-unknown-linux-gnu.tar.gz": "1a1bba0cb974217cbff68001c83270c631f13193b5e3227f22a8b32613f7d570", + "dist/2022-06-29/cargo-beta-powerpc-unknown-linux-gnu.tar.xz": "cb32c1d4addc20433b15751db0da67cef5bcc576c17319bd79566596c153af80", + "dist/2022-06-29/cargo-beta-powerpc64-unknown-linux-gnu.tar.gz": "7b6713071c93bdbb68f80f4045deaa8078382abe3179c60c92e0de5a0d93f161", + "dist/2022-06-29/cargo-beta-powerpc64-unknown-linux-gnu.tar.xz": "313e6b05c3178b7e481ab09b71c1491b7136a47a9577649506823bdc698b279d", + "dist/2022-06-29/cargo-beta-powerpc64le-unknown-linux-gnu.tar.gz": "0d7d4dc600ff03857b60767c50a79c0de8a0a6a78ef3f309121b8338583526c5", + "dist/2022-06-29/cargo-beta-powerpc64le-unknown-linux-gnu.tar.xz": "4b7d7da12ffe1ee279db21f6ef5b6124330ccee03711f3801561f68b303e15c0", + "dist/2022-06-29/cargo-beta-riscv64gc-unknown-linux-gnu.tar.gz": "154938148945148682bd165836e503064c248752cb24f1437d20a3ad128d6c91", + "dist/2022-06-29/cargo-beta-riscv64gc-unknown-linux-gnu.tar.xz": "be4c8a5b14fa9db00ad2f8efac052bbd6f7981610baf692b1d01f3bfb3be96f4", + "dist/2022-06-29/cargo-beta-s390x-unknown-linux-gnu.tar.gz": "9ed70575f47e5a6bec063ed19eff165e35efbf6941403def15e48bf6560b949a", + "dist/2022-06-29/cargo-beta-s390x-unknown-linux-gnu.tar.xz": "ad90bd85638cf26ecd72ffc0b09d1384c64fb990b4aa62f69e39d205609ba06f", + "dist/2022-06-29/cargo-beta-x86_64-apple-darwin.tar.gz": "54f71eff8e1ad3d22f49106b2c7b04713e7927a3f54cfc452c61e810e2b57129", + "dist/2022-06-29/cargo-beta-x86_64-apple-darwin.tar.xz": "b3f136e3d2bd5776887fb0071bc6434a1eb2cd42fccfe95eb8a32ca1bd36de29", + "dist/2022-06-29/cargo-beta-x86_64-pc-windows-gnu.tar.gz": "e57239d7d3b889ec4dad8db20bbaa0140a2f0a471ab62e4a1c48558490f33d36", + "dist/2022-06-29/cargo-beta-x86_64-pc-windows-gnu.tar.xz": "4f14c69c15e3038508df42e254027f0b59ed798cc26f0952fcaa8068341fb55b", + "dist/2022-06-29/cargo-beta-x86_64-pc-windows-msvc.tar.gz": "2898e0a9dc793fe85835b8167b8e4e4cd4d0b044fff37a85034624a92a8e8f76", + "dist/2022-06-29/cargo-beta-x86_64-pc-windows-msvc.tar.xz": "667a8a268fda0c44878498b2c68239bfe7387d9d8f9d39ec4445a79409e65a1a", + "dist/2022-06-29/cargo-beta-x86_64-unknown-freebsd.tar.gz": "da4ab4baae0f241653591c0f69091724ac8949b18e261c69069ff368f86e76b3", + "dist/2022-06-29/cargo-beta-x86_64-unknown-freebsd.tar.xz": "333295a07edac2f7aa9acec4284c3f2417ec764a9c09e8735ebbb69621d80aa5", + "dist/2022-06-29/cargo-beta-x86_64-unknown-illumos.tar.gz": "3b0899c1cdeebe01d8dabf5d0cd4f9762c07012e874111c77909840f917295d0", + "dist/2022-06-29/cargo-beta-x86_64-unknown-illumos.tar.xz": "ad698922172524912ecba24c966df6bdf18a21e530c2467d835c297709f1f413", + "dist/2022-06-29/cargo-beta-x86_64-unknown-linux-gnu.tar.gz": "f9efa10a31e31857644ecd8877b08ae96f80962bc96efbb374128220d659c2c5", + "dist/2022-06-29/cargo-beta-x86_64-unknown-linux-gnu.tar.xz": "5392a4bc11097ac95e208c9cea7b0773b966f713f3b1e0ba42f1323484b1d27c", + "dist/2022-06-29/cargo-beta-x86_64-unknown-linux-musl.tar.gz": "a6177b8b69eb5d4bd3507d50054009734854775f8821b74b6ad603cda1e0b351", + "dist/2022-06-29/cargo-beta-x86_64-unknown-linux-musl.tar.xz": "33a00ce744789c49438fe8accf40a17c99282339ca69adc7a3e8a810cad9f1f0", + "dist/2022-06-29/cargo-beta-x86_64-unknown-netbsd.tar.gz": "4b042e30402804c20abd84b39384b0b7d88743d27a9f0a34f90d7626f07a4f47", + "dist/2022-06-29/cargo-beta-x86_64-unknown-netbsd.tar.xz": "2e9fe2e92129a3952f1ae32760fd818a637b829a575194b84ab6d793d74c2c04", + "dist/2022-06-29/rust-std-beta-aarch64-apple-darwin.tar.gz": "031b3c2134e2c54aeb29ba2e46a5b6db11c65ff3a364cedd14c79d741a1f9ddc", + "dist/2022-06-29/rust-std-beta-aarch64-apple-darwin.tar.xz": "55f82ac681d5c8b6f0777939e747e8856707822e34b3060e9a85ec5935c8a406", + "dist/2022-06-29/rust-std-beta-aarch64-apple-ios-sim.tar.gz": "53cc84de66c0c70b988b6136aa55c4051e51d27952e67db066ea409d56166fbb", + "dist/2022-06-29/rust-std-beta-aarch64-apple-ios-sim.tar.xz": "6e9fa64aa157eb32e3ea4deb8d42256e5bbfee5fd4dae111f107033d792d28ad", + "dist/2022-06-29/rust-std-beta-aarch64-apple-ios.tar.gz": "d0e27984f1a2133af4e2fe9fd79a22f3e8a792a81111a496f80cfd9f3019b5e0", + "dist/2022-06-29/rust-std-beta-aarch64-apple-ios.tar.xz": "404780fc534501fbdd6fb34aeb3f338086feadebfef420a9530c6c4b48b803bb", + "dist/2022-06-29/rust-std-beta-aarch64-fuchsia.tar.gz": "bdafb54b1798812a0144029c421cc784a441ee82fc433f5788712f2c05fe4391", + "dist/2022-06-29/rust-std-beta-aarch64-fuchsia.tar.xz": "198be344c4a1c4247d8fb21efd9c84787272c0ae6208b341cae508adb8ba0ca4", + "dist/2022-06-29/rust-std-beta-aarch64-linux-android.tar.gz": "9c51ebdba4c211050cc8c6733e21faec7d7fb2591abb38226b0593f449d7e8b2", + "dist/2022-06-29/rust-std-beta-aarch64-linux-android.tar.xz": "f97595685703d22b0689b3f2822b3f69780eefc74a3169fdd1cf1d9a4538342d", + "dist/2022-06-29/rust-std-beta-aarch64-pc-windows-msvc.tar.gz": "2c32867f2e8ef81d1a8b0b3af14055be79f1da6dfe514155c9f9fd1eb98a99bb", + "dist/2022-06-29/rust-std-beta-aarch64-pc-windows-msvc.tar.xz": "bfc34e4077ece9675ed044a0e518bf8c38d0f351b62b6ea0d674f0c77c7af671", + "dist/2022-06-29/rust-std-beta-aarch64-unknown-linux-gnu.tar.gz": "547505e533d6654d33df44e362cb421ea8fc69458efe51a357afc3665e19c826", + "dist/2022-06-29/rust-std-beta-aarch64-unknown-linux-gnu.tar.xz": "f14478bd5bc6fea393111cd6f2dbbd1bc5a8d50adf0faa95b6d804c882d30415", + "dist/2022-06-29/rust-std-beta-aarch64-unknown-linux-musl.tar.gz": "ed17ac700cb1e4e773fd832c59aec036cebad714009786fec422077af35336e8", + "dist/2022-06-29/rust-std-beta-aarch64-unknown-linux-musl.tar.xz": "32b670e1e29d50c8af4ec0647b34855a07f9ab7a0142305a6a629cd4124c067e", + "dist/2022-06-29/rust-std-beta-aarch64-unknown-none-softfloat.tar.gz": "225d33281ca9c69c3cdea76714e0383ae543c4f778859dd63cdd37dac09fa9d4", + "dist/2022-06-29/rust-std-beta-aarch64-unknown-none-softfloat.tar.xz": "d55f5260e2c50a608f760d50e7fa653284f2a8b8a64588a80dfb13419061b014", + "dist/2022-06-29/rust-std-beta-aarch64-unknown-none.tar.gz": "3719244c77c4d5870accfe562f30a9dc3290a14dc3da399e64909402d116c482", + "dist/2022-06-29/rust-std-beta-aarch64-unknown-none.tar.xz": "78bb343bb519070c0761ea7ed3c4e56b6d821095ac931ad7f812743600dffb64", + "dist/2022-06-29/rust-std-beta-arm-linux-androideabi.tar.gz": "452973239e8c0995a8b9522417e020b883f2f4052764b18b8cd50c9d08cb4f14", + "dist/2022-06-29/rust-std-beta-arm-linux-androideabi.tar.xz": "b1952ef69d1c4c32bc0aad4b4beddc6e6bd56155eafce1ffcaafceff8cb6d77d", + "dist/2022-06-29/rust-std-beta-arm-unknown-linux-gnueabi.tar.gz": "c1ad87f6a2f4e1bc1eb2f732285546fb062faad9b27c4dc248ff174e4a2ec60e", + "dist/2022-06-29/rust-std-beta-arm-unknown-linux-gnueabi.tar.xz": "ef6611b0ee43efdfc0a27dc3a7b65eeb8cba0d10624233fb473d521392c7d3f4", + "dist/2022-06-29/rust-std-beta-arm-unknown-linux-gnueabihf.tar.gz": "4efd4c3e06a3bc3c2f873901a956827e69cecfd38ed62ba1d8cfaf979d6a67e6", + "dist/2022-06-29/rust-std-beta-arm-unknown-linux-gnueabihf.tar.xz": "2c99a7541c6ca5b1c1fad00e76736e74d7ae50af3cd891aeed8f4f8747d4292d", + "dist/2022-06-29/rust-std-beta-arm-unknown-linux-musleabi.tar.gz": "3d5c2be1e0e5b4ce33e2aa4765e869872b247709db1b194512d12146be439c80", + "dist/2022-06-29/rust-std-beta-arm-unknown-linux-musleabi.tar.xz": "e0b7e25f78e29a62d05eec6220000bcee815bcda24d857225ae47fcf3612fcf9", + "dist/2022-06-29/rust-std-beta-arm-unknown-linux-musleabihf.tar.gz": "0639d8e52de274f02f34ca547a2c692defb329bae290a4ee977b05e9a3deca52", + "dist/2022-06-29/rust-std-beta-arm-unknown-linux-musleabihf.tar.xz": "256a4ddafddacad0024be539cb038e7742b37f34038a774a06e9a43b29558d5a", + "dist/2022-06-29/rust-std-beta-armebv7r-none-eabi.tar.gz": "468113b22041adf0b7746838643ee316063f6049c20d499aa52ac2d9241091ce", + "dist/2022-06-29/rust-std-beta-armebv7r-none-eabi.tar.xz": "5b614aa0b7a360a8ee79bb0dca0b2adc3cc0b8f4f2266806bfb0d07b811c11d0", + "dist/2022-06-29/rust-std-beta-armebv7r-none-eabihf.tar.gz": "d13f0a0abcc35bf6ccd035ba9bdd5b0760b995c885902bae73cf8a22cddc847e", + "dist/2022-06-29/rust-std-beta-armebv7r-none-eabihf.tar.xz": "c7ffd2f6df10e754480bb1cb84b823084cf95cb6bbae2017437d5b9ffcd90b77", + "dist/2022-06-29/rust-std-beta-armv5te-unknown-linux-gnueabi.tar.gz": "ad94a6356dbee95031bd943212eedc441d596cb11da1206010cef611e436975f", + "dist/2022-06-29/rust-std-beta-armv5te-unknown-linux-gnueabi.tar.xz": "b8c78492bb88d317580d01e96a70d9eb42d2f9f8396806bd810e348706924d25", + "dist/2022-06-29/rust-std-beta-armv5te-unknown-linux-musleabi.tar.gz": "cd09bcb2d9d9fa25ddbcc81d9bf2ed2e68a177a1d61e1f9611516c95ca4f5e3e", + "dist/2022-06-29/rust-std-beta-armv5te-unknown-linux-musleabi.tar.xz": "efd2795a1484cd7331cbd849757a3b6cdbd50ae466bff760d9ec8e7ff965536f", + "dist/2022-06-29/rust-std-beta-armv7-linux-androideabi.tar.gz": "10ac8daf897263a1c51f0ed9df13f707261048c6d11e7a024470ba71c3d3ef34", + "dist/2022-06-29/rust-std-beta-armv7-linux-androideabi.tar.xz": "3968db993db3c861856dfa0974207b0709fba871cc17bc857c29f59063af15e5", + "dist/2022-06-29/rust-std-beta-armv7-unknown-linux-gnueabi.tar.gz": "33d19cbc173f71771b7a00a009789eef8f0b2cf65072642e0689bb86b191df4c", + "dist/2022-06-29/rust-std-beta-armv7-unknown-linux-gnueabi.tar.xz": "e896810ee1322ed011d662678839161e7c39faa27f1a8af963bc0a1e3b40a88f", + "dist/2022-06-29/rust-std-beta-armv7-unknown-linux-gnueabihf.tar.gz": "d6b81169c6b77b7b93e03ac2d8289539e7ce6436106709f63b79a195b98d6fe8", + "dist/2022-06-29/rust-std-beta-armv7-unknown-linux-gnueabihf.tar.xz": "6db5dfcdb0bba850db005a11e76cb3750befde0b6ef03b600c3c0e67a4c5d46a", + "dist/2022-06-29/rust-std-beta-armv7-unknown-linux-musleabi.tar.gz": "5a729bb3471ccd07de54ca8fbc570fb617d4ba059a620754becc7aa48620f092", + "dist/2022-06-29/rust-std-beta-armv7-unknown-linux-musleabi.tar.xz": "deb76d6f0bb0e4c9931df9976e869dcfc2548a851a06db89d656856bcab4fa8a", + "dist/2022-06-29/rust-std-beta-armv7-unknown-linux-musleabihf.tar.gz": "464bcf3a881d107747e241f88e71361dc5cabe7c27fe0e0f370c7ef90f8b77ad", + "dist/2022-06-29/rust-std-beta-armv7-unknown-linux-musleabihf.tar.xz": "0b66291a56ea5b7aa6b194fcf08d844a067940a3ec4cac11a377c87947a5cf4e", + "dist/2022-06-29/rust-std-beta-armv7a-none-eabi.tar.gz": "583e0b2e03386dcc0397dec2802659937e73dad04a52263218128ee2bab8c412", + "dist/2022-06-29/rust-std-beta-armv7a-none-eabi.tar.xz": "b9ebb07f4b461cef81b5fbbb38ac89245f4df13215fc64ad04e6972c1c2d405a", + "dist/2022-06-29/rust-std-beta-armv7r-none-eabi.tar.gz": "12a5b49d776cbdb26a1a6c1e2c38d62f562cf9f99fd4868da317b08d4df1bb84", + "dist/2022-06-29/rust-std-beta-armv7r-none-eabi.tar.xz": "a1b7b2c27236e36893056dccfd9d15db906db53e8c0f931d1dfc9daa147642a0", + "dist/2022-06-29/rust-std-beta-armv7r-none-eabihf.tar.gz": "9d1f6a6694e82528a6dc98d94f63aa253c0f2eac2cf1e9db97fb1fd9d9e68f46", + "dist/2022-06-29/rust-std-beta-armv7r-none-eabihf.tar.xz": "179e6d158a2f27bca2be54059414526de20de76a9eaf26c99e01ef9b1c7743be", + "dist/2022-06-29/rust-std-beta-asmjs-unknown-emscripten.tar.gz": "eda6db1398471b8cda7b7449ba86db47587398c7b322e995039f59caabe8c815", + "dist/2022-06-29/rust-std-beta-asmjs-unknown-emscripten.tar.xz": "9a079f124309edf9a187a0980b59085f5a1cb9c94236154a9f53cd7ca67a71e9", + "dist/2022-06-29/rust-std-beta-i586-pc-windows-msvc.tar.gz": "af4a7d3da748a9f2ff867fb7e6b87e0b4696904bab60a2e38df21cf41c658ee3", + "dist/2022-06-29/rust-std-beta-i586-pc-windows-msvc.tar.xz": "420801efc6deddaaee5a7e17672e0ff520d965ece9a2b8aa1534d86ce839777b", + "dist/2022-06-29/rust-std-beta-i586-unknown-linux-gnu.tar.gz": "82d3b6bbc71b5e138f8715bfcba5107f0d1cde6aee8fe6bddaf85fa646ddf1d1", + "dist/2022-06-29/rust-std-beta-i586-unknown-linux-gnu.tar.xz": "1eba8240509d6d5d0650f7e8e42cce89246aa1d416b859db496013d83983d4bd", + "dist/2022-06-29/rust-std-beta-i586-unknown-linux-musl.tar.gz": "d846e2ea559ad467945369d8230321734cca6634b8d1a4088475f8cafc9854d8", + "dist/2022-06-29/rust-std-beta-i586-unknown-linux-musl.tar.xz": "d5d8df8255a252af0c3eb66596d42a6d6cb9fcf3036fa8ab3f85ca1f344394c0", + "dist/2022-06-29/rust-std-beta-i686-linux-android.tar.gz": "55bca00de9caed1f5443592373b8a2581b1bc1ade24bd062a8f2ba396c82e520", + "dist/2022-06-29/rust-std-beta-i686-linux-android.tar.xz": "4db58c08b4e58584bf1a38205f100e0bfe79a74a4ff00280d5a29a3367302ca3", + "dist/2022-06-29/rust-std-beta-i686-pc-windows-gnu.tar.gz": "76c72088f1d77d84270b8ad00ee87a79cc8607c852291c5d2b82f59e6efd96cd", + "dist/2022-06-29/rust-std-beta-i686-pc-windows-gnu.tar.xz": "17eb428984599dd696554d9710cec60fcb01c8d341c0e59a0c1c00370c0d9c72", + "dist/2022-06-29/rust-std-beta-i686-pc-windows-msvc.tar.gz": "9dd0184f99be287f318952ace8190af2cd7accc47a7b3f388d34c77cff60c5ae", + "dist/2022-06-29/rust-std-beta-i686-pc-windows-msvc.tar.xz": "d76d255d3db0b9a5b5e8b1670b3eff4feaed8dc938187a6783a3323fb4998b8a", + "dist/2022-06-29/rust-std-beta-i686-unknown-freebsd.tar.gz": "8f8d60ba72543402b0c62bd68192891ee290fc7daff104e9ff8b10c9d109d791", + "dist/2022-06-29/rust-std-beta-i686-unknown-freebsd.tar.xz": "030629f57e1f05c7a1e96a147f7a2086c0968a6abfecbd375f9093c4a2859fbb", + "dist/2022-06-29/rust-std-beta-i686-unknown-linux-gnu.tar.gz": "a5d01dba11d59ac1a11404905c54425594bc69f40cad8814d3ffd00d1b38c52a", + "dist/2022-06-29/rust-std-beta-i686-unknown-linux-gnu.tar.xz": "5f2ea9f7e62fb429f4f0575a267eb46a014b9ae727939f909ec5e3777e32e65b", + "dist/2022-06-29/rust-std-beta-i686-unknown-linux-musl.tar.gz": "6e76c8616ee86d1b51c9b055b324f715c1a9cbb1c1564982d1f7e6fd623cd292", + "dist/2022-06-29/rust-std-beta-i686-unknown-linux-musl.tar.xz": "54641f169e424a73cb386e41563af5ed9ba833379edc148579f67bdcdab281ba", + "dist/2022-06-29/rust-std-beta-mips-unknown-linux-gnu.tar.gz": "64303412deb9264dfd15a16341203df39af2e9206ce1d22ca5eaa83762e1f62a", + "dist/2022-06-29/rust-std-beta-mips-unknown-linux-gnu.tar.xz": "4c4cb3fb0ee51f9294cb805c7263f716a921e7d76503cbbd24f8600c485c58aa", + "dist/2022-06-29/rust-std-beta-mips-unknown-linux-musl.tar.gz": "e197dab9c9b11cf98404aed094d1d8bc03a6755ebf4046423c11baeb0143f254", + "dist/2022-06-29/rust-std-beta-mips-unknown-linux-musl.tar.xz": "81a80fa315dc3da8111f487b9dd6dbe56991276fac138de4469c0e0b688bae07", + "dist/2022-06-29/rust-std-beta-mips64-unknown-linux-gnuabi64.tar.gz": "9cc065dd7fe550716efa403c910d9eaf8c18d90d7d3e316772fac72f7f16c45f", + "dist/2022-06-29/rust-std-beta-mips64-unknown-linux-gnuabi64.tar.xz": "6bde95f6c57f6ce4de4f1ce9837b386e374eb291d8778956bee0956b150c3917", + "dist/2022-06-29/rust-std-beta-mips64-unknown-linux-muslabi64.tar.gz": "1262105c31f7ec6248b24b71f0003014a8558220444cfc88c611ad2aa94efebd", + "dist/2022-06-29/rust-std-beta-mips64-unknown-linux-muslabi64.tar.xz": "cb35ba7184ba5a74f5d6c8592e67e08faed205e091784f85137872e02541ae99", + "dist/2022-06-29/rust-std-beta-mips64el-unknown-linux-gnuabi64.tar.gz": "31d7af84b431c9185b2ef98c18eaadb957e22e427b331a8ed4ab8b2b6ae364ae", + "dist/2022-06-29/rust-std-beta-mips64el-unknown-linux-gnuabi64.tar.xz": "674b1c886ae4a2273edd6e49539d45a2a02e73874f6a65ba820dbea75d8ca8c6", + "dist/2022-06-29/rust-std-beta-mips64el-unknown-linux-muslabi64.tar.gz": "cc620438e90fbd086b4f237454b099a81e4cc3dae9582e7526b2a10648663e4c", + "dist/2022-06-29/rust-std-beta-mips64el-unknown-linux-muslabi64.tar.xz": "425ce38ad1bb048756a37e8642ab6b43f8189bee244e4ee011e95fd45f3a3747", + "dist/2022-06-29/rust-std-beta-mipsel-unknown-linux-gnu.tar.gz": "40b0df32d5df53fe8774000804738d56e7c8768cba1baaf52721a9956d62c557", + "dist/2022-06-29/rust-std-beta-mipsel-unknown-linux-gnu.tar.xz": "7df34f8ddb1b14698c6473eaaeffd5d6da23ddcde23a74a3482194e01fa5ace7", + "dist/2022-06-29/rust-std-beta-mipsel-unknown-linux-musl.tar.gz": "65b3db3bac29c8aad57c8cabe7fbe622acfdcd9221c11af4419d74c24452a939", + "dist/2022-06-29/rust-std-beta-mipsel-unknown-linux-musl.tar.xz": "9a4a382945631425fc8227d6b42d0f97988dc39c8e79646280e080595d82aa31", + "dist/2022-06-29/rust-std-beta-nvptx64-nvidia-cuda.tar.gz": "30fc151ae3a6423e027aacd70bcd45d13243aa5394ff2d6cf285c55d3c5c6e23", + "dist/2022-06-29/rust-std-beta-nvptx64-nvidia-cuda.tar.xz": "28cef1191d2181004b8e5032bc3f7b548996149dac8ffb5b8a5431b32d396683", + "dist/2022-06-29/rust-std-beta-powerpc-unknown-linux-gnu.tar.gz": "a6b79a07cdd6cd6d0e468132ab504464e3d6c41f28111cf15c6053d7d560b8b7", + "dist/2022-06-29/rust-std-beta-powerpc-unknown-linux-gnu.tar.xz": "67aa93c917f234b0b61dbd3fac21a1d6d4ef20cc8dd7fdc6a8bb8e688e3920ca", + "dist/2022-06-29/rust-std-beta-powerpc64-unknown-linux-gnu.tar.gz": "e4dd3483a85060d75a7dff95dda7a121943f1121983e5d33eff166f4c3e97e6c", + "dist/2022-06-29/rust-std-beta-powerpc64-unknown-linux-gnu.tar.xz": "36f2b7305e8ed58666c206c26e28cc5e8708fdf104f1d67dd0c692f9e36a1482", + "dist/2022-06-29/rust-std-beta-powerpc64le-unknown-linux-gnu.tar.gz": "f232913783443410614af3e27a832740b06d392563f5d0aa6d0ac0558d7bbb6f", + "dist/2022-06-29/rust-std-beta-powerpc64le-unknown-linux-gnu.tar.xz": "f54f1f0c7fe7b31ff97bde512573225f7380bd1c35876862ea798fc2b38cd4fc", + "dist/2022-06-29/rust-std-beta-riscv32i-unknown-none-elf.tar.gz": "728135a1f7c89a129c78c2adf360ab06feb79f28b10f993797d498a9effab9e9", + "dist/2022-06-29/rust-std-beta-riscv32i-unknown-none-elf.tar.xz": "ba91db121409dc9414377759fd27e8947e46dbb9f3788521d82a67b063c2a9d6", + "dist/2022-06-29/rust-std-beta-riscv32imac-unknown-none-elf.tar.gz": "c092940c2eaea9c9168061b8f5b87f1b735c1d0ffe05bc834252719c42f3ff33", + "dist/2022-06-29/rust-std-beta-riscv32imac-unknown-none-elf.tar.xz": "2906008d17bb17bc84709d8e47c8c065b2749355240e630cdb1f0c173721a05a", + "dist/2022-06-29/rust-std-beta-riscv32imc-unknown-none-elf.tar.gz": "7815f8bf5838e2f497e2d42cad55c3e738f64957e031af90f82d80fa7ce78f1a", + "dist/2022-06-29/rust-std-beta-riscv32imc-unknown-none-elf.tar.xz": "16bbac000585cc3985582698b42635d1e3af68445e2ef4340600087e1fc38e26", + "dist/2022-06-29/rust-std-beta-riscv64gc-unknown-linux-gnu.tar.gz": "2fdb717d0fa4f3e162ab8603d2b5233c6ec20a587af874d0987b1b040ea95dfa", + "dist/2022-06-29/rust-std-beta-riscv64gc-unknown-linux-gnu.tar.xz": "f4f2445d1e9f8cd0af34ce0063a44041465df0b6d5b73546595d0d37f0342087", + "dist/2022-06-29/rust-std-beta-riscv64gc-unknown-none-elf.tar.gz": "a2df1578a4ec47fb925102fd6604add216ed7d27bdf323176328afef48f2faca", + "dist/2022-06-29/rust-std-beta-riscv64gc-unknown-none-elf.tar.xz": "e3839aa18e35d7d050ce00210774a63b84b3070bc28be1d70ffd4c939b6d8cc0", + "dist/2022-06-29/rust-std-beta-riscv64imac-unknown-none-elf.tar.gz": "4ad1c23982c5d5b45935e52fc1a0e36e08e853a993a0adb5c9fb9e703ee2cb7f", + "dist/2022-06-29/rust-std-beta-riscv64imac-unknown-none-elf.tar.xz": "1308041c43eca228f265cd1cdb3d419bb7e4e1461e117536b719cc3ec8527798", + "dist/2022-06-29/rust-std-beta-s390x-unknown-linux-gnu.tar.gz": "0fdbbe00f9b655e657d93e97bd1b625afd1531249cd32d013c0a1d62e48fdbad", + "dist/2022-06-29/rust-std-beta-s390x-unknown-linux-gnu.tar.xz": "cd9120d576a533106721b11e4e457c317be7ff484613d2c7592606a379c0fb3f", + "dist/2022-06-29/rust-std-beta-sparc64-unknown-linux-gnu.tar.gz": "c570c55584f9d725c69bf092e0187dd7830839b6badc6fba62b5fbaa19b75548", + "dist/2022-06-29/rust-std-beta-sparc64-unknown-linux-gnu.tar.xz": "d3e63b5f8f139e32a40ccbc7d877714e88d68a31e1644cf4d1cc91771d5459c9", + "dist/2022-06-29/rust-std-beta-sparcv9-sun-solaris.tar.gz": "61169fbfdab7d66712f04a53d6ab8766766158a566bf606075132002a67bda0f", + "dist/2022-06-29/rust-std-beta-sparcv9-sun-solaris.tar.xz": "f137dbdf000903de091c076fd3800466097caf2f9c48e4ebae9c3072fc2aaca4", + "dist/2022-06-29/rust-std-beta-thumbv6m-none-eabi.tar.gz": "b81429647fa2fd42fa7a5b4c15d15b1595023e81a7e4289e06bd214c6666127b", + "dist/2022-06-29/rust-std-beta-thumbv6m-none-eabi.tar.xz": "4a741ba60918138ab24cac1d6fda432d38d02bbf0a22103270df13e0d40c8a86", + "dist/2022-06-29/rust-std-beta-thumbv7em-none-eabi.tar.gz": "ac20977687a1831ea2883568eac148821ad9f1ad199a9b728447f7d15f518e1e", + "dist/2022-06-29/rust-std-beta-thumbv7em-none-eabi.tar.xz": "57262c3ddf2351b80ff8dcc03fe8e16b441e1b0014c0e4534e2e493902928ea7", + "dist/2022-06-29/rust-std-beta-thumbv7em-none-eabihf.tar.gz": "be9111bfcd464b5f107642b18fc375eeea16a1d758de71cfb6258e0302c9ae7a", + "dist/2022-06-29/rust-std-beta-thumbv7em-none-eabihf.tar.xz": "63f84a900c52caac4eed1c58bbfc604e591c56e0fc1afcebe7ae832a9610c060", + "dist/2022-06-29/rust-std-beta-thumbv7m-none-eabi.tar.gz": "51f5266d9790f4e691493e403edcd664541afd448123fea3fbd1de2d50c87f1e", + "dist/2022-06-29/rust-std-beta-thumbv7m-none-eabi.tar.xz": "12f7be43c58de67c761ed17bb555509e639c31c5cc0783d9ca55e78c4586317a", + "dist/2022-06-29/rust-std-beta-thumbv7neon-linux-androideabi.tar.gz": "37f3baa3a2db1b15315915910447332bcf5b9f36666f4cc08868b551d27022cb", + "dist/2022-06-29/rust-std-beta-thumbv7neon-linux-androideabi.tar.xz": "e1f457d3da72a9989b90395692310c78c5e5fdcea35fc1bc2f450eba62b7d21d", + "dist/2022-06-29/rust-std-beta-thumbv7neon-unknown-linux-gnueabihf.tar.gz": "77a461b06eff56bc00361e9f771e0a81087fed2999e5d1f2f53632a61e90829b", + "dist/2022-06-29/rust-std-beta-thumbv7neon-unknown-linux-gnueabihf.tar.xz": "29a4f3a426e380b886bc7a468b08d2dad38ff704d74ec2f243ba5ba7720c7e9a", + "dist/2022-06-29/rust-std-beta-thumbv8m.base-none-eabi.tar.gz": "cd0285f0254f4042ee70f02ea576ec713e34ec00e2fc0309cd7c891ca26674ca", + "dist/2022-06-29/rust-std-beta-thumbv8m.base-none-eabi.tar.xz": "43dd490c8068897a5f45ee0da36ea8854496cfb54faff9f759e2795f22d46cb7", + "dist/2022-06-29/rust-std-beta-thumbv8m.main-none-eabi.tar.gz": "cea8f1a52c3829f4781c321bb43486e44ee8fc94602249d1084e8a6e9269e2ce", + "dist/2022-06-29/rust-std-beta-thumbv8m.main-none-eabi.tar.xz": "9a6b827b4958d412d4f413219458582142d1536f313d14ded54cf666a43946bf", + "dist/2022-06-29/rust-std-beta-thumbv8m.main-none-eabihf.tar.gz": "a032c778052e77eb32eef136ca431ce2bfbd6e43ba5a82e90b2ef3dd414b2cd0", + "dist/2022-06-29/rust-std-beta-thumbv8m.main-none-eabihf.tar.xz": "cb560e7b3c62bd2598e701360b11a6edb16e730700c4aa5e5d284dd1ceb570c3", + "dist/2022-06-29/rust-std-beta-wasm32-unknown-emscripten.tar.gz": "c8e3309f94e8187e41d5de922c7988d610439be3a90e06c9eab76b4a3850343d", + "dist/2022-06-29/rust-std-beta-wasm32-unknown-emscripten.tar.xz": "f1388800ff04b85fa549191a5cae8e4964baff89ddadd57fccdef85a1da99e4a", + "dist/2022-06-29/rust-std-beta-wasm32-unknown-unknown.tar.gz": "c0a18d66485400b692011d72af2226fc609eddd19fd1e95f370ed6a864f6dd8a", + "dist/2022-06-29/rust-std-beta-wasm32-unknown-unknown.tar.xz": "f3772ae732dcc6a63c2143d3530d8253b35c7412b2266ed9583d14f6000b214a", + "dist/2022-06-29/rust-std-beta-wasm32-wasi.tar.gz": "aa204e3377e1c4272c18231bcdaa439678fbb1158d794ee8b2699fbad382c828", + "dist/2022-06-29/rust-std-beta-wasm32-wasi.tar.xz": "25c90365da9be1307e4aa80f699ed14eec03bd48b8271570d9e9e9d4dd0f701d", + "dist/2022-06-29/rust-std-beta-x86_64-apple-darwin.tar.gz": "24754ac282a434638de5bd2a548b3960149b811f03422cf875a5018dfb229441", + "dist/2022-06-29/rust-std-beta-x86_64-apple-darwin.tar.xz": "0806c72137fd994acfb304039af85e028999ab941d3d95cd037f298a66377aa5", + "dist/2022-06-29/rust-std-beta-x86_64-apple-ios.tar.gz": "588bd3b637531ae3399a91e805d52481c927477d15822636714091d2371e95cf", + "dist/2022-06-29/rust-std-beta-x86_64-apple-ios.tar.xz": "27d75a39fec3ead30dca470f0f6c96561a48bffa8d22c283001f7543b0d62f0b", + "dist/2022-06-29/rust-std-beta-x86_64-fortanix-unknown-sgx.tar.gz": "b7b32388857ecd8f1f16fdd5354a9411c84c463b8b40a1ec2982d5dee11e2318", + "dist/2022-06-29/rust-std-beta-x86_64-fortanix-unknown-sgx.tar.xz": "5ea72074aedac44961823a6a8788bb7aecb905dffe2c25d52c417275be39676d", + "dist/2022-06-29/rust-std-beta-x86_64-fuchsia.tar.gz": "5f53ff113fa233161183bd1c79a946aa13770f52f08ab3d8a62a080ee2682163", + "dist/2022-06-29/rust-std-beta-x86_64-fuchsia.tar.xz": "5541a85df4ac431a14830b09bcda0d030236ea31419b1ccfdf2e761638a1c484", + "dist/2022-06-29/rust-std-beta-x86_64-linux-android.tar.gz": "d17d49d6e416941c1aeed7d145b47d2d61a7bcb563720ed5dd9b867cd0522f05", + "dist/2022-06-29/rust-std-beta-x86_64-linux-android.tar.xz": "41aa64b361c17afd7466b621923a44e80d61edefd7052e06df1eb96ee0cad3b1", + "dist/2022-06-29/rust-std-beta-x86_64-pc-solaris.tar.gz": "2527ecd6465989f54570e7ed61b51c8a00bc5e1c613e972c93b028df0ad60ec5", + "dist/2022-06-29/rust-std-beta-x86_64-pc-solaris.tar.xz": "91f243a73494de90c5250a663f111b3a999925a923cb92220d1853428e2b1aea", + "dist/2022-06-29/rust-std-beta-x86_64-pc-windows-gnu.tar.gz": "e41010c4f7bec5b06205085fba4e538cec40222c18c5d560c2a1a2f5c2d4b859", + "dist/2022-06-29/rust-std-beta-x86_64-pc-windows-gnu.tar.xz": "af8185b065f2ab37f92ec671eae1652368b26b6917e34c24f2a15779f1e447c7", + "dist/2022-06-29/rust-std-beta-x86_64-pc-windows-msvc.tar.gz": "1fc3c51f18174e07ba21bd8bb4da495540273ac3f89d2e106172bd6cbfd08ae3", + "dist/2022-06-29/rust-std-beta-x86_64-pc-windows-msvc.tar.xz": "b5ffbbda960fd38bc11bf56e154990b385940fa6fd95563feed0a403317aeca4", + "dist/2022-06-29/rust-std-beta-x86_64-sun-solaris.tar.gz": "8bc7de9a99c3eb1954a1dfd17a39629449e41d743ee85437dcc67f37ccfa9cfa", + "dist/2022-06-29/rust-std-beta-x86_64-sun-solaris.tar.xz": "919ffd2e0221c6e6125cecf5f1c21c4b03d3e98c4e1322e5ec664e4079d37fce", + "dist/2022-06-29/rust-std-beta-x86_64-unknown-freebsd.tar.gz": "fbcdbf0d7a8dc6970fadc835455a6fce455ecbdb16ec435957e19477efe94af6", + "dist/2022-06-29/rust-std-beta-x86_64-unknown-freebsd.tar.xz": "09bb9ef104f7eeaf6fae591d908a0f8cbaaf98f1a14e788f468cf99dcbecd8ce", + "dist/2022-06-29/rust-std-beta-x86_64-unknown-illumos.tar.gz": "9b0176f89bbff3c2fef94ca3731dbf9e3c079288aee88827efb42a6296ff8168", + "dist/2022-06-29/rust-std-beta-x86_64-unknown-illumos.tar.xz": "d84e40868ce185b39a0ad9a6dfc118b31cc0742b9e4e80b59944572043088f24", + "dist/2022-06-29/rust-std-beta-x86_64-unknown-linux-gnu.tar.gz": "69cb1a75f109f1bc3ef55eacb2bf8f3ad4e4f74fbe7fd2b92ee448082b15292f", + "dist/2022-06-29/rust-std-beta-x86_64-unknown-linux-gnu.tar.xz": "de2bff6b876d38a20c944b9ef1ca296061e6882080316cb6ad4f346b3f25543d", + "dist/2022-06-29/rust-std-beta-x86_64-unknown-linux-gnux32.tar.gz": "1e7803d70fd4965da58e0949f1de2ed9624852b48a6afc43fa7f007940e1ad61", + "dist/2022-06-29/rust-std-beta-x86_64-unknown-linux-gnux32.tar.xz": "cff451b8636469879061f9d0a2e2403d3bece99ea61e4ce8992095dcc5d57429", + "dist/2022-06-29/rust-std-beta-x86_64-unknown-linux-musl.tar.gz": "42654d72fc9816827ee0e0fba553f672eeacf7af2f828dcced42b3603ea7b244", + "dist/2022-06-29/rust-std-beta-x86_64-unknown-linux-musl.tar.xz": "d8b40b941b95d888af07649aece54b51fe419f129957a3c1ea00bb707092fba9", + "dist/2022-06-29/rust-std-beta-x86_64-unknown-netbsd.tar.gz": "9e168ccc151b0320feac61a46f69e5287ebe61d5cda4fd096c2a6e4c1bc4630e", + "dist/2022-06-29/rust-std-beta-x86_64-unknown-netbsd.tar.xz": "1fa18c0e9d352188505f1dcf21b132863cf531f3a5d1cec512baaa135dae071b", + "dist/2022-06-29/rust-std-beta-x86_64-unknown-none.tar.gz": "221da3b26cafafb2f1db1bcb69529424df021e149983ddd07cae15f9e7bd3b05", + "dist/2022-06-29/rust-std-beta-x86_64-unknown-none.tar.xz": "401b277ab48e8b5dd30da993a68b2318b9f5c3f6a1cd69c244dfa62212b77dc1", + "dist/2022-06-29/rust-std-beta-x86_64-unknown-redox.tar.gz": "0a67ac955769e71b677af6647233bea61f2bc61db0eda5b3a2d70fe52c094806", + "dist/2022-06-29/rust-std-beta-x86_64-unknown-redox.tar.xz": "96d52cf2a502adbb3cc37f1c46fba79ec7dc2ffdfaa369e58ba60a2e9b7a6efb", + "dist/2022-06-29/rustc-beta-aarch64-apple-darwin.tar.gz": "13c5bf14af21282b302efc63285b2c683f24853d510319aa43d150fd127255d1", + "dist/2022-06-29/rustc-beta-aarch64-apple-darwin.tar.xz": "3afc8778d32d04b8137552ca651237b5573149bfb7c4b3797e73746af8636612", + "dist/2022-06-29/rustc-beta-aarch64-pc-windows-msvc.tar.gz": "84f95488f8540020efc1f59d3112805b7b16517fcf0e991fac45757f7f88d09b", + "dist/2022-06-29/rustc-beta-aarch64-pc-windows-msvc.tar.xz": "818479235bdc06809c89728ba7c449f2187c159aeb45ffce62250a1e40202921", + "dist/2022-06-29/rustc-beta-aarch64-unknown-linux-gnu.tar.gz": "1a8acf7bd5d81b0cce741669aa76170c595525bfd981f327199a014d8f96cf29", + "dist/2022-06-29/rustc-beta-aarch64-unknown-linux-gnu.tar.xz": "eaecede917a4994772b1043c42c1a0a88bbf0efe5b9830e5be4fa039c13152a6", + "dist/2022-06-29/rustc-beta-aarch64-unknown-linux-musl.tar.gz": "f38e0aefff50338ec442a8a915aef83bb89a445c2535840a74cc1cd3ccd0ec1a", + "dist/2022-06-29/rustc-beta-aarch64-unknown-linux-musl.tar.xz": "f4c7ff3f19303bf82b0a7e3adff2f1d76be75487b78a53a23b5a564567c418b8", + "dist/2022-06-29/rustc-beta-arm-unknown-linux-gnueabi.tar.gz": "473936c8d1c6fb7de9da593185d6d3dcf32b3cd833e9a7b96a721ce6ad587628", + "dist/2022-06-29/rustc-beta-arm-unknown-linux-gnueabi.tar.xz": "72787fe6ae27c684c166acf178556ff570a923db89b5e4576b97b528b991b6db", + "dist/2022-06-29/rustc-beta-arm-unknown-linux-gnueabihf.tar.gz": "f641842f5b298ba11d7143d4e24f03b8adf20363e25c459a9b98e9903fd48a16", + "dist/2022-06-29/rustc-beta-arm-unknown-linux-gnueabihf.tar.xz": "3ef2c162e55a62024e4cbb079f03a38d40529d864ce4f8d28c12843b38568802", + "dist/2022-06-29/rustc-beta-armv7-unknown-linux-gnueabihf.tar.gz": "e3e714078092863a7cd3a6d9c8b8d8a8c05da97debff0545f45593163bd51e4e", + "dist/2022-06-29/rustc-beta-armv7-unknown-linux-gnueabihf.tar.xz": "dc9ae664ffa5b61d576182ddb79234331e1227302fe9cd6db0926011522582c8", + "dist/2022-06-29/rustc-beta-i686-pc-windows-gnu.tar.gz": "9bc6578d355c1fee74e8104331cdad4f3c9c94bf1713e989de5d52c1f5291528", + "dist/2022-06-29/rustc-beta-i686-pc-windows-gnu.tar.xz": "412a2ee2a94ecec20c1c54934b72d84b46e29f35f6520b8e654ef518b9a7e511", + "dist/2022-06-29/rustc-beta-i686-pc-windows-msvc.tar.gz": "f8fc7fbcd82398964ec562f0750f33fa1af55268e053d416d0729b466fc7fb3f", + "dist/2022-06-29/rustc-beta-i686-pc-windows-msvc.tar.xz": "eaa66c5680987aaea99d7cd38a5245c832698f4a53443eeeb06880a8ec915497", + "dist/2022-06-29/rustc-beta-i686-unknown-linux-gnu.tar.gz": "8748755c8c72ede71310f998c38ea0ba80e2065da5f53f8ac61bfe8e4c94ea1a", + "dist/2022-06-29/rustc-beta-i686-unknown-linux-gnu.tar.xz": "fac18aa72b3c801230dd3a653bab76521618be5fe48de2f79dc1890dacbc7a9c", + "dist/2022-06-29/rustc-beta-mips-unknown-linux-gnu.tar.gz": "e22c7209d77b1fdce3439225c2e7d659a61cdaced9387fccaef5370cb25baef1", + "dist/2022-06-29/rustc-beta-mips-unknown-linux-gnu.tar.xz": "cea1aa2447e02cc6a4be215f0bb4b658560f641389e314c0cc6814c2e1cb5c18", + "dist/2022-06-29/rustc-beta-mips64-unknown-linux-gnuabi64.tar.gz": "e57c23dd8981d77b81b27af2879c4a2bf9e6619b5a638d8ba9dac790bf9316a0", + "dist/2022-06-29/rustc-beta-mips64-unknown-linux-gnuabi64.tar.xz": "0dafb1d812358f5275ff272d247573ac0799dac64a446f7ad08543d6f4334088", + "dist/2022-06-29/rustc-beta-mips64el-unknown-linux-gnuabi64.tar.gz": "bf6be111afb4ea7ecdbc611e94aedce8e5ebf255f1e52cc61da65913a6963471", + "dist/2022-06-29/rustc-beta-mips64el-unknown-linux-gnuabi64.tar.xz": "7d169795f5ef7c09b7e3a9b40d8669c0b2fc6449247551b426286ebe3f6e258f", + "dist/2022-06-29/rustc-beta-mipsel-unknown-linux-gnu.tar.gz": "0e76f229b0dbeb14497cfda0f4d717c369b8bc59c7bce1fbad059220562c0814", + "dist/2022-06-29/rustc-beta-mipsel-unknown-linux-gnu.tar.xz": "d6870a46ab49264498b18a4cd2d2400f0df8b02514e92c1bd6396c732f869035", + "dist/2022-06-29/rustc-beta-powerpc-unknown-linux-gnu.tar.gz": "547269aa65cbfe33ef5457ac969399fcf90384f57523a91e9c61306fb9e464da", + "dist/2022-06-29/rustc-beta-powerpc-unknown-linux-gnu.tar.xz": "fe75b0ae3a9338f1e48e72e6d6f51edba25f5fd7ab0544d3feae6b69105f160c", + "dist/2022-06-29/rustc-beta-powerpc64-unknown-linux-gnu.tar.gz": "b445b6ec414be5c580a19717125858ed4c8e0c90828e085f2ab47a3b44a0863e", + "dist/2022-06-29/rustc-beta-powerpc64-unknown-linux-gnu.tar.xz": "a915c1da4a45cd286c0b8978999d5ef2ab96b24185793ee1dc043e094cf6c51c", + "dist/2022-06-29/rustc-beta-powerpc64le-unknown-linux-gnu.tar.gz": "72b6014c14f12f5e5848924e20342d993903d16e883ea8473ca8cf9d188f68d5", + "dist/2022-06-29/rustc-beta-powerpc64le-unknown-linux-gnu.tar.xz": "ee707cf657c9991eca8a9b722fb58b420b2c9fe9bc9e32c4042a4af2bc37e8cb", + "dist/2022-06-29/rustc-beta-riscv64gc-unknown-linux-gnu.tar.gz": "8e1fc4091115f93f13d88dd7a9b05492ffbcf72f12fc8bdeac28dd6f3c78c3ac", + "dist/2022-06-29/rustc-beta-riscv64gc-unknown-linux-gnu.tar.xz": "ae52c2a0c43871c658d63c101a192dd5fea65931e0d45855bd8dd40a58a7e688", + "dist/2022-06-29/rustc-beta-s390x-unknown-linux-gnu.tar.gz": "fe45b4d1d509a7a0c317888b575d3dcf1dfb7c0b8306ec54e2d09245c906e276", + "dist/2022-06-29/rustc-beta-s390x-unknown-linux-gnu.tar.xz": "0c06412d27669429ff1c0e5855c3a3ac923b40a93b2fdcb8fbccb4033476b5d1", + "dist/2022-06-29/rustc-beta-x86_64-apple-darwin.tar.gz": "a3c33e87a6b12049fcd7cbb0f53ea74c8411c91c262b6f352a1024221d3457c4", + "dist/2022-06-29/rustc-beta-x86_64-apple-darwin.tar.xz": "3256ad9fdca2506b06962b4e88c9a41daa8f094a5c1c80530fbce4dbdd6e1c32", + "dist/2022-06-29/rustc-beta-x86_64-pc-windows-gnu.tar.gz": "e2881ef537ec43fc012307cdac5291e4733b322e92a3b056a6f2820c883653b8", + "dist/2022-06-29/rustc-beta-x86_64-pc-windows-gnu.tar.xz": "5a8a36ca5f01ffc8a2dff21c6fbf99652444c6d3731c650fb91cce1fe79c3ebc", + "dist/2022-06-29/rustc-beta-x86_64-pc-windows-msvc.tar.gz": "6ee9a6511fc5342b4f07102f874822553c928ed75f09c4e34952db1c248604f1", + "dist/2022-06-29/rustc-beta-x86_64-pc-windows-msvc.tar.xz": "830d24aff7aac91a61143878969632a47eb8392c539fabdd25826792c7125509", + "dist/2022-06-29/rustc-beta-x86_64-unknown-freebsd.tar.gz": "1fb6dc34083e95e193c39bfb4edca99f42713f5cfe3bda8e368e977f61c82110", + "dist/2022-06-29/rustc-beta-x86_64-unknown-freebsd.tar.xz": "c3b9ba1586bb6152596aeb01997b40ab65ab7140525b1b0bc22f2a84baf5c44b", + "dist/2022-06-29/rustc-beta-x86_64-unknown-illumos.tar.gz": "584b8ee47755982a6b0f0d0d5a12af35ad740e2df8b1ec1d3084509ea940c2b6", + "dist/2022-06-29/rustc-beta-x86_64-unknown-illumos.tar.xz": "a4532b97743b8a90f4f492513c7cd51600426c08454be2e24a49cf867ca0e30b", + "dist/2022-06-29/rustc-beta-x86_64-unknown-linux-gnu.tar.gz": "f3fb7f949724bf9b8b77cc562d9d53eb067872bc312ceeb2b5541c6667f70da2", + "dist/2022-06-29/rustc-beta-x86_64-unknown-linux-gnu.tar.xz": "10912b2783699d9e155b4f59dd762fe012e4ea4410b56d83b36d1df769a8cd49", + "dist/2022-06-29/rustc-beta-x86_64-unknown-linux-musl.tar.gz": "f548bad660bce1513081be0767305a523fd129a0b13aa368e8c86a36d1ec3b23", + "dist/2022-06-29/rustc-beta-x86_64-unknown-linux-musl.tar.xz": "fd52405c614d6932d9e5948e851be7315f1f9d21bbfc3e6d142d6d3196464fe7", + "dist/2022-06-29/rustc-beta-x86_64-unknown-netbsd.tar.gz": "1b816d0bf6d4138bd557094f922e7aa9b2e7d0ea27464cadbb117eac8a42f3fc", + "dist/2022-06-29/rustc-beta-x86_64-unknown-netbsd.tar.xz": "b869ba4ab920cd08bd063cedba08614d5c6199f643d277d59f44af513925c16b", + "dist/2022-06-29/rustfmt-nightly-aarch64-apple-darwin.tar.gz": "3ac81b63371115875eec194eb4d0c3e9aeb624c7f7ce3ee85b197b8e3f1cd599", + "dist/2022-06-29/rustfmt-nightly-aarch64-apple-darwin.tar.xz": "8eda09837e39a0847b79803645f810d87be7208465deb7f5b0952fa7e39c2113", + "dist/2022-06-29/rustfmt-nightly-aarch64-pc-windows-msvc.tar.gz": "353d2f523a3a1bc2ca478b6facea40363d2d18ca6b48d8f4be18626c7cdb3142", + "dist/2022-06-29/rustfmt-nightly-aarch64-pc-windows-msvc.tar.xz": "ade013031c8c72eae5717c248cb20f36107d326c497b4f3c8e90dc2912d11975", + "dist/2022-06-29/rustfmt-nightly-aarch64-unknown-linux-gnu.tar.gz": "64b5f8f97781bd4eca5554f28688a58831162fafaebac31b0f04610e16f09a48", + "dist/2022-06-29/rustfmt-nightly-aarch64-unknown-linux-gnu.tar.xz": "feb458ae9a30773519b8be69557d0bd4c3d924aa22eb4a4fdf331e0d620f1e90", + "dist/2022-06-29/rustfmt-nightly-aarch64-unknown-linux-musl.tar.gz": "cb2698b870f2c56554996f2e651ae53b11241c06da6ebab4b40a460f6826d91f", + "dist/2022-06-29/rustfmt-nightly-aarch64-unknown-linux-musl.tar.xz": "b0be127f8c04dc4ac2d77b2f9ec7e74a793b65bcd591c0c6a7208b1f4b445df3", + "dist/2022-06-29/rustfmt-nightly-arm-unknown-linux-gnueabi.tar.gz": "596b02cf564a03c69a29f61ca6bba4758152d64775eff62b767bf77cce3b00bf", + "dist/2022-06-29/rustfmt-nightly-arm-unknown-linux-gnueabi.tar.xz": "f819a48640599ea06bcc4a3f3630bd0a12c9e698cf8f62f61b36813830a54d55", + "dist/2022-06-29/rustfmt-nightly-arm-unknown-linux-gnueabihf.tar.gz": "19df36c566a4cf5d440011a1c0e94a4cc70e5b66e29b36a268872d4e2def8e78", + "dist/2022-06-29/rustfmt-nightly-arm-unknown-linux-gnueabihf.tar.xz": "dade13d688c6ba9b291b403d4d61bfd8973d3284b9bc7a92ed6de47665411f07", + "dist/2022-06-29/rustfmt-nightly-armv7-unknown-linux-gnueabihf.tar.gz": "5ba3a696872e02cb2a4b2e191262d61ecbe6f289345373ee06c542a2d2580527", + "dist/2022-06-29/rustfmt-nightly-armv7-unknown-linux-gnueabihf.tar.xz": "8ff08027f040bdf0de0496d6a408796fcca44540b097414255f776704e6f4966", + "dist/2022-06-29/rustfmt-nightly-i686-pc-windows-gnu.tar.gz": "15a36d3a798d2fa027d05229ab42baa4cadb6faa8edfd8c13260ea4756031194", + "dist/2022-06-29/rustfmt-nightly-i686-pc-windows-gnu.tar.xz": "438ea44472607752d205d9d2f14056a4c66fd9a84f728110792aadd22929b9fd", + "dist/2022-06-29/rustfmt-nightly-i686-pc-windows-msvc.tar.gz": "734aa5ce2105134c34301e44f7d8f0ea3bc94587df3e27793530f3a722eb9b26", + "dist/2022-06-29/rustfmt-nightly-i686-pc-windows-msvc.tar.xz": "02a7401369a03caec796deb2d3a0b3c1a46bad79bbe6e654d9e721cd95bfcb0a", + "dist/2022-06-29/rustfmt-nightly-i686-unknown-linux-gnu.tar.gz": "17a8c573eaaf5033b15ef14ff221848e3100332b6f01b30b249c9e854bcc21d9", + "dist/2022-06-29/rustfmt-nightly-i686-unknown-linux-gnu.tar.xz": "bca6959f1e6977cccd0571bc61a37928f559eee8e10395d7eb033cec9a8e0dae", + "dist/2022-06-29/rustfmt-nightly-mips-unknown-linux-gnu.tar.gz": "6a4cd4b13e877b7f8ba712cab0e804edefd432d78cd46970bd44384ce94e7faa", + "dist/2022-06-29/rustfmt-nightly-mips-unknown-linux-gnu.tar.xz": "43adf44181bee2b295584c36c35041ff97465fa3fe46b358e142a1d10c224a40", + "dist/2022-06-29/rustfmt-nightly-mips64-unknown-linux-gnuabi64.tar.gz": "376abf3aa462c0e1271044761af0c9f3c63442731c6d04accd32a0ca0221eee6", + "dist/2022-06-29/rustfmt-nightly-mips64-unknown-linux-gnuabi64.tar.xz": "f8a5f3d01e06f46a6d85fa7f74b1a494fcb55a6d5dc8113eb96d6a46d0d37050", + "dist/2022-06-29/rustfmt-nightly-mips64el-unknown-linux-gnuabi64.tar.gz": "158573b8e9da4e8a464bd3c692e54084cd0b9097596d41c21646091883d15b48", + "dist/2022-06-29/rustfmt-nightly-mips64el-unknown-linux-gnuabi64.tar.xz": "bdae49f025be97fbf37c9ca7ef1f4331ec4ebf8a5fb429a4c20f09619069e655", + "dist/2022-06-29/rustfmt-nightly-mipsel-unknown-linux-gnu.tar.gz": "6ed1ea2364c8b645c6d899cada76cf161222fae9b4693ee71fb98721409f73a8", + "dist/2022-06-29/rustfmt-nightly-mipsel-unknown-linux-gnu.tar.xz": "beaa6383696385769cd885b3314ccb6f69a7a5557bb1af7214c2c8b2d03d64c7", + "dist/2022-06-29/rustfmt-nightly-powerpc-unknown-linux-gnu.tar.gz": "0f0ad140d47b4477e9ff0a925468b36aaaca0063eed018022624ee15cd0fcd7e", + "dist/2022-06-29/rustfmt-nightly-powerpc-unknown-linux-gnu.tar.xz": "23d3bcf9d9a22bd869b3857c7c8bbf25c168ab60677a958c8b48d8b04319beae", + "dist/2022-06-29/rustfmt-nightly-powerpc64-unknown-linux-gnu.tar.gz": "fbd1655d0399a3e8728710dc0c234ebca2ce8669fc42eadbbb075baabaee740f", + "dist/2022-06-29/rustfmt-nightly-powerpc64-unknown-linux-gnu.tar.xz": "1d0c70f5ec38542f2d5b125d59d93ffa1a984a7a2e2353503f8b8554604daa8a", + "dist/2022-06-29/rustfmt-nightly-powerpc64le-unknown-linux-gnu.tar.gz": "34acce36d8aecd8f4414fae766c2ad7c7942eaa8b422075017ce28e84f08fb08", + "dist/2022-06-29/rustfmt-nightly-powerpc64le-unknown-linux-gnu.tar.xz": "8984ea923bf93c394ca50b41f58df0d750bc522c481de2a0468afafef052f343", + "dist/2022-06-29/rustfmt-nightly-riscv64gc-unknown-linux-gnu.tar.gz": "a9064c4ecfe40a2b3cdbabe12b6063f13680f2a6eb36d58f02fa6207af988a13", + "dist/2022-06-29/rustfmt-nightly-riscv64gc-unknown-linux-gnu.tar.xz": "3576cfd24cb1b53d96145651810c532a5b1c424dfcc39b2c78d5688d7f0791ca", + "dist/2022-06-29/rustfmt-nightly-s390x-unknown-linux-gnu.tar.gz": "2b921dbf7f8c2931bc531665087ffa05efe8bb4270902a311789409994844cd0", + "dist/2022-06-29/rustfmt-nightly-s390x-unknown-linux-gnu.tar.xz": "f6a4134ffb2c4616606b5d9d3ba63b9dda1ec49c2c0af2290a915c08d80ef301", + "dist/2022-06-29/rustfmt-nightly-x86_64-apple-darwin.tar.gz": "468bc3d0d587b37993cda14fbaf07ab4edc05627126d96d9ccaf58b1df55178f", + "dist/2022-06-29/rustfmt-nightly-x86_64-apple-darwin.tar.xz": "e6262f053b2e456d09ce6617e8209e229d2b9ced144a9eff12de830b6f0cbcfe", + "dist/2022-06-29/rustfmt-nightly-x86_64-pc-windows-gnu.tar.gz": "34a9cf74d9076c49c6266d718fad9a78ea1ede268f9b7978b508b76a4c6e3f8c", + "dist/2022-06-29/rustfmt-nightly-x86_64-pc-windows-gnu.tar.xz": "3d0e544dbb280e4cafebc05dcc68b3cda8a742f9909f59de93c8791721c3f2c8", + "dist/2022-06-29/rustfmt-nightly-x86_64-pc-windows-msvc.tar.gz": "d7119b250b1b31fcba6b3d34cb8deafa32fe20f547ad1bc1e931c58e7059f65f", + "dist/2022-06-29/rustfmt-nightly-x86_64-pc-windows-msvc.tar.xz": "ebc31e9118112e64fced1ad94e4e903e7ac0ff8dd771d85a55c1589a6b838c38", + "dist/2022-06-29/rustfmt-nightly-x86_64-unknown-freebsd.tar.gz": "a940ea208faa9882808cc56a8e96cadf79f954844ede160b2b8971238bc84f4a", + "dist/2022-06-29/rustfmt-nightly-x86_64-unknown-freebsd.tar.xz": "e699ef1a7a7f5e4bd40cbb3daff754e9214cbe71c28b1436a893a5edbca8c876", + "dist/2022-06-29/rustfmt-nightly-x86_64-unknown-illumos.tar.gz": "2a53b4b5e57fd9e1d9014d46576e6b47b51d0dbaaf55c4e84964390c2b2065cf", + "dist/2022-06-29/rustfmt-nightly-x86_64-unknown-illumos.tar.xz": "e4491027e20ac563ea8a0906d8941f80274890d4d1b4b3728e26e5926f2c77cf", + "dist/2022-06-29/rustfmt-nightly-x86_64-unknown-linux-gnu.tar.gz": "b7ba70b0ca5ece6b14cb1034e7226a83435f8b71c77a864b4ad949db11ab75b1", + "dist/2022-06-29/rustfmt-nightly-x86_64-unknown-linux-gnu.tar.xz": "ce07cc2010a424e83672095d89b4592485a7c94a3f450e609ed62237c86909ca", + "dist/2022-06-29/rustfmt-nightly-x86_64-unknown-linux-musl.tar.gz": "bd653ae8f104872e5a2f937fabdff09d41691c28d512fb7f08562fb21ab64e89", + "dist/2022-06-29/rustfmt-nightly-x86_64-unknown-linux-musl.tar.xz": "d374ef3fcfaf21c13813cab8953c42c9c965c02549d18e95fca903b923ef5e6b", + "dist/2022-06-29/rustfmt-nightly-x86_64-unknown-netbsd.tar.gz": "f0fe5175ea73034b1b789db8d31214ca561af0f4be21c52895b47baf103e5952", + "dist/2022-06-29/rustfmt-nightly-x86_64-unknown-netbsd.tar.xz": "6bc6231ebba38ec47fc1de646aa7d8a9855d2dbfb61595fad299656e39acd0d5" } } diff --git a/src/test/codegen/enum-bounds-check-derived-idx.rs b/src/test/codegen/enum-bounds-check-derived-idx.rs index aa66c2ed08e..fe02aeb5f62 100644 --- a/src/test/codegen/enum-bounds-check-derived-idx.rs +++ b/src/test/codegen/enum-bounds-check-derived-idx.rs @@ -12,13 +12,15 @@ pub enum Bar { // CHECK-LABEL: @lookup_inc #[no_mangle] pub fn lookup_inc(buf: &[u8; 5], f: Bar) -> u8 { - // CHECK-NOT: panic_bounds_check + // FIXME: panic check can be removed by adding the assumes back after https://github.com/rust-lang/rust/pull/98332 + // CHECK: panic_bounds_check buf[f as usize + 1] } // CHECK-LABEL: @lookup_dec #[no_mangle] pub fn lookup_dec(buf: &[u8; 5], f: Bar) -> u8 { - // CHECK-NOT: panic_bounds_check + // FIXME: panic check can be removed by adding the assumes back after https://github.com/rust-lang/rust/pull/98332 + // CHECK: panic_bounds_check buf[f as usize - 1] } diff --git a/src/test/codegen/enum-bounds-check-issue-13926.rs b/src/test/codegen/enum-bounds-check-issue-13926.rs index b26945bc549..1aec41d5441 100644 --- a/src/test/codegen/enum-bounds-check-issue-13926.rs +++ b/src/test/codegen/enum-bounds-check-issue-13926.rs @@ -13,6 +13,7 @@ pub enum Exception { // CHECK-LABEL: @access #[no_mangle] pub fn access(array: &[usize; 12], exc: Exception) -> usize { - // CHECK-NOT: panic_bounds_check + // FIXME: panic check can be removed by adding the assumes back after https://github.com/rust-lang/rust/pull/98332 + // CHECK: panic_bounds_check array[(exc as u8 - 4) as usize] } diff --git a/src/test/codegen/enum-bounds-check-issue-82871.rs b/src/test/codegen/enum-bounds-check-issue-82871.rs index a1fa1387d94..32fdc4a5f4f 100644 --- a/src/test/codegen/enum-bounds-check-issue-82871.rs +++ b/src/test/codegen/enum-bounds-check-issue-82871.rs @@ -1,4 +1,4 @@ -// compile-flags: -O +// compile-flags: -C opt-level=0 #![crate_type = "lib"] @@ -9,7 +9,10 @@ pub enum E { // CHECK-LABEL: @index #[no_mangle] -pub fn index(x: &[u32; 3], ind: E) -> u32{ - // CHECK-NOT: panic_bounds_check +pub fn index(x: &[u32; 3], ind: E) -> u32 { + // Canary: we should be able to optimize out the bounds check, but we need + // to track the range of the discriminant result in order to be able to do that. + // oli-obk tried to add that, but that caused miscompilations all over the place. + // CHECK: panic_bounds_check x[ind as usize] } diff --git a/src/test/codegen/enum-bounds-check.rs b/src/test/codegen/enum-bounds-check.rs index 17322d5911b..f85c6817ded 100644 --- a/src/test/codegen/enum-bounds-check.rs +++ b/src/test/codegen/enum-bounds-check.rs @@ -21,6 +21,7 @@ pub enum Bar { // CHECK-LABEL: @lookup_unmodified #[no_mangle] pub fn lookup_unmodified(buf: &[u8; 5], f: Bar) -> u8 { - // CHECK-NOT: panic_bounds_check + // FIXME: panic check can be removed by adding the assumes back after https://github.com/rust-lang/rust/pull/98332 + // CHECK: panic_bounds_check buf[f as usize] } diff --git a/src/test/codegen/issue-37945.rs b/src/test/codegen/issue-37945.rs index ee63a783f52..12fa1e9e56b 100644 --- a/src/test/codegen/issue-37945.rs +++ b/src/test/codegen/issue-37945.rs @@ -17,7 +17,9 @@ pub fn is_empty_1(xs: Iter<f32>) -> bool { // CHECK-NEXT: start: // CHECK-NEXT: [[A:%.*]] = icmp ne {{i32\*|ptr}} %xs.1, null // CHECK-NEXT: tail call void @llvm.assume(i1 [[A]]) -// CHECK-NEXT: [[B:%.*]] = icmp eq {{i32\*|ptr}} %xs.0, %xs.1 +// The order between %xs.0 and %xs.1 on the next line doesn't matter +// and different LLVM versions produce different order. +// CHECK-NEXT: [[B:%.*]] = icmp eq {{i32\*|ptr}} {{%xs.0, %xs.1|%xs.1, %xs.0}} // CHECK-NEXT: ret i1 [[B:%.*]] {xs}.next().is_none() } @@ -28,7 +30,9 @@ pub fn is_empty_2(xs: Iter<f32>) -> bool { // CHECK-NEXT: start: // CHECK-NEXT: [[C:%.*]] = icmp ne {{i32\*|ptr}} %xs.1, null // CHECK-NEXT: tail call void @llvm.assume(i1 [[C]]) -// CHECK-NEXT: [[D:%.*]] = icmp eq {{i32\*|ptr}} %xs.0, %xs.1 +// The order between %xs.0 and %xs.1 on the next line doesn't matter +// and different LLVM versions produce different order. +// CHECK-NEXT: [[D:%.*]] = icmp eq {{i32\*|ptr}} {{%xs.0, %xs.1|%xs.1, %xs.0}} // CHECK-NEXT: ret i1 [[D:%.*]] xs.map(|&x| x).next().is_none() } diff --git a/src/test/codegen/issue-75659.rs b/src/test/codegen/issue-75659.rs index d093c841d68..6bcb59affe3 100644 --- a/src/test/codegen/issue-75659.rs +++ b/src/test/codegen/issue-75659.rs @@ -1,7 +1,7 @@ // This test checks that the call to memchr/slice_contains is optimized away // when searching in small slices. -// compile-flags: -O +// compile-flags: -O -Zinline-mir=no // only-x86_64 #![crate_type = "lib"] diff --git a/src/test/codegen/mem-replace-direct-memcpy.rs b/src/test/codegen/mem-replace-direct-memcpy.rs index d1c4c56dbe4..b41ef538d71 100644 --- a/src/test/codegen/mem-replace-direct-memcpy.rs +++ b/src/test/codegen/mem-replace-direct-memcpy.rs @@ -3,7 +3,7 @@ // may e.g. multiply `size_of::<T>()` with a variable "count" (which is only // known to be `1` after inlining). -// compile-flags: -C no-prepopulate-passes +// compile-flags: -C no-prepopulate-passes -Zinline-mir=no #![crate_type = "lib"] @@ -12,14 +12,12 @@ pub fn replace_byte(dst: &mut u8, src: u8) -> u8 { } // NOTE(eddyb) the `CHECK-NOT`s ensure that the only calls of `@llvm.memcpy` in -// the entire output, are the two direct calls we want, from `ptr::{read,write}`. +// the entire output, are the two direct calls we want, from `ptr::replace`. // CHECK-NOT: call void @llvm.memcpy -// CHECK: ; core::ptr::read +// CHECK: ; core::mem::replace // CHECK-NOT: call void @llvm.memcpy -// CHECK: call void @llvm.memcpy.{{.+}}({{i8\*|ptr}} align 1 %{{.*}}, {{i8\*|ptr}} align 1 %src, i{{.*}} 1, i1 false) +// CHECK: call void @llvm.memcpy.{{.+}}({{i8\*|ptr}} align 1 %{{.*}}, {{i8\*|ptr}} align 1 %dest, i{{.*}} 1, i1 false) // CHECK-NOT: call void @llvm.memcpy -// CHECK: ; core::ptr::write -// CHECK-NOT: call void @llvm.memcpy -// CHECK: call void @llvm.memcpy.{{.+}}({{i8\*|ptr}} align 1 %dst, {{i8\*|ptr}} align 1 %src, i{{.*}} 1, i1 false) +// CHECK: call void @llvm.memcpy.{{.+}}({{i8\*|ptr}} align 1 %dest, {{i8\*|ptr}} align 1 %src{{.*}}, i{{.*}} 1, i1 false) // CHECK-NOT: call void @llvm.memcpy diff --git a/src/test/codegen/remap_path_prefix/main.rs b/src/test/codegen/remap_path_prefix/main.rs index 381f11ff1ef..9bef743ddcb 100644 --- a/src/test/codegen/remap_path_prefix/main.rs +++ b/src/test/codegen/remap_path_prefix/main.rs @@ -1,7 +1,7 @@ // ignore-windows // -// compile-flags: -g -C no-prepopulate-passes --remap-path-prefix={{cwd}}=/the/cwd --remap-path-prefix={{src-base}}=/the/src +// compile-flags: -g -C no-prepopulate-passes --remap-path-prefix={{cwd}}=/the/cwd --remap-path-prefix={{src-base}}=/the/src -Zinline-mir=no // aux-build:remap_path_prefix_aux.rs extern crate remap_path_prefix_aux; diff --git a/src/test/codegen/simd-wide-sum.rs b/src/test/codegen/simd-wide-sum.rs index fde9b0fcd8a..015ac4fe4d1 100644 --- a/src/test/codegen/simd-wide-sum.rs +++ b/src/test/codegen/simd-wide-sum.rs @@ -47,8 +47,9 @@ pub fn wider_reduce_iter(x: Simd<u8, N>) -> u16 { #[no_mangle] // CHECK-LABEL: @wider_reduce_into_iter pub fn wider_reduce_into_iter(x: Simd<u8, N>) -> u16 { - // CHECK: zext <8 x i8> - // CHECK-SAME: to <8 x i16> - // CHECK: call i16 @llvm.vector.reduce.add.v8i16(<8 x i16> + // FIXME MIR inlining messes up LLVM optimizations. + // WOULD-CHECK: zext <8 x i8> + // WOULD-CHECK-SAME: to <8 x i16> + // WOULD-CHECK: call i16 @llvm.vector.reduce.add.v8i16(<8 x i16> x.to_array().into_iter().map(u16::from).sum() } diff --git a/src/test/codegen/slice-ref-equality.rs b/src/test/codegen/slice-ref-equality.rs index e5cde5e9e74..47fde12bf30 100644 --- a/src/test/codegen/slice-ref-equality.rs +++ b/src/test/codegen/slice-ref-equality.rs @@ -1,4 +1,4 @@ -// compile-flags: -C opt-level=3 +// compile-flags: -C opt-level=3 -Zmerge-functions=disabled #![crate_type = "lib"] diff --git a/src/test/codegen/swap-small-types.rs b/src/test/codegen/swap-small-types.rs index 2f375844cc7..03e2a2327fc 100644 --- a/src/test/codegen/swap-small-types.rs +++ b/src/test/codegen/swap-small-types.rs @@ -11,9 +11,10 @@ type RGB48 = [u16; 3]; // CHECK-LABEL: @swap_rgb48 #[no_mangle] pub fn swap_rgb48(x: &mut RGB48, y: &mut RGB48) { -// CHECK-NOT: alloca -// CHECK: load i48 -// CHECK: store i48 + // FIXME MIR inlining messes up LLVM optimizations. +// WOULD-CHECK-NOT: alloca +// WOULD-CHECK: load i48 +// WOULD-CHECK: store i48 swap(x, y) } diff --git a/src/test/codegen/vec-in-place.rs b/src/test/codegen/vec-in-place.rs index 13c41f7d4a9..62139aa9beb 100644 --- a/src/test/codegen/vec-in-place.rs +++ b/src/test/codegen/vec-in-place.rs @@ -53,16 +53,18 @@ pub fn vec_iterator_cast_unwrap(vec: Vec<Wrapper<u8>>) -> Vec<u8> { // CHECK-LABEL: @vec_iterator_cast_aggregate #[no_mangle] pub fn vec_iterator_cast_aggregate(vec: Vec<[u64; 4]>) -> Vec<Foo> { - // CHECK-NOT: loop - // CHECK-NOT: call + // FIXME These checks should be the same as other functions. + // CHECK-NOT: @__rust_alloc + // CHECK-NOT: @__rust_alloc vec.into_iter().map(|e| unsafe { std::mem::transmute(e) }).collect() } // CHECK-LABEL: @vec_iterator_cast_deaggregate #[no_mangle] pub fn vec_iterator_cast_deaggregate(vec: Vec<Bar>) -> Vec<[u64; 4]> { - // CHECK-NOT: loop - // CHECK-NOT: call + // FIXME These checks should be the same as other functions. + // CHECK-NOT: @__rust_alloc + // CHECK-NOT: @__rust_alloc // Safety: For the purpose of this test we assume that Bar layout matches [u64; 4]. // This currently is not guaranteed for repr(Rust) types, but it happens to work here and diff --git a/src/test/incremental/issue-61323.rs b/src/test/incremental/issue-61323.rs index 448ce367b8c..97cbfe408f2 100644 --- a/src/test/incremental/issue-61323.rs +++ b/src/test/incremental/issue-61323.rs @@ -10,6 +10,6 @@ struct C(Box<A>); #[cfg(cfail)] struct C(A); -//[cfail]~^ ERROR 12:1: 12:13: recursive type `C` has infinite size [E0072] +//[cfail]~^ ERROR 12:1: 12:9: recursive type `C` has infinite size [E0072] fn main() {} diff --git a/src/test/incremental/split_debuginfo_mode.rs b/src/test/incremental/split_debuginfo_mode.rs new file mode 100644 index 00000000000..f2533e4146a --- /dev/null +++ b/src/test/incremental/split_debuginfo_mode.rs @@ -0,0 +1,33 @@ +// This test case makes sure that changing split-debuginfo commandline options triggers a full re-compilation. +// We only test on x86_64-unknown-linux-gnu because there all combinations split-debuginfo settings are valid +// and the test is platform-independent otherwise. + +// ignore-tidy-linelength +// only-x86_64-unknown-linux-gnu +// revisions:rpass1 rpass2 rpass3 rpass4 + +// [rpass1]compile-flags: -Zquery-dep-graph -Zunstable-options -Csplit-debuginfo=unpacked -Zsplit-dwarf-kind=single -Zsplit-dwarf-inlining=on +// [rpass2]compile-flags: -Zquery-dep-graph -Zunstable-options -Csplit-debuginfo=packed -Zsplit-dwarf-kind=single -Zsplit-dwarf-inlining=on +// [rpass3]compile-flags: -Zquery-dep-graph -Zunstable-options -Csplit-debuginfo=packed -Zsplit-dwarf-kind=split -Zsplit-dwarf-inlining=on +// [rpass4]compile-flags: -Zquery-dep-graph -Zunstable-options -Csplit-debuginfo=packed -Zsplit-dwarf-kind=split -Zsplit-dwarf-inlining=off + +#![feature(rustc_attrs)] +// For rpass2 we change -Csplit-debuginfo and thus expect every CGU to be recompiled +#![rustc_partition_codegened(module = "split_debuginfo_mode", cfg = "rpass2")] +#![rustc_partition_codegened(module = "split_debuginfo_mode-another_module", cfg = "rpass2")] +// For rpass3 we change -Zsplit-dwarf-kind and thus also expect every CGU to be recompiled +#![rustc_partition_codegened(module = "split_debuginfo_mode", cfg = "rpass3")] +#![rustc_partition_codegened(module = "split_debuginfo_mode-another_module", cfg = "rpass3")] +// For rpass4 we change -Zsplit-dwarf-inlining and thus also expect every CGU to be recompiled +#![rustc_partition_codegened(module = "split_debuginfo_mode", cfg = "rpass4")] +#![rustc_partition_codegened(module = "split_debuginfo_mode-another_module", cfg = "rpass4")] + +mod another_module { + pub fn foo() -> &'static str { + "hello world" + } +} + +pub fn main() { + println!("{}", another_module::foo()); +} diff --git a/src/test/mir-opt/combine_clone_of_primitives.{impl#0}-clone.InstCombine.diff b/src/test/mir-opt/combine_clone_of_primitives.{impl#0}-clone.InstCombine.diff index fdc016a95d5..b1ff480324f 100644 --- a/src/test/mir-opt/combine_clone_of_primitives.{impl#0}-clone.InstCombine.diff +++ b/src/test/mir-opt/combine_clone_of_primitives.{impl#0}-clone.InstCombine.diff @@ -4,98 +4,78 @@ fn <impl at $DIR/combine_clone_of_primitives.rs:6:10: 6:15>::clone(_1: &MyThing<T>) -> MyThing<T> { debug self => _1; // in scope 0 at $DIR/combine_clone_of_primitives.rs:6:10: 6:15 let mut _0: MyThing<T>; // return place in scope 0 at $DIR/combine_clone_of_primitives.rs:6:10: 6:15 - let _2: &T; // in scope 0 at $DIR/combine_clone_of_primitives.rs:8:5: 8:9 - let _3: &u64; // in scope 0 at $DIR/combine_clone_of_primitives.rs:9:5: 9:11 - let _4: &[f32; 3]; // in scope 0 at $DIR/combine_clone_of_primitives.rs:10:5: 10:16 - let mut _5: T; // in scope 0 at $DIR/combine_clone_of_primitives.rs:8:5: 8:9 - let mut _6: &T; // in scope 0 at $DIR/combine_clone_of_primitives.rs:8:5: 8:9 - let _7: &T; // in scope 0 at $DIR/combine_clone_of_primitives.rs:8:5: 8:9 - let mut _8: u64; // in scope 0 at $DIR/combine_clone_of_primitives.rs:9:5: 9:11 - let mut _9: &u64; // in scope 0 at $DIR/combine_clone_of_primitives.rs:9:5: 9:11 - let _10: &u64; // in scope 0 at $DIR/combine_clone_of_primitives.rs:9:5: 9:11 - let mut _11: [f32; 3]; // in scope 0 at $DIR/combine_clone_of_primitives.rs:10:5: 10:16 - let mut _12: &[f32; 3]; // in scope 0 at $DIR/combine_clone_of_primitives.rs:10:5: 10:16 - let _13: &[f32; 3]; // in scope 0 at $DIR/combine_clone_of_primitives.rs:10:5: 10:16 - scope 1 { - debug __self_0_0 => _2; // in scope 1 at $DIR/combine_clone_of_primitives.rs:8:5: 8:9 - debug __self_0_1 => _3; // in scope 1 at $DIR/combine_clone_of_primitives.rs:9:5: 9:11 - debug __self_0_2 => _4; // in scope 1 at $DIR/combine_clone_of_primitives.rs:10:5: 10:16 - } + let mut _2: T; // in scope 0 at $DIR/combine_clone_of_primitives.rs:8:5: 8:9 + let mut _3: &T; // in scope 0 at $DIR/combine_clone_of_primitives.rs:8:5: 8:9 + let _4: &T; // in scope 0 at $DIR/combine_clone_of_primitives.rs:8:5: 8:9 + let mut _5: u64; // in scope 0 at $DIR/combine_clone_of_primitives.rs:9:5: 9:11 + let mut _6: &u64; // in scope 0 at $DIR/combine_clone_of_primitives.rs:9:5: 9:11 + let _7: &u64; // in scope 0 at $DIR/combine_clone_of_primitives.rs:9:5: 9:11 + let mut _8: [f32; 3]; // in scope 0 at $DIR/combine_clone_of_primitives.rs:10:5: 10:16 + let mut _9: &[f32; 3]; // in scope 0 at $DIR/combine_clone_of_primitives.rs:10:5: 10:16 + let _10: &[f32; 3]; // in scope 0 at $DIR/combine_clone_of_primitives.rs:10:5: 10:16 bb0: { StorageLive(_2); // scope 0 at $DIR/combine_clone_of_primitives.rs:8:5: 8:9 - _2 = &((*_1).0: T); // scope 0 at $DIR/combine_clone_of_primitives.rs:8:5: 8:9 - StorageLive(_3); // scope 0 at $DIR/combine_clone_of_primitives.rs:9:5: 9:11 - _3 = &((*_1).1: u64); // scope 0 at $DIR/combine_clone_of_primitives.rs:9:5: 9:11 - StorageLive(_4); // scope 0 at $DIR/combine_clone_of_primitives.rs:10:5: 10:16 - _4 = &((*_1).2: [f32; 3]); // scope 0 at $DIR/combine_clone_of_primitives.rs:10:5: 10:16 - StorageLive(_5); // scope 1 at $DIR/combine_clone_of_primitives.rs:8:5: 8:9 - StorageLive(_6); // scope 1 at $DIR/combine_clone_of_primitives.rs:8:5: 8:9 - StorageLive(_7); // scope 1 at $DIR/combine_clone_of_primitives.rs:8:5: 8:9 -- _7 = &(*_2); // scope 1 at $DIR/combine_clone_of_primitives.rs:8:5: 8:9 -- _6 = &(*_7); // scope 1 at $DIR/combine_clone_of_primitives.rs:8:5: 8:9 -+ _7 = _2; // scope 1 at $DIR/combine_clone_of_primitives.rs:8:5: 8:9 -+ _6 = _7; // scope 1 at $DIR/combine_clone_of_primitives.rs:8:5: 8:9 - _5 = <T as Clone>::clone(move _6) -> bb1; // scope 1 at $DIR/combine_clone_of_primitives.rs:8:5: 8:9 + StorageLive(_3); // scope 0 at $DIR/combine_clone_of_primitives.rs:8:5: 8:9 + StorageLive(_4); // scope 0 at $DIR/combine_clone_of_primitives.rs:8:5: 8:9 + _4 = &((*_1).0: T); // scope 0 at $DIR/combine_clone_of_primitives.rs:8:5: 8:9 +- _3 = &(*_4); // scope 0 at $DIR/combine_clone_of_primitives.rs:8:5: 8:9 ++ _3 = _4; // scope 0 at $DIR/combine_clone_of_primitives.rs:8:5: 8:9 + _2 = <T as Clone>::clone(move _3) -> bb1; // scope 0 at $DIR/combine_clone_of_primitives.rs:8:5: 8:9 // mir::Constant // + span: $DIR/combine_clone_of_primitives.rs:8:5: 8:9 // + literal: Const { ty: for<'r> fn(&'r T) -> T {<T as Clone>::clone}, val: Value(Scalar(<ZST>)) } } bb1: { - StorageDead(_6); // scope 1 at $DIR/combine_clone_of_primitives.rs:8:8: 8:9 - StorageLive(_8); // scope 1 at $DIR/combine_clone_of_primitives.rs:9:5: 9:11 - StorageLive(_9); // scope 1 at $DIR/combine_clone_of_primitives.rs:9:5: 9:11 - StorageLive(_10); // scope 1 at $DIR/combine_clone_of_primitives.rs:9:5: 9:11 -- _10 = &(*_3); // scope 1 at $DIR/combine_clone_of_primitives.rs:9:5: 9:11 -- _9 = &(*_10); // scope 1 at $DIR/combine_clone_of_primitives.rs:9:5: 9:11 -- _8 = <u64 as Clone>::clone(move _9) -> [return: bb2, unwind: bb4]; // scope 1 at $DIR/combine_clone_of_primitives.rs:9:5: 9:11 + StorageDead(_3); // scope 0 at $DIR/combine_clone_of_primitives.rs:8:8: 8:9 + StorageLive(_5); // scope 0 at $DIR/combine_clone_of_primitives.rs:9:5: 9:11 + StorageLive(_6); // scope 0 at $DIR/combine_clone_of_primitives.rs:9:5: 9:11 + StorageLive(_7); // scope 0 at $DIR/combine_clone_of_primitives.rs:9:5: 9:11 + _7 = &((*_1).1: u64); // scope 0 at $DIR/combine_clone_of_primitives.rs:9:5: 9:11 +- _6 = &(*_7); // scope 0 at $DIR/combine_clone_of_primitives.rs:9:5: 9:11 +- _5 = <u64 as Clone>::clone(move _6) -> [return: bb2, unwind: bb4]; // scope 0 at $DIR/combine_clone_of_primitives.rs:9:5: 9:11 - // mir::Constant - // + span: $DIR/combine_clone_of_primitives.rs:9:5: 9:11 - // + literal: Const { ty: for<'r> fn(&'r u64) -> u64 {<u64 as Clone>::clone}, val: Value(Scalar(<ZST>)) } -+ _10 = _3; // scope 1 at $DIR/combine_clone_of_primitives.rs:9:5: 9:11 -+ _9 = _10; // scope 1 at $DIR/combine_clone_of_primitives.rs:9:5: 9:11 -+ _8 = (*_9); // scope 1 at $DIR/combine_clone_of_primitives.rs:9:5: 9:11 -+ goto -> bb2; // scope 1 at $DIR/combine_clone_of_primitives.rs:9:5: 9:11 ++ _6 = _7; // scope 0 at $DIR/combine_clone_of_primitives.rs:9:5: 9:11 ++ _5 = (*_6); // scope 0 at $DIR/combine_clone_of_primitives.rs:9:5: 9:11 ++ goto -> bb2; // scope 0 at $DIR/combine_clone_of_primitives.rs:9:5: 9:11 } bb2: { - StorageDead(_9); // scope 1 at $DIR/combine_clone_of_primitives.rs:9:10: 9:11 - StorageLive(_11); // scope 1 at $DIR/combine_clone_of_primitives.rs:10:5: 10:16 - StorageLive(_12); // scope 1 at $DIR/combine_clone_of_primitives.rs:10:5: 10:16 - StorageLive(_13); // scope 1 at $DIR/combine_clone_of_primitives.rs:10:5: 10:16 -- _13 = &(*_4); // scope 1 at $DIR/combine_clone_of_primitives.rs:10:5: 10:16 -- _12 = &(*_13); // scope 1 at $DIR/combine_clone_of_primitives.rs:10:5: 10:16 -- _11 = <[f32; 3] as Clone>::clone(move _12) -> [return: bb3, unwind: bb4]; // scope 1 at $DIR/combine_clone_of_primitives.rs:10:5: 10:16 + StorageDead(_6); // scope 0 at $DIR/combine_clone_of_primitives.rs:9:10: 9:11 + StorageLive(_8); // scope 0 at $DIR/combine_clone_of_primitives.rs:10:5: 10:16 + StorageLive(_9); // scope 0 at $DIR/combine_clone_of_primitives.rs:10:5: 10:16 + StorageLive(_10); // scope 0 at $DIR/combine_clone_of_primitives.rs:10:5: 10:16 + _10 = &((*_1).2: [f32; 3]); // scope 0 at $DIR/combine_clone_of_primitives.rs:10:5: 10:16 +- _9 = &(*_10); // scope 0 at $DIR/combine_clone_of_primitives.rs:10:5: 10:16 +- _8 = <[f32; 3] as Clone>::clone(move _9) -> [return: bb3, unwind: bb4]; // scope 0 at $DIR/combine_clone_of_primitives.rs:10:5: 10:16 - // mir::Constant - // + span: $DIR/combine_clone_of_primitives.rs:10:5: 10:16 - // + literal: Const { ty: for<'r> fn(&'r [f32; 3]) -> [f32; 3] {<[f32; 3] as Clone>::clone}, val: Value(Scalar(<ZST>)) } -+ _13 = _4; // scope 1 at $DIR/combine_clone_of_primitives.rs:10:5: 10:16 -+ _12 = _13; // scope 1 at $DIR/combine_clone_of_primitives.rs:10:5: 10:16 -+ _11 = (*_12); // scope 1 at $DIR/combine_clone_of_primitives.rs:10:5: 10:16 -+ goto -> bb3; // scope 1 at $DIR/combine_clone_of_primitives.rs:10:5: 10:16 ++ _9 = _10; // scope 0 at $DIR/combine_clone_of_primitives.rs:10:5: 10:16 ++ _8 = (*_9); // scope 0 at $DIR/combine_clone_of_primitives.rs:10:5: 10:16 ++ goto -> bb3; // scope 0 at $DIR/combine_clone_of_primitives.rs:10:5: 10:16 } bb3: { - StorageDead(_12); // scope 1 at $DIR/combine_clone_of_primitives.rs:10:15: 10:16 - Deinit(_0); // scope 1 at $DIR/combine_clone_of_primitives.rs:6:10: 6:15 - (_0.0: T) = move _5; // scope 1 at $DIR/combine_clone_of_primitives.rs:6:10: 6:15 - (_0.1: u64) = move _8; // scope 1 at $DIR/combine_clone_of_primitives.rs:6:10: 6:15 - (_0.2: [f32; 3]) = move _11; // scope 1 at $DIR/combine_clone_of_primitives.rs:6:10: 6:15 - StorageDead(_13); // scope 1 at $DIR/combine_clone_of_primitives.rs:6:14: 6:15 - StorageDead(_11); // scope 1 at $DIR/combine_clone_of_primitives.rs:6:14: 6:15 - StorageDead(_10); // scope 1 at $DIR/combine_clone_of_primitives.rs:6:14: 6:15 - StorageDead(_8); // scope 1 at $DIR/combine_clone_of_primitives.rs:6:14: 6:15 - StorageDead(_7); // scope 1 at $DIR/combine_clone_of_primitives.rs:6:14: 6:15 - StorageDead(_5); // scope 1 at $DIR/combine_clone_of_primitives.rs:6:14: 6:15 - StorageDead(_4); // scope 0 at $DIR/combine_clone_of_primitives.rs:6:14: 6:15 - StorageDead(_3); // scope 0 at $DIR/combine_clone_of_primitives.rs:6:14: 6:15 + StorageDead(_9); // scope 0 at $DIR/combine_clone_of_primitives.rs:10:15: 10:16 + Deinit(_0); // scope 0 at $DIR/combine_clone_of_primitives.rs:6:10: 6:15 + (_0.0: T) = move _2; // scope 0 at $DIR/combine_clone_of_primitives.rs:6:10: 6:15 + (_0.1: u64) = move _5; // scope 0 at $DIR/combine_clone_of_primitives.rs:6:10: 6:15 + (_0.2: [f32; 3]) = move _8; // scope 0 at $DIR/combine_clone_of_primitives.rs:6:10: 6:15 + StorageDead(_8); // scope 0 at $DIR/combine_clone_of_primitives.rs:6:14: 6:15 + StorageDead(_5); // scope 0 at $DIR/combine_clone_of_primitives.rs:6:14: 6:15 StorageDead(_2); // scope 0 at $DIR/combine_clone_of_primitives.rs:6:14: 6:15 + StorageDead(_10); // scope 0 at $DIR/combine_clone_of_primitives.rs:6:14: 6:15 + StorageDead(_7); // scope 0 at $DIR/combine_clone_of_primitives.rs:6:14: 6:15 + StorageDead(_4); // scope 0 at $DIR/combine_clone_of_primitives.rs:6:14: 6:15 return; // scope 0 at $DIR/combine_clone_of_primitives.rs:6:15: 6:15 } bb4 (cleanup): { - drop(_5) -> bb5; // scope 1 at $DIR/combine_clone_of_primitives.rs:6:14: 6:15 + drop(_2) -> bb5; // scope 0 at $DIR/combine_clone_of_primitives.rs:6:14: 6:15 } bb5 (cleanup): { diff --git a/src/test/mir-opt/const_promotion_extern_static.BAR.PromoteTemps.diff b/src/test/mir-opt/const_promotion_extern_static.BAR.PromoteTemps.diff index 816c598059d..268d8f46464 100644 --- a/src/test/mir-opt/const_promotion_extern_static.BAR.PromoteTemps.diff +++ b/src/test/mir-opt/const_promotion_extern_static.BAR.PromoteTemps.diff @@ -40,11 +40,11 @@ - StorageDead(_5); // scope 0 at $DIR/const-promotion-extern-static.rs:9:43: 9:44 - StorageDead(_3); // scope 0 at $DIR/const-promotion-extern-static.rs:9:43: 9:44 StorageDead(_1); // scope 0 at $DIR/const-promotion-extern-static.rs:9:43: 9:44 - return; // scope 0 at $DIR/const-promotion-extern-static.rs:9:1: 9:45 + return; // scope 0 at $DIR/const-promotion-extern-static.rs:9:1: 9:28 } bb2 (cleanup): { - resume; // scope 0 at $DIR/const-promotion-extern-static.rs:9:1: 9:45 + resume; // scope 0 at $DIR/const-promotion-extern-static.rs:9:1: 9:28 } - } - diff --git a/src/test/mir-opt/const_promotion_extern_static.BOP.mir_map.0.mir b/src/test/mir-opt/const_promotion_extern_static.BOP.mir_map.0.mir index 4d24387afc7..2e63c2c25fa 100644 --- a/src/test/mir-opt/const_promotion_extern_static.BOP.mir_map.0.mir +++ b/src/test/mir-opt/const_promotion_extern_static.BOP.mir_map.0.mir @@ -12,6 +12,6 @@ static BOP: &i32 = { _1 = &_2; // scope 0 at $DIR/const-promotion-extern-static.rs:16:20: 16:23 _0 = &(*_1); // scope 0 at $DIR/const-promotion-extern-static.rs:16:20: 16:23 StorageDead(_1); // scope 0 at $DIR/const-promotion-extern-static.rs:16:22: 16:23 - return; // scope 0 at $DIR/const-promotion-extern-static.rs:16:1: 16:24 + return; // scope 0 at $DIR/const-promotion-extern-static.rs:16:1: 16:17 } } diff --git a/src/test/mir-opt/const_promotion_extern_static.FOO.PromoteTemps.diff b/src/test/mir-opt/const_promotion_extern_static.FOO.PromoteTemps.diff index 096b427bb75..322a1b206f9 100644 --- a/src/test/mir-opt/const_promotion_extern_static.FOO.PromoteTemps.diff +++ b/src/test/mir-opt/const_promotion_extern_static.FOO.PromoteTemps.diff @@ -42,11 +42,11 @@ - StorageDead(_5); // scope 0 at $DIR/const-promotion-extern-static.rs:13:54: 13:55 - StorageDead(_3); // scope 0 at $DIR/const-promotion-extern-static.rs:13:54: 13:55 StorageDead(_1); // scope 0 at $DIR/const-promotion-extern-static.rs:13:54: 13:55 - return; // scope 0 at $DIR/const-promotion-extern-static.rs:13:1: 13:56 + return; // scope 0 at $DIR/const-promotion-extern-static.rs:13:1: 13:28 } bb2 (cleanup): { - resume; // scope 0 at $DIR/const-promotion-extern-static.rs:13:1: 13:56 + resume; // scope 0 at $DIR/const-promotion-extern-static.rs:13:1: 13:28 } } - diff --git a/src/test/mir-opt/enum_cast.bar.mir_map.0.mir b/src/test/mir-opt/enum_cast.bar.mir_map.0.mir new file mode 100644 index 00000000000..1b4a469135c --- /dev/null +++ b/src/test/mir-opt/enum_cast.bar.mir_map.0.mir @@ -0,0 +1,13 @@ +// MIR for `bar` 0 mir_map + +fn bar(_1: Bar) -> usize { + debug bar => _1; // in scope 0 at $DIR/enum_cast.rs:22:8: 22:11 + let mut _0: usize; // return place in scope 0 at $DIR/enum_cast.rs:22:21: 22:26 + let mut _2: isize; // in scope 0 at $DIR/enum_cast.rs:23:5: 23:8 + + bb0: { + _2 = discriminant(_1); // scope 0 at $DIR/enum_cast.rs:23:5: 23:17 + _0 = move _2 as usize (Misc); // scope 0 at $DIR/enum_cast.rs:23:5: 23:17 + return; // scope 0 at $DIR/enum_cast.rs:24:2: 24:2 + } +} diff --git a/src/test/mir-opt/enum_cast.boo.mir_map.0.mir b/src/test/mir-opt/enum_cast.boo.mir_map.0.mir new file mode 100644 index 00000000000..7724e89a228 --- /dev/null +++ b/src/test/mir-opt/enum_cast.boo.mir_map.0.mir @@ -0,0 +1,13 @@ +// MIR for `boo` 0 mir_map + +fn boo(_1: Boo) -> usize { + debug boo => _1; // in scope 0 at $DIR/enum_cast.rs:26:8: 26:11 + let mut _0: usize; // return place in scope 0 at $DIR/enum_cast.rs:26:21: 26:26 + let mut _2: u8; // in scope 0 at $DIR/enum_cast.rs:27:5: 27:8 + + bb0: { + _2 = discriminant(_1); // scope 0 at $DIR/enum_cast.rs:27:5: 27:17 + _0 = move _2 as usize (Misc); // scope 0 at $DIR/enum_cast.rs:27:5: 27:17 + return; // scope 0 at $DIR/enum_cast.rs:28:2: 28:2 + } +} diff --git a/src/test/mir-opt/enum_cast.droppy.mir_map.0.mir b/src/test/mir-opt/enum_cast.droppy.mir_map.0.mir new file mode 100644 index 00000000000..a9dcfadae75 --- /dev/null +++ b/src/test/mir-opt/enum_cast.droppy.mir_map.0.mir @@ -0,0 +1,54 @@ +// MIR for `droppy` 0 mir_map + +fn droppy() -> () { + let mut _0: (); // return place in scope 0 at $DIR/enum_cast.rs:39:13: 39:13 + let _1: (); // in scope 0 at $DIR/enum_cast.rs:40:5: 45:6 + let _2: Droppy; // in scope 0 at $DIR/enum_cast.rs:41:13: 41:14 + let mut _4: isize; // in scope 0 at $DIR/enum_cast.rs:44:17: 44:18 + let _5: Droppy; // in scope 0 at $DIR/enum_cast.rs:46:9: 46:10 + scope 1 { + debug x => _2; // in scope 1 at $DIR/enum_cast.rs:41:13: 41:14 + scope 2 { + debug y => _3; // in scope 2 at $DIR/enum_cast.rs:44:13: 44:14 + } + scope 3 { + let _3: usize; // in scope 3 at $DIR/enum_cast.rs:44:13: 44:14 + } + } + scope 4 { + debug z => _5; // in scope 4 at $DIR/enum_cast.rs:46:9: 46:10 + } + + bb0: { + StorageLive(_1); // scope 0 at $DIR/enum_cast.rs:40:5: 45:6 + StorageLive(_2); // scope 0 at $DIR/enum_cast.rs:41:13: 41:14 + _2 = Droppy::C; // scope 0 at $DIR/enum_cast.rs:41:17: 41:26 + FakeRead(ForLet(None), _2); // scope 0 at $DIR/enum_cast.rs:41:13: 41:14 + StorageLive(_3); // scope 3 at $DIR/enum_cast.rs:44:13: 44:14 + _4 = discriminant(_2); // scope 3 at $DIR/enum_cast.rs:44:17: 44:27 + _3 = move _4 as usize (Misc); // scope 3 at $DIR/enum_cast.rs:44:17: 44:27 + FakeRead(ForLet(None), _3); // scope 3 at $DIR/enum_cast.rs:44:13: 44:14 + _1 = const (); // scope 0 at $DIR/enum_cast.rs:40:5: 45:6 + StorageDead(_3); // scope 1 at $DIR/enum_cast.rs:45:5: 45:6 + drop(_2) -> [return: bb1, unwind: bb3]; // scope 0 at $DIR/enum_cast.rs:45:5: 45:6 + } + + bb1: { + StorageDead(_2); // scope 0 at $DIR/enum_cast.rs:45:5: 45:6 + StorageDead(_1); // scope 0 at $DIR/enum_cast.rs:45:5: 45:6 + StorageLive(_5); // scope 0 at $DIR/enum_cast.rs:46:9: 46:10 + _5 = Droppy::B; // scope 0 at $DIR/enum_cast.rs:46:13: 46:22 + FakeRead(ForLet(None), _5); // scope 0 at $DIR/enum_cast.rs:46:9: 46:10 + _0 = const (); // scope 0 at $DIR/enum_cast.rs:39:13: 47:2 + drop(_5) -> [return: bb2, unwind: bb3]; // scope 0 at $DIR/enum_cast.rs:47:1: 47:2 + } + + bb2: { + StorageDead(_5); // scope 0 at $DIR/enum_cast.rs:47:1: 47:2 + return; // scope 0 at $DIR/enum_cast.rs:47:2: 47:2 + } + + bb3 (cleanup): { + resume; // scope 0 at $DIR/enum_cast.rs:39:1: 47:2 + } +} diff --git a/src/test/mir-opt/enum_cast.foo.mir_map.0.mir b/src/test/mir-opt/enum_cast.foo.mir_map.0.mir new file mode 100644 index 00000000000..d89dc951923 --- /dev/null +++ b/src/test/mir-opt/enum_cast.foo.mir_map.0.mir @@ -0,0 +1,13 @@ +// MIR for `foo` 0 mir_map + +fn foo(_1: Foo) -> usize { + debug foo => _1; // in scope 0 at $DIR/enum_cast.rs:18:8: 18:11 + let mut _0: usize; // return place in scope 0 at $DIR/enum_cast.rs:18:21: 18:26 + let mut _2: isize; // in scope 0 at $DIR/enum_cast.rs:19:5: 19:8 + + bb0: { + _2 = discriminant(_1); // scope 0 at $DIR/enum_cast.rs:19:5: 19:17 + _0 = move _2 as usize (Misc); // scope 0 at $DIR/enum_cast.rs:19:5: 19:17 + return; // scope 0 at $DIR/enum_cast.rs:20:2: 20:2 + } +} diff --git a/src/test/mir-opt/enum_cast.rs b/src/test/mir-opt/enum_cast.rs new file mode 100644 index 00000000000..090142aaf35 --- /dev/null +++ b/src/test/mir-opt/enum_cast.rs @@ -0,0 +1,50 @@ +// EMIT_MIR enum_cast.foo.mir_map.0.mir +// EMIT_MIR enum_cast.bar.mir_map.0.mir +// EMIT_MIR enum_cast.boo.mir_map.0.mir + +enum Foo { + A +} + +enum Bar { + A, B +} + +#[repr(u8)] +enum Boo { + A, B +} + +fn foo(foo: Foo) -> usize { + foo as usize +} + +fn bar(bar: Bar) -> usize { + bar as usize +} + +fn boo(boo: Boo) -> usize { + boo as usize +} + +// EMIT_MIR enum_cast.droppy.mir_map.0.mir +enum Droppy { + A, B, C +} + +impl Drop for Droppy { + fn drop(&mut self) {} +} + +fn droppy() { + { + let x = Droppy::C; + // remove this entire test once `cenum_impl_drop_cast` becomes a hard error + #[allow(cenum_impl_drop_cast)] + let y = x as usize; + } + let z = Droppy::B; +} + +fn main() { +} diff --git a/src/test/mir-opt/inline/caller-with-trivial-bound.rs b/src/test/mir-opt/inline/caller-with-trivial-bound.rs new file mode 100644 index 00000000000..8545db89414 --- /dev/null +++ b/src/test/mir-opt/inline/caller-with-trivial-bound.rs @@ -0,0 +1,26 @@ +// ignore-wasm32 compiled with panic=abort by default +// needs-unwind + +#![crate_type = "lib"] +pub trait Factory<T> { + type Item; +} + +pub struct IntFactory; + +impl<T> Factory<T> for IntFactory { + type Item = usize; +} + +// EMIT_MIR caller_with_trivial_bound.foo.Inline.diff +pub fn foo<T>() +where + IntFactory: Factory<T>, +{ + let mut x: <IntFactory as Factory<T>>::Item = bar::<T>(); +} + +#[inline(always)] +pub fn bar<T>() -> <IntFactory as Factory<T>>::Item { + 0usize +} diff --git a/src/test/mir-opt/inline/caller_with_trivial_bound.foo.Inline.diff b/src/test/mir-opt/inline/caller_with_trivial_bound.foo.Inline.diff new file mode 100644 index 00000000000..5d236373a4c --- /dev/null +++ b/src/test/mir-opt/inline/caller_with_trivial_bound.foo.Inline.diff @@ -0,0 +1,33 @@ +- // MIR for `foo` before Inline ++ // MIR for `foo` after Inline + + fn foo() -> () { + let mut _0: (); // return place in scope 0 at $DIR/caller-with-trivial-bound.rs:17:1: 17:1 + let mut _1: <IntFactory as Factory<T>>::Item; // in scope 0 at $DIR/caller-with-trivial-bound.rs:20:9: 20:14 + scope 1 { + debug x => _1; // in scope 1 at $DIR/caller-with-trivial-bound.rs:20:9: 20:14 + } + + bb0: { + StorageLive(_1); // scope 0 at $DIR/caller-with-trivial-bound.rs:20:9: 20:14 + _1 = bar::<T>() -> bb1; // scope 0 at $DIR/caller-with-trivial-bound.rs:20:51: 20:61 + // mir::Constant + // + span: $DIR/caller-with-trivial-bound.rs:20:51: 20:59 + // + literal: Const { ty: fn() -> <IntFactory as Factory<T>>::Item {bar::<T>}, val: Value(Scalar(<ZST>)) } + } + + bb1: { + _0 = const (); // scope 0 at $DIR/caller-with-trivial-bound.rs:19:1: 21:2 + drop(_1) -> [return: bb2, unwind: bb3]; // scope 0 at $DIR/caller-with-trivial-bound.rs:21:1: 21:2 + } + + bb2: { + StorageDead(_1); // scope 0 at $DIR/caller-with-trivial-bound.rs:21:1: 21:2 + return; // scope 0 at $DIR/caller-with-trivial-bound.rs:21:2: 21:2 + } + + bb3 (cleanup): { + resume; // scope 0 at $DIR/caller-with-trivial-bound.rs:16:1: 21:2 + } + } + diff --git a/src/test/mir-opt/inline/inline_cycle.one.Inline.diff b/src/test/mir-opt/inline/inline_cycle.one.Inline.diff index b732e7cdb9b..3b32cb80911 100644 --- a/src/test/mir-opt/inline/inline_cycle.one.Inline.diff +++ b/src/test/mir-opt/inline/inline_cycle.one.Inline.diff @@ -5,17 +5,20 @@ let mut _0: (); // return place in scope 0 at $DIR/inline-cycle.rs:13:10: 13:10 let _1: (); // in scope 0 at $DIR/inline-cycle.rs:14:5: 14:24 + scope 1 (inlined <C as Call>::call) { // at $DIR/inline-cycle.rs:14:5: 14:24 ++ scope 2 (inlined <A<C> as Call>::call) { // at $DIR/inline-cycle.rs:43:9: 43:23 ++ scope 3 (inlined <B<C> as Call>::call) { // at $DIR/inline-cycle.rs:28:9: 28:31 ++ } ++ } + } bb0: { StorageLive(_1); // scope 0 at $DIR/inline-cycle.rs:14:5: 14:24 - _1 = <C as Call>::call() -> bb1; // scope 0 at $DIR/inline-cycle.rs:14:5: 14:24 -+ _1 = <A<C> as Call>::call() -> bb1; // scope 1 at $DIR/inline-cycle.rs:43:9: 43:23 ++ _1 = <C as Call>::call() -> bb1; // scope 3 at $DIR/inline-cycle.rs:36:9: 36:28 // mir::Constant - // + span: $DIR/inline-cycle.rs:14:5: 14:22 -- // + literal: Const { ty: fn() {<C as Call>::call}, val: Value(Scalar(<ZST>)) } -+ // + span: $DIR/inline-cycle.rs:43:9: 43:21 -+ // + literal: Const { ty: fn() {<A<C> as Call>::call}, val: Value(Scalar(<ZST>)) } ++ // + span: $DIR/inline-cycle.rs:36:9: 36:26 + // + literal: Const { ty: fn() {<C as Call>::call}, val: Value(Scalar(<ZST>)) } } bb1: { diff --git a/src/test/mir-opt/inline/inline_cycle.two.Inline.diff b/src/test/mir-opt/inline/inline_cycle.two.Inline.diff index eac5bf8edec..c7f8a64afcd 100644 --- a/src/test/mir-opt/inline/inline_cycle.two.Inline.diff +++ b/src/test/mir-opt/inline/inline_cycle.two.Inline.diff @@ -11,6 +11,9 @@ + let _3: (); // in scope 1 at $DIR/inline-cycle.rs:54:5: 54:8 + let mut _4: fn() {f}; // in scope 1 at $DIR/inline-cycle.rs:54:5: 54:6 + scope 2 (inlined <fn() {f} as FnOnce<()>>::call_once - shim(fn() {f})) { // at $DIR/inline-cycle.rs:54:5: 54:8 ++ scope 3 (inlined f) { // at $SRC_DIR/core/src/ops/function.rs:LL:COL ++ let _6: (); // in scope 3 at $DIR/inline-cycle.rs:59:5: 59:12 ++ } + } + } @@ -21,19 +24,26 @@ + _2 = f; // scope 0 at $DIR/inline-cycle.rs:49:5: 49:12 // mir::Constant - // + span: $DIR/inline-cycle.rs:49:5: 49:9 -- // + literal: Const { ty: fn(fn() {f}) {call::<fn() {f}>}, val: Value(Scalar(<ZST>)) } -- // mir::Constant - // + span: $DIR/inline-cycle.rs:49:10: 49:11 - // + literal: Const { ty: fn() {f}, val: Value(Scalar(<ZST>)) } ++ // + span: $DIR/inline-cycle.rs:49:10: 49:11 ++ // + literal: Const { ty: fn() {f}, val: Value(Scalar(<ZST>)) } + StorageLive(_3); // scope 1 at $DIR/inline-cycle.rs:54:5: 54:8 + StorageLive(_4); // scope 1 at $DIR/inline-cycle.rs:54:5: 54:6 + _4 = move _2; // scope 1 at $DIR/inline-cycle.rs:54:5: 54:6 + StorageLive(_5); // scope 1 at $DIR/inline-cycle.rs:54:5: 54:8 + _5 = const (); // scope 1 at $DIR/inline-cycle.rs:54:5: 54:8 -+ _3 = move _4() -> bb1; // scope 2 at $SRC_DIR/core/src/ops/function.rs:LL:COL ++ StorageLive(_6); // scope 3 at $DIR/inline-cycle.rs:59:5: 59:12 ++ _6 = call::<fn() {f}>(f) -> bb1; // scope 3 at $DIR/inline-cycle.rs:59:5: 59:12 ++ // mir::Constant ++ // + span: $DIR/inline-cycle.rs:59:5: 59:9 + // + literal: Const { ty: fn(fn() {f}) {call::<fn() {f}>}, val: Value(Scalar(<ZST>)) } + // mir::Constant +- // + span: $DIR/inline-cycle.rs:49:10: 49:11 ++ // + span: $DIR/inline-cycle.rs:59:10: 59:11 + // + literal: Const { ty: fn() {f}, val: Value(Scalar(<ZST>)) } } bb1: { ++ StorageDead(_6); // scope 3 at $DIR/inline-cycle.rs:59:12: 59:13 + StorageDead(_5); // scope 1 at $DIR/inline-cycle.rs:54:5: 54:8 + StorageDead(_4); // scope 1 at $DIR/inline-cycle.rs:54:7: 54:8 + StorageDead(_3); // scope 1 at $DIR/inline-cycle.rs:54:8: 54:9 diff --git a/src/test/mir-opt/inline/inline_cycle_generic.main.Inline.diff b/src/test/mir-opt/inline/inline_cycle_generic.main.Inline.diff index 267f53a8dfe..2a19b21510a 100644 --- a/src/test/mir-opt/inline/inline_cycle_generic.main.Inline.diff +++ b/src/test/mir-opt/inline/inline_cycle_generic.main.Inline.diff @@ -4,12 +4,22 @@ fn main() -> () { let mut _0: (); // return place in scope 0 at $DIR/inline-cycle-generic.rs:8:11: 8:11 let _1: (); // in scope 0 at $DIR/inline-cycle-generic.rs:9:5: 9:24 ++ scope 1 (inlined <C as Call>::call) { // at $DIR/inline-cycle-generic.rs:9:5: 9:24 ++ scope 2 (inlined <B<A> as Call>::call) { // at $DIR/inline-cycle-generic.rs:38:9: 38:31 ++ scope 3 (inlined <A as Call>::call) { // at $DIR/inline-cycle-generic.rs:31:9: 31:28 ++ scope 4 (inlined <B<C> as Call>::call) { // at $DIR/inline-cycle-generic.rs:23:9: 23:31 ++ } ++ } ++ } ++ } bb0: { StorageLive(_1); // scope 0 at $DIR/inline-cycle-generic.rs:9:5: 9:24 - _1 = <C as Call>::call() -> bb1; // scope 0 at $DIR/inline-cycle-generic.rs:9:5: 9:24 +- _1 = <C as Call>::call() -> bb1; // scope 0 at $DIR/inline-cycle-generic.rs:9:5: 9:24 ++ _1 = <C as Call>::call() -> bb1; // scope 4 at $DIR/inline-cycle-generic.rs:31:9: 31:28 // mir::Constant - // + span: $DIR/inline-cycle-generic.rs:9:5: 9:22 +- // + span: $DIR/inline-cycle-generic.rs:9:5: 9:22 ++ // + span: $DIR/inline-cycle-generic.rs:31:9: 31:26 // + literal: Const { ty: fn() {<C as Call>::call}, val: Value(Scalar(<ZST>)) } } @@ -17,6 +27,10 @@ StorageDead(_1); // scope 0 at $DIR/inline-cycle-generic.rs:9:24: 9:25 _0 = const (); // scope 0 at $DIR/inline-cycle-generic.rs:8:11: 10:2 return; // scope 0 at $DIR/inline-cycle-generic.rs:10:2: 10:2 ++ } ++ ++ bb2 (cleanup): { ++ resume; // scope 0 at $DIR/inline-cycle-generic.rs:8:1: 10:2 } } diff --git a/src/test/mir-opt/issue_41697.{impl#0}-{constant#0}.SimplifyCfg-promote-consts.after.32bit.mir b/src/test/mir-opt/issue_41697.{impl#0}-{constant#0}.SimplifyCfg-promote-consts.after.32bit.mir index db9caf84314..701e291f46e 100644 --- a/src/test/mir-opt/issue_41697.{impl#0}-{constant#0}.SimplifyCfg-promote-consts.after.32bit.mir +++ b/src/test/mir-opt/issue_41697.{impl#0}-{constant#0}.SimplifyCfg-promote-consts.after.32bit.mir @@ -1,6 +1,6 @@ -// MIR for `<impl at $DIR/issue-41697.rs:18:1: 22:2>::{constant#0}` after SimplifyCfg-promote-consts +// MIR for `<impl at $DIR/issue-41697.rs:18:1: 18:23>::{constant#0}` after SimplifyCfg-promote-consts -<impl at $DIR/issue-41697.rs:18:1: 22:2>::{constant#0}: usize = { +<impl at $DIR/issue-41697.rs:18:1: 18:23>::{constant#0}: usize = { let mut _0: usize; // return place in scope 0 at $DIR/issue-41697.rs:18:19: 18:22 let mut _1: (usize, bool); // in scope 0 at $DIR/issue-41697.rs:18:19: 18:22 diff --git a/src/test/mir-opt/issue_41697.{impl#0}-{constant#0}.SimplifyCfg-promote-consts.after.64bit.mir b/src/test/mir-opt/issue_41697.{impl#0}-{constant#0}.SimplifyCfg-promote-consts.after.64bit.mir index db9caf84314..701e291f46e 100644 --- a/src/test/mir-opt/issue_41697.{impl#0}-{constant#0}.SimplifyCfg-promote-consts.after.64bit.mir +++ b/src/test/mir-opt/issue_41697.{impl#0}-{constant#0}.SimplifyCfg-promote-consts.after.64bit.mir @@ -1,6 +1,6 @@ -// MIR for `<impl at $DIR/issue-41697.rs:18:1: 22:2>::{constant#0}` after SimplifyCfg-promote-consts +// MIR for `<impl at $DIR/issue-41697.rs:18:1: 18:23>::{constant#0}` after SimplifyCfg-promote-consts -<impl at $DIR/issue-41697.rs:18:1: 22:2>::{constant#0}: usize = { +<impl at $DIR/issue-41697.rs:18:1: 18:23>::{constant#0}: usize = { let mut _0: usize; // return place in scope 0 at $DIR/issue-41697.rs:18:19: 18:22 let mut _1: (usize, bool); // in scope 0 at $DIR/issue-41697.rs:18:19: 18:22 diff --git a/src/test/mir-opt/retag.{impl#0}-foo.SimplifyCfg-elaborate-drops.after.mir b/src/test/mir-opt/retag.{impl#0}-foo.SimplifyCfg-elaborate-drops.after.mir index f9ed3932d33..980f07d5f10 100644 --- a/src/test/mir-opt/retag.{impl#0}-foo.SimplifyCfg-elaborate-drops.after.mir +++ b/src/test/mir-opt/retag.{impl#0}-foo.SimplifyCfg-elaborate-drops.after.mir @@ -1,6 +1,6 @@ -// MIR for `<impl at $DIR/retag.rs:11:1: 19:2>::foo` after SimplifyCfg-elaborate-drops +// MIR for `<impl at $DIR/retag.rs:11:1: 11:10>::foo` after SimplifyCfg-elaborate-drops -fn <impl at $DIR/retag.rs:11:1: 19:2>::foo(_1: &Test, _2: &mut i32) -> &mut i32 { +fn <impl at $DIR/retag.rs:11:1: 11:10>::foo(_1: &Test, _2: &mut i32) -> &mut i32 { debug self => _1; // in scope 0 at $DIR/retag.rs:13:16: 13:21 debug x => _2; // in scope 0 at $DIR/retag.rs:13:23: 13:24 let mut _0: &mut i32; // return place in scope 0 at $DIR/retag.rs:13:42: 13:53 diff --git a/src/test/mir-opt/retag.{impl#0}-foo_shr.SimplifyCfg-elaborate-drops.after.mir b/src/test/mir-opt/retag.{impl#0}-foo_shr.SimplifyCfg-elaborate-drops.after.mir index 87a8603a931..9c252d63fc7 100644 --- a/src/test/mir-opt/retag.{impl#0}-foo_shr.SimplifyCfg-elaborate-drops.after.mir +++ b/src/test/mir-opt/retag.{impl#0}-foo_shr.SimplifyCfg-elaborate-drops.after.mir @@ -1,6 +1,6 @@ -// MIR for `<impl at $DIR/retag.rs:11:1: 19:2>::foo_shr` after SimplifyCfg-elaborate-drops +// MIR for `<impl at $DIR/retag.rs:11:1: 11:10>::foo_shr` after SimplifyCfg-elaborate-drops -fn <impl at $DIR/retag.rs:11:1: 19:2>::foo_shr(_1: &Test, _2: &i32) -> &i32 { +fn <impl at $DIR/retag.rs:11:1: 11:10>::foo_shr(_1: &Test, _2: &i32) -> &i32 { debug self => _1; // in scope 0 at $DIR/retag.rs:16:20: 16:25 debug x => _2; // in scope 0 at $DIR/retag.rs:16:27: 16:28 let mut _0: &i32; // return place in scope 0 at $DIR/retag.rs:16:42: 16:49 diff --git a/src/test/mir-opt/storage_live_dead_in_statics.XXX.mir_map.0.mir b/src/test/mir-opt/storage_live_dead_in_statics.XXX.mir_map.0.mir index e0875ab0069..2c4738aa866 100644 --- a/src/test/mir-opt/storage_live_dead_in_statics.XXX.mir_map.0.mir +++ b/src/test/mir-opt/storage_live_dead_in_statics.XXX.mir_map.0.mir @@ -198,6 +198,6 @@ static XXX: &Foo = { _0 = &(*_1); // scope 0 at $DIR/storage_live_dead_in_statics.rs:5:28: 23:2 StorageDead(_5); // scope 0 at $DIR/storage_live_dead_in_statics.rs:23:1: 23:2 StorageDead(_1); // scope 0 at $DIR/storage_live_dead_in_statics.rs:23:1: 23:2 - return; // scope 0 at $DIR/storage_live_dead_in_statics.rs:5:1: 23:3 + return; // scope 0 at $DIR/storage_live_dead_in_statics.rs:5:1: 5:25 } } diff --git a/src/test/mir-opt/unusual_item_types.{impl#0}-ASSOCIATED_CONSTANT.mir_map.0.32bit.mir b/src/test/mir-opt/unusual_item_types.{impl#0}-ASSOCIATED_CONSTANT.mir_map.0.32bit.mir index a046a89bc8c..c41fe61d48b 100644 --- a/src/test/mir-opt/unusual_item_types.{impl#0}-ASSOCIATED_CONSTANT.mir_map.0.32bit.mir +++ b/src/test/mir-opt/unusual_item_types.{impl#0}-ASSOCIATED_CONSTANT.mir_map.0.32bit.mir @@ -1,10 +1,10 @@ -// MIR for `<impl at $DIR/unusual-item-types.rs:9:1: 11:2>::ASSOCIATED_CONSTANT` 0 mir_map +// MIR for `<impl at $DIR/unusual-item-types.rs:9:1: 9:7>::ASSOCIATED_CONSTANT` 0 mir_map -const <impl at $DIR/unusual-item-types.rs:9:1: 11:2>::ASSOCIATED_CONSTANT: i32 = { +const <impl at $DIR/unusual-item-types.rs:9:1: 9:7>::ASSOCIATED_CONSTANT: i32 = { let mut _0: i32; // return place in scope 0 at $DIR/unusual-item-types.rs:10:32: 10:35 bb0: { _0 = const 2_i32; // scope 0 at $DIR/unusual-item-types.rs:10:38: 10:39 - return; // scope 0 at $DIR/unusual-item-types.rs:10:5: 10:40 + return; // scope 0 at $DIR/unusual-item-types.rs:10:5: 10:35 } } diff --git a/src/test/mir-opt/unusual_item_types.{impl#0}-ASSOCIATED_CONSTANT.mir_map.0.64bit.mir b/src/test/mir-opt/unusual_item_types.{impl#0}-ASSOCIATED_CONSTANT.mir_map.0.64bit.mir index a046a89bc8c..c41fe61d48b 100644 --- a/src/test/mir-opt/unusual_item_types.{impl#0}-ASSOCIATED_CONSTANT.mir_map.0.64bit.mir +++ b/src/test/mir-opt/unusual_item_types.{impl#0}-ASSOCIATED_CONSTANT.mir_map.0.64bit.mir @@ -1,10 +1,10 @@ -// MIR for `<impl at $DIR/unusual-item-types.rs:9:1: 11:2>::ASSOCIATED_CONSTANT` 0 mir_map +// MIR for `<impl at $DIR/unusual-item-types.rs:9:1: 9:7>::ASSOCIATED_CONSTANT` 0 mir_map -const <impl at $DIR/unusual-item-types.rs:9:1: 11:2>::ASSOCIATED_CONSTANT: i32 = { +const <impl at $DIR/unusual-item-types.rs:9:1: 9:7>::ASSOCIATED_CONSTANT: i32 = { let mut _0: i32; // return place in scope 0 at $DIR/unusual-item-types.rs:10:32: 10:35 bb0: { _0 = const 2_i32; // scope 0 at $DIR/unusual-item-types.rs:10:38: 10:39 - return; // scope 0 at $DIR/unusual-item-types.rs:10:5: 10:40 + return; // scope 0 at $DIR/unusual-item-types.rs:10:5: 10:35 } } diff --git a/src/test/run-make-fulldeps/coverage-reports/expected_show_coverage.uses_crate.txt b/src/test/run-make-fulldeps/coverage-reports/expected_show_coverage.uses_crate.txt index 55a49548cb5..65eb1008dd8 100644 --- a/src/test/run-make-fulldeps/coverage-reports/expected_show_coverage.uses_crate.txt +++ b/src/test/run-make-fulldeps/coverage-reports/expected_show_coverage.uses_crate.txt @@ -36,12 +36,12 @@ 22| 2| println!("used_only_from_this_lib_crate_generic_function with {:?}", arg); 23| 2|} ------------------ - | used_crate::used_only_from_this_lib_crate_generic_function::<&str>: + | used_crate::used_only_from_this_lib_crate_generic_function::<alloc::vec::Vec<i32>>: | 21| 1|pub fn used_only_from_this_lib_crate_generic_function<T: Debug>(arg: T) { | 22| 1| println!("used_only_from_this_lib_crate_generic_function with {:?}", arg); | 23| 1|} ------------------ - | used_crate::used_only_from_this_lib_crate_generic_function::<alloc::vec::Vec<i32>>: + | used_crate::used_only_from_this_lib_crate_generic_function::<&str>: | 21| 1|pub fn used_only_from_this_lib_crate_generic_function<T: Debug>(arg: T) { | 22| 1| println!("used_only_from_this_lib_crate_generic_function with {:?}", arg); | 23| 1|} diff --git a/src/test/run-make/issue-88756-opt-help/Makefile b/src/test/run-make/issue-88756-opt-help/Makefile deleted file mode 100644 index 8ababbf5b4e..00000000000 --- a/src/test/run-make/issue-88756-opt-help/Makefile +++ /dev/null @@ -1,4 +0,0 @@ --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 deleted file mode 100644 index 9b742753f25..00000000000 --- a/src/test/run-make/issue-88756-opt-help/README.md +++ /dev/null @@ -1 +0,0 @@ -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 deleted file mode 100644 index 5cb7ecb649a..00000000000 --- a/src/test/run-make/issue-88756-opt-help/output-default.stdout +++ /dev/null @@ -1,193 +0,0 @@ - -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 deleted file mode 100644 index 5df7576133a..00000000000 --- a/src/test/run-make/issue-88756-opt-help/x.rs +++ /dev/null @@ -1 +0,0 @@ -// nothing to see here diff --git a/src/test/run-make/native-link-modifier-bundle/Makefile b/src/test/run-make/native-link-modifier-bundle/Makefile index 723bb4689fe..e4b0f74ac26 100644 --- a/src/test/run-make/native-link-modifier-bundle/Makefile +++ b/src/test/run-make/native-link-modifier-bundle/Makefile @@ -3,27 +3,31 @@ -include ../../run-make-fulldeps/tools.mk +# We're using the llvm-nm instead of the system nm to ensure it is compatible +# with the LLVM bitcode generated by rustc. +NM = "$(LLVM_BIN_DIR)"/llvm-nm + all: $(call NATIVE_STATICLIB,native-staticlib) # Build a staticlib and a rlib, the `native_func` symbol will be bundled into them $(RUSTC) bundled.rs --crate-type=staticlib --crate-type=rlib - nm $(TMPDIR)/libbundled.a | $(CGREP) -e "T _*native_func" - nm $(TMPDIR)/libbundled.a | $(CGREP) -e "U _*native_func" - nm $(TMPDIR)/libbundled.rlib | $(CGREP) -e "T _*native_func" - nm $(TMPDIR)/libbundled.rlib | $(CGREP) -e "U _*native_func" + $(NM) $(TMPDIR)/libbundled.a | $(CGREP) -e "T _*native_func" + $(NM) $(TMPDIR)/libbundled.a | $(CGREP) -e "U _*native_func" + $(NM) $(TMPDIR)/libbundled.rlib | $(CGREP) -e "T _*native_func" + $(NM) $(TMPDIR)/libbundled.rlib | $(CGREP) -e "U _*native_func" # Build a staticlib and a rlib, the `native_func` symbol will not be bundled into it $(RUSTC) non-bundled.rs --crate-type=staticlib --crate-type=rlib - nm $(TMPDIR)/libnon_bundled.a | $(CGREP) -ve "T _*native_func" - nm $(TMPDIR)/libnon_bundled.a | $(CGREP) -e "U _*native_func" - nm $(TMPDIR)/libnon_bundled.rlib | $(CGREP) -ve "T _*native_func" - nm $(TMPDIR)/libnon_bundled.rlib | $(CGREP) -e "U _*native_func" + $(NM) $(TMPDIR)/libnon_bundled.a | $(CGREP) -ve "T _*native_func" + $(NM) $(TMPDIR)/libnon_bundled.a | $(CGREP) -e "U _*native_func" + $(NM) $(TMPDIR)/libnon_bundled.rlib | $(CGREP) -ve "T _*native_func" + $(NM) $(TMPDIR)/libnon_bundled.rlib | $(CGREP) -e "U _*native_func" # Build a cdylib, `native-staticlib` will not appear on the linker line because it was bundled previously # The cdylib will contain the `native_func` symbol in the end $(RUSTC) cdylib-bundled.rs --crate-type=cdylib --print link-args | $(CGREP) -ve '-l[" ]*native-staticlib' - nm $(call DYLIB,cdylib_bundled) | $(CGREP) -e "[Tt] _*native_func" + $(NM) $(call DYLIB,cdylib_bundled) | $(CGREP) -e "[Tt] _*native_func" # Build a cdylib, `native-staticlib` will appear on the linker line because it was not bundled previously # The cdylib will contain the `native_func` symbol in the end $(RUSTC) cdylib-non-bundled.rs --crate-type=cdylib --print link-args | $(CGREP) -e '-l[" ]*native-staticlib' - nm $(call DYLIB,cdylib_non_bundled) | $(CGREP) -e "[Tt] _*native_func" + $(NM) $(call DYLIB,cdylib_non_bundled) | $(CGREP) -e "[Tt] _*native_func" diff --git a/src/test/run-pass-valgrind/cast-enum-with-dtor.rs b/src/test/run-pass-valgrind/cast-enum-with-dtor.rs index 998d202b117..f29bc50e84c 100644 --- a/src/test/run-pass-valgrind/cast-enum-with-dtor.rs +++ b/src/test/run-pass-valgrind/cast-enum-with-dtor.rs @@ -30,5 +30,5 @@ fn main() { assert_eq!(e as u32, 2); assert_eq!(FLAG.load(Ordering::SeqCst), 0); } - assert_eq!(FLAG.load(Ordering::SeqCst), 0); + assert_eq!(FLAG.load(Ordering::SeqCst), 1); } diff --git a/src/test/rustdoc-gui/docblock-details.goml b/src/test/rustdoc-gui/docblock-details.goml new file mode 100644 index 00000000000..2edbf1e4e2d --- /dev/null +++ b/src/test/rustdoc-gui/docblock-details.goml @@ -0,0 +1,23 @@ +// This ensures that the `<details>`/`<summary>` elements are displayed as expected. +goto: file://|DOC_PATH|/test_docs/details/struct.Details.html +show-text: true +local-storage: {"rustdoc-theme": "dark", "rustdoc-use-system-theme": "false"} +reload: + +// We first check that the headers in the `.top-doc` doc block still have their +// bottom border. +assert-text: (".top-doc .docblock > h3", "Hello") +assert-css: ( + ".top-doc .docblock > h3", + {"border-bottom": "1px solid rgb(221, 221, 221)"}, +) +// We now check that the `<summary>` doesn't have a bottom border and has the correct display. +assert-css: ( + ".top-doc .docblock summary h4", + {"border-bottom": "0px none rgb(221, 221, 221)"}, +) +// This allows to ensure that summary is on one line only! +assert-property: (".top-doc .docblock summary h4", {"offsetHeight": "33"}) +assert-css: (".top-doc .docblock summary h4", {"margin-top": "15px", "margin-bottom": "5px"}) +// So `33 + 15 + 5` == `53` +assert-property: (".top-doc .docblock summary", {"offsetHeight": "53"}) diff --git a/src/test/rustdoc-gui/sidebar-source-code-display.goml b/src/test/rustdoc-gui/sidebar-source-code-display.goml index 8f53e8627ee..fa322574fde 100644 --- a/src/test/rustdoc-gui/sidebar-source-code-display.goml +++ b/src/test/rustdoc-gui/sidebar-source-code-display.goml @@ -18,6 +18,17 @@ click: "#sidebar-toggle" // Because of the transition CSS, we check by using `wait-for-css` instead of `assert-css`. wait-for-css: ("#sidebar-toggle", {"visibility": "visible", "opacity": 1}) +// We now check that opening the sidebar and clicking a link will leave it open. +// The behavior here on desktop is different than the behavior on mobile, +// but since the sidebar doesn't fill the entire screen here, it makes sense to have the +// sidebar stay resident. +wait-for-css: (".sidebar", {"width": "300px"}) +assert-local-storage: {"rustdoc-source-sidebar-show": "true"} +click: ".sidebar a.selected" +goto: file://|DOC_PATH|/src/test_docs/lib.rs.html +wait-for-css: (".sidebar", {"width": "300px"}) +assert-local-storage: {"rustdoc-source-sidebar-show": "true"} + // Now we check the display of the sidebar items. show-text: true @@ -27,29 +38,52 @@ reload: // Waiting for the sidebar to be displayed... wait-for-css: ("#sidebar-toggle", {"visibility": "visible", "opacity": 1}) assert-css: ( - "#source-sidebar .expand + .children a.selected", + "#source-sidebar details[open] > .files a.selected", {"color": "rgb(0, 0, 0)", "background-color": "rgb(255, 255, 255)"}, ) +// Without hover or focus. +assert-css: ("#sidebar-toggle > button", {"background-color": "rgba(0, 0, 0, 0)"}) +// With focus. +focus: "#sidebar-toggle > button" +assert-css: ("#sidebar-toggle > button", {"background-color": "rgb(224, 224, 224)"}) +focus: ".search-input" +// With hover. +move-cursor-to: "#sidebar-toggle > button" +assert-css: ("#sidebar-toggle > button", {"background-color": "rgb(224, 224, 224)"}) // Without hover. assert-css: ( - "#source-sidebar .expand + .children > .files a:not(.selected)", + "#source-sidebar details[open] > .files a:not(.selected)", {"color": "rgb(0, 0, 0)", "background-color": "rgba(0, 0, 0, 0)"}, ) +// With focus. +focus: "#source-sidebar details[open] > .files a:not(.selected)" +wait-for-css: ( + "#source-sidebar details[open] > .files a:not(.selected)", + {"color": "rgb(0, 0, 0)", "background-color": "rgb(224, 224, 224)"}, +) +focus: ".search-input" // With hover. -move-cursor-to: "#source-sidebar .expand + .children > .files a:not(.selected)" +move-cursor-to: "#source-sidebar details[open] > .files a:not(.selected)" assert-css: ( - "#source-sidebar .expand + .children > .files a:not(.selected)", + "#source-sidebar details[open] > .files a:not(.selected)", {"color": "rgb(0, 0, 0)", "background-color": "rgb(224, 224, 224)"}, ) // Without hover. assert-css: ( - "#source-sidebar .expand + .children .folders .name", + "#source-sidebar details[open] > .folders > details > summary", {"color": "rgb(0, 0, 0)", "background-color": "rgba(0, 0, 0, 0)"}, ) +// With focus. +focus: "#source-sidebar details[open] > .folders > details > summary" +wait-for-css: ( + "#source-sidebar details[open] > .folders > details > summary", + {"color": "rgb(0, 0, 0)", "background-color": "rgb(224, 224, 224)"}, +) +focus: ".search-input" // With hover. -move-cursor-to: "#source-sidebar .expand + .children .folders .name" +move-cursor-to: "#source-sidebar details[open] > .folders > details > summary" assert-css: ( - "#source-sidebar .expand + .children .folders .name", + "#source-sidebar details[open] > .folders > details > summary", {"color": "rgb(0, 0, 0)", "background-color": "rgb(224, 224, 224)"}, ) @@ -59,29 +93,52 @@ reload: // Waiting for the sidebar to be displayed... wait-for-css: ("#sidebar-toggle", {"visibility": "visible", "opacity": 1}) assert-css: ( - "#source-sidebar .expand + .children a.selected", + "#source-sidebar details[open] > .files > a.selected", {"color": "rgb(221, 221, 221)", "background-color": "rgb(51, 51, 51)"}, ) +// Without hover or focus. +assert-css: ("#sidebar-toggle > button", {"background-color": "rgba(0, 0, 0, 0)"}) +// With focus. +focus: "#sidebar-toggle > button" +assert-css: ("#sidebar-toggle > button", {"background-color": "rgb(103, 103, 103)"}) +focus: ".search-input" +// With hover. +move-cursor-to: "#sidebar-toggle > button" +assert-css: ("#sidebar-toggle > button", {"background-color": "rgb(103, 103, 103)"}) // Without hover. assert-css: ( - "#source-sidebar .expand + .children > .files a:not(.selected)", + "#source-sidebar details[open] > .files > a:not(.selected)", {"color": "rgb(221, 221, 221)", "background-color": "rgba(0, 0, 0, 0)"}, ) +// With focus. +focus: "#source-sidebar details[open] > .files a:not(.selected)" +wait-for-css: ( + "#source-sidebar details[open] > .files a:not(.selected)", + {"color": "rgb(221, 221, 221)", "background-color": "rgb(68, 68, 68)"}, +) +focus: ".search-input" // With hover. -move-cursor-to: "#source-sidebar .expand + .children > .files a:not(.selected)" +move-cursor-to: "#source-sidebar details[open] > .files a:not(.selected)" assert-css: ( - "#source-sidebar .expand + .children > .files a:not(.selected)", + "#source-sidebar details[open] > .files a:not(.selected)", {"color": "rgb(221, 221, 221)", "background-color": "rgb(68, 68, 68)"}, ) // Without hover. assert-css: ( - "#source-sidebar .expand + .children .folders .name", + "#source-sidebar details[open] > .folders > details > summary", {"color": "rgb(221, 221, 221)", "background-color": "rgba(0, 0, 0, 0)"}, ) +// With focus. +focus: "#source-sidebar details[open] > .folders > details > summary" +wait-for-css: ( + "#source-sidebar details[open] > .folders > details > summary", + {"color": "rgb(221, 221, 221)", "background-color": "rgb(68, 68, 68)"}, +) +focus: ".search-input" // With hover. -move-cursor-to: "#source-sidebar .expand + .children .folders .name" +move-cursor-to: "#source-sidebar details[open] > .folders > details > summary" assert-css: ( - "#source-sidebar .expand + .children .folders .name", + "#source-sidebar details[open] > .folders > details > summary", {"color": "rgb(221, 221, 221)", "background-color": "rgb(68, 68, 68)"}, ) @@ -91,28 +148,107 @@ reload: // Waiting for the sidebar to be displayed... wait-for-css: ("#sidebar-toggle", {"visibility": "visible", "opacity": 1}) assert-css: ( - "#source-sidebar .expand + .children a.selected", + "#source-sidebar details[open] > .files a.selected", {"color": "rgb(255, 180, 76)", "background-color": "rgb(20, 25, 31)"}, ) +// Without hover or focus. +assert-css: ("#sidebar-toggle > button", {"background-color": "rgba(0, 0, 0, 0)"}) +// With focus. +focus: "#sidebar-toggle > button" +assert-css: ("#sidebar-toggle > button", {"background-color": "rgba(70, 70, 70, 0.33)"}) +focus: ".search-input" +// With hover. +move-cursor-to: "#sidebar-toggle > button" +assert-css: ("#sidebar-toggle > button", {"background-color": "rgba(70, 70, 70, 0.33)"}) // Without hover. assert-css: ( - "#source-sidebar .expand + .children > .files a:not(.selected)", + "#source-sidebar details[open] > .files a:not(.selected)", {"color": "rgb(197, 197, 197)", "background-color": "rgba(0, 0, 0, 0)"}, ) +// With focus. +focus: "#source-sidebar details[open] > .files a:not(.selected)" +wait-for-css: ( + "#source-sidebar details[open] > .files a:not(.selected)", + {"color": "rgb(255, 180, 76)", "background-color": "rgb(20, 25, 31)"}, +) +focus: ".search-input" // With hover. -move-cursor-to: "#source-sidebar .expand + .children > .files a:not(.selected)" +move-cursor-to: "#source-sidebar details[open] > .files a:not(.selected)" assert-css: ( - "#source-sidebar .expand + .children > .files a:not(.selected)", + "#source-sidebar details[open] > .files a:not(.selected)", {"color": "rgb(255, 180, 76)", "background-color": "rgb(20, 25, 31)"}, ) // Without hover. assert-css: ( - "#source-sidebar .expand + .children .folders .name", + "#source-sidebar details[open] > .folders > details > summary", {"color": "rgb(197, 197, 197)", "background-color": "rgba(0, 0, 0, 0)"}, ) +// With focus. +focus: "#source-sidebar details[open] > .folders > details > summary" +wait-for-css: ( + "#source-sidebar details[open] > .folders > details > summary", + {"color": "rgb(255, 180, 76)", "background-color": "rgb(20, 25, 31)"}, +) +focus: ".search-input" // With hover. -move-cursor-to: "#source-sidebar .expand + .children .folders .name" +move-cursor-to: "#source-sidebar details[open] > .folders > details > summary" assert-css: ( - "#source-sidebar .expand + .children .folders .name", + "#source-sidebar details[open] > .folders > details > summary", {"color": "rgb(255, 180, 76)", "background-color": "rgb(20, 25, 31)"}, ) + +// Now checking on mobile devices. +size: (500, 700) +reload: +// Waiting for the sidebar to be displayed... +wait-for-css: ("#sidebar-toggle", {"visibility": "visible", "opacity": 1}) + +// We now check it takes the full size of the display. +assert-property: ("body", {"clientWidth": "500", "clientHeight": "700"}) +assert-property: (".sidebar", {"clientWidth": "500", "clientHeight": "700"}) + +// We now check the display of the toggle once the sidebar is expanded. +assert-property: ("#sidebar-toggle", {"clientWidth": "500", "clientHeight": "39"}) +assert-css: ( + "#sidebar-toggle", + { + "border-top-width": "0px", + "border-right-width": "0px", + "border-left-width": "0px", + "border-bottom-width": "1px", + }, +) + +// We now check that the scroll position is kept when opening the sidebar. +click: "#sidebar-toggle" +wait-for-css: (".sidebar", {"width": "0px"}) +// We scroll to line 117 to change the scroll position. +scroll-to: '//*[@id="117"]' +assert-window-property: {"pageYOffset": "2519"} +// Expanding the sidebar... +click: "#sidebar-toggle" +wait-for-css: (".sidebar", {"width": "500px"}) +click: "#sidebar-toggle" +wait-for-css: (".sidebar", {"width": "0px"}) +// The "scrollTop" property should be the same. +assert-window-property: {"pageYOffset": "2519"} + +// We now check that opening the sidebar and clicking a link will close it. +// The behavior here on mobile is different than the behavior on desktop, +// but common sense dictates that if you have a list of files that fills the entire screen, and +// you click one of them, you probably want to actually see the file's contents, and not just +// make it the current selection. +click: "#sidebar-toggle" +wait-for-css: ("#source-sidebar", {"visibility": "visible"}) +assert-local-storage: {"rustdoc-source-sidebar-show": "true"} +click: ".sidebar a.selected" +goto: file://|DOC_PATH|/src/test_docs/lib.rs.html +wait-for-css: ("#source-sidebar", {"visibility": "hidden"}) +assert-local-storage: {"rustdoc-source-sidebar-show": "false"} +// Resize back to desktop size, to check that the sidebar doesn't spontaneously open. +size: (1000, 1000) +wait-for-css: ("#source-sidebar", {"visibility": "hidden"}) +assert-local-storage: {"rustdoc-source-sidebar-show": "false"} +click: "#sidebar-toggle" +wait-for-css: ("#source-sidebar", {"visibility": "visible"}) +assert-local-storage: {"rustdoc-source-sidebar-show": "true"} diff --git a/src/test/rustdoc-gui/sidebar-source-code.goml b/src/test/rustdoc-gui/sidebar-source-code.goml index 724520bc399..86df478fa1d 100644 --- a/src/test/rustdoc-gui/sidebar-source-code.goml +++ b/src/test/rustdoc-gui/sidebar-source-code.goml @@ -18,8 +18,8 @@ assert: "nav.sidebar" // We now switch to mobile mode. size: (600, 600) -// We check that the sidebar has the expected width (0 and 1px for the border). -assert-css: ("nav.sidebar", {"width": "1px"}) +// We check that the sidebar has the expected width (0). +assert-css: ("nav.sidebar", {"width": "0px"}) // We expand the sidebar. click: "#sidebar-toggle" assert-css: (".source-sidebar-expanded nav.sidebar", {"width": "600px"}) diff --git a/src/test/rustdoc-gui/source-code-page.goml b/src/test/rustdoc-gui/source-code-page.goml index b45512601f2..581f826a3d9 100644 --- a/src/test/rustdoc-gui/source-code-page.goml +++ b/src/test/rustdoc-gui/source-code-page.goml @@ -34,19 +34,16 @@ assert-document-property: ({"URL": "/lib.rs.html"}, ENDS_WITH) click: "#sidebar-toggle" assert: ".source-sidebar-expanded" -// We check that the first entry of the sidebar is collapsed (which, for whatever reason, -// is number 2 and not 1...). -assert-attribute: ("#source-sidebar .name:nth-child(2)", {"class": "name"}) -assert-text: ("#source-sidebar .name:nth-child(2)", "implementors") -// We also check its children are hidden too. -assert-css: ("#source-sidebar .name:nth-child(2) + .children", {"display": "none"}) +// We check that the first entry of the sidebar is collapsed +assert-property: ("#source-sidebar details:first-of-type", {"open": "false"}) +assert-text: ("#source-sidebar details:first-of-type > summary", "implementors") // We now click on it. -click: "#source-sidebar .name:nth-child(2)" -assert-attribute: ("#source-sidebar .name:nth-child(2)", {"class": "name expand"}) -// Checking that its children are displayed as well. -assert-css: ("#source-sidebar .name:nth-child(2) + .children", {"display": "block"}) +click: "#source-sidebar details:first-of-type > summary" +assert-property: ("#source-sidebar details:first-of-type", {"open": "true"}) // And now we collapse it again. -click: "#source-sidebar .name:nth-child(2)" -assert-attribute: ("#source-sidebar .name:nth-child(2)", {"class": "name"}) -assert-css: ("#source-sidebar .name:nth-child(2) + .children", {"display": "none"}) +click: "#source-sidebar details:first-of-type > summary" +assert-property: ("#source-sidebar details:first-of-type", {"open": "false"}) + +// Check the spacing. +assert-css: ("#source-sidebar > details.dir-entry", {"padding-left": "4px"}) diff --git a/src/test/rustdoc-gui/src/test_docs/lib.rs b/src/test/rustdoc-gui/src/test_docs/lib.rs index b6fe9eb2565..aa2f78289be 100644 --- a/src/test/rustdoc-gui/src/test_docs/lib.rs +++ b/src/test/rustdoc-gui/src/test_docs/lib.rs @@ -277,3 +277,15 @@ pub use macros::*; #[doc(alias = "AliasForTheStdReexport")] pub use ::std as TheStdReexport; + +pub mod details { + /// We check the appearance of the `<details>`/`<summary>` in here. + /// + /// ## Hello + /// + /// <details> + /// <summary><h4>I'm a summary</h4></summary> + /// <div>I'm the content of the details!</div> + /// </details> + pub struct Details; +} diff --git a/src/test/rustdoc-ui/issue-79467.rs b/src/test/rustdoc-ui/issue-79467.rs new file mode 100644 index 00000000000..eb0b9b38071 --- /dev/null +++ b/src/test/rustdoc-ui/issue-79467.rs @@ -0,0 +1,8 @@ +fn g() +where + 'static: 'static, + dyn 'static: 'static + Copy, //~ ERROR at least one trait is required for an object type +{ +} + +fn main() {} diff --git a/src/test/rustdoc-ui/issue-79467.stderr b/src/test/rustdoc-ui/issue-79467.stderr new file mode 100644 index 00000000000..561513a432b --- /dev/null +++ b/src/test/rustdoc-ui/issue-79467.stderr @@ -0,0 +1,9 @@ +error[E0224]: at least one trait is required for an object type + --> $DIR/issue-79467.rs:4:5 + | +LL | dyn 'static: 'static + Copy, + | ^^^^^^^^^^^ + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0224`. diff --git a/src/test/rustdoc-ui/issue-79494.rs b/src/test/rustdoc-ui/issue-79494.rs new file mode 100644 index 00000000000..fc39424b793 --- /dev/null +++ b/src/test/rustdoc-ui/issue-79494.rs @@ -0,0 +1,5 @@ +// only-x86_64-unknown-linux-gnu + +#![feature(const_transmute)] + +const ZST: &[u8] = unsafe { std::mem::transmute(1usize) }; //~ ERROR cannot transmute between types of different sizes, or dependently-sized types diff --git a/src/test/rustdoc-ui/issue-79494.stderr b/src/test/rustdoc-ui/issue-79494.stderr new file mode 100644 index 00000000000..7ed5ed38247 --- /dev/null +++ b/src/test/rustdoc-ui/issue-79494.stderr @@ -0,0 +1,12 @@ +error[E0512]: cannot transmute between types of different sizes, or dependently-sized types + --> $DIR/issue-79494.rs:5:29 + | +LL | const ZST: &[u8] = unsafe { std::mem::transmute(1usize) }; + | ^^^^^^^^^^^^^^^^^^^ + | + = note: source type: `usize` (64 bits) + = note: target type: `&[u8]` (128 bits) + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0512`. diff --git a/src/test/rustdoc-ui/issue-83883-describe-lints.rs b/src/test/rustdoc-ui/issue-83883-describe-lints.rs index a261b782d48..0474d6c143e 100644 --- a/src/test/rustdoc-ui/issue-83883-describe-lints.rs +++ b/src/test/rustdoc-ui/issue-83883-describe-lints.rs @@ -1,8 +1,10 @@ // compile-flags: -W help // check-pass +// check-stdout +// error-pattern:Lint checks provided +// error-pattern:rustdoc::broken-intra-doc-links // // ignore-tidy-linelength // // normalize-stdout-test: "( +name default meaning\n +---- ------- -------\n)?( *[[:word:]:-]+ (allow |warn |deny |forbid ) [^\n]+\n)+" -> " $$NAMES $$LEVELS $$MEANINGS" // normalize-stdout-test: " +name sub-lints\n +---- ---------\n( *[[:word:]:-]+ [^\n]+\n)+" -> " $$NAMES $$SUB_LINTS" -// normalize-stdout-test: " +rustdoc::all( (rustdoc::[[:word:]-]+, )*rustdoc::[[:word:]-]+)?" -> " rustdoc::all $$GROUPS$4" diff --git a/src/test/rustdoc-ui/issue-83883-describe-lints.stdout b/src/test/rustdoc-ui/issue-83883-describe-lints.stdout index 5cb7ecb649a..bbf66a31583 100644 --- a/src/test/rustdoc-ui/issue-83883-describe-lints.stdout +++ b/src/test/rustdoc-ui/issue-83883-describe-lints.stdout @@ -1,193 +1,24 @@ - -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 +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: + + $NAMES $SUB_LINTS + diff --git a/src/test/rustdoc-ui/issue-98690.rs b/src/test/rustdoc-ui/issue-98690.rs new file mode 100644 index 00000000000..fe9bd87ab28 --- /dev/null +++ b/src/test/rustdoc-ui/issue-98690.rs @@ -0,0 +1,10 @@ +// compile-flags: --test --persist-doctests /../../ -Z unstable-options +// failure-status: 101 +// only-linux + +#![crate_name = "foo"] + +//! ```rust +//! use foo::dummy; +//! dummy(); +//! ``` diff --git a/src/test/rustdoc-ui/issue-98690.stderr b/src/test/rustdoc-ui/issue-98690.stderr new file mode 100644 index 00000000000..47d94f99a45 --- /dev/null +++ b/src/test/rustdoc-ui/issue-98690.stderr @@ -0,0 +1 @@ +Couldn't create directory for doctest executables: Permission denied (os error 13) diff --git a/src/test/rustdoc-ui/lint-missing-doc-code-example.stderr b/src/test/rustdoc-ui/lint-missing-doc-code-example.stderr index 37157978542..9e51ecd2ba0 100644 --- a/src/test/rustdoc-ui/lint-missing-doc-code-example.stderr +++ b/src/test/rustdoc-ui/lint-missing-doc-code-example.stderr @@ -1,9 +1,8 @@ error: missing code example in this documentation --> $DIR/lint-missing-doc-code-example.rs:19:1 | -LL | / pub mod module1 { -LL | | } - | |_^ +LL | pub mod module1 { + | ^^^^^^^^^^^^^^^ | note: the lint level is defined here --> $DIR/lint-missing-doc-code-example.rs:2:9 diff --git a/src/test/rustdoc/assoc-consts.rs b/src/test/rustdoc/assoc-consts.rs index 0ac6dc763df..a79e93145ba 100644 --- a/src/test/rustdoc/assoc-consts.rs +++ b/src/test/rustdoc/assoc-consts.rs @@ -27,6 +27,10 @@ impl Bar { // @has assoc_consts/struct.Bar.html '//*[@id="associatedconstant.BAR"]' \ // 'const BAR: usize' pub const BAR: usize = 3; + + // @has - '//*[@id="associatedconstant.BAR_ESCAPED"]' \ + // "const BAR_ESCAPED: &'static str = \"<em>markup</em>\"" + pub const BAR_ESCAPED: &'static str = "<em>markup</em>"; } pub struct Baz<'a, U: 'a, T>(T, &'a [U]); diff --git a/src/test/rustdoc/assoc-types.rs b/src/test/rustdoc/assoc-types.rs index d9e4ffab1c7..a9e5b8d0019 100644 --- a/src/test/rustdoc/assoc-types.rs +++ b/src/test/rustdoc/assoc-types.rs @@ -2,7 +2,7 @@ // @has assoc_types/trait.Index.html pub trait Index<I: ?Sized> { - // @has - '//*[@id="associatedtype.Output"]//h4[@class="code-header"]' 'type Output: ?Sized' + // @has - '//*[@id="associatedtype.Output"]//h4[@class="code-header"]' 'type Output: ?Sized' type Output: ?Sized; // @has - '//*[@id="tymethod.index"]//h4[@class="code-header"]' \ // "fn index<'a>(&'a self, index: I) -> &'a Self::Output" diff --git a/src/test/rustdoc/auxiliary/issue-98697-reexport-with-anonymous-lifetime.rs b/src/test/rustdoc/auxiliary/issue-98697-reexport-with-anonymous-lifetime.rs new file mode 100644 index 00000000000..22cbeae7266 --- /dev/null +++ b/src/test/rustdoc/auxiliary/issue-98697-reexport-with-anonymous-lifetime.rs @@ -0,0 +1,9 @@ +/// When reexporting this function, make sure the anonymous lifetimes are not rendered. +/// +/// https://github.com/rust-lang/rust/issues/98697 +pub fn repro<F>() +where + F: Fn(&str), +{ + unimplemented!() +} diff --git a/src/test/rustdoc/check-source-code-urls-to-def.rs b/src/test/rustdoc/check-source-code-urls-to-def.rs index 12c5df2871c..ec44e1bc65c 100644 --- a/src/test/rustdoc/check-source-code-urls-to-def.rs +++ b/src/test/rustdoc/check-source-code-urls-to-def.rs @@ -14,10 +14,10 @@ extern crate source_code; #[path = "auxiliary/source-code-bar.rs"] pub mod bar; -// @count - '//a[@href="../../src/foo/auxiliary/source-code-bar.rs.html#5-7"]' 4 +// @count - '//a[@href="../../src/foo/auxiliary/source-code-bar.rs.html#5"]' 4 use bar::Bar; -// @has - '//a[@href="../../src/foo/auxiliary/source-code-bar.rs.html#13-17"]' 'self' -// @has - '//a[@href="../../src/foo/auxiliary/source-code-bar.rs.html#14-16"]' 'Trait' +// @has - '//a[@href="../../src/foo/auxiliary/source-code-bar.rs.html#13"]' 'self' +// @has - '//a[@href="../../src/foo/auxiliary/source-code-bar.rs.html#14"]' 'Trait' use bar::sub::{self, Trait}; pub struct Foo; @@ -42,8 +42,8 @@ pub fn foo(a: u32, b: &str, c: String, d: Foo, e: bar::Bar, f: source_code::Sour y.hello(); } -// @has - '//a[@href="../../src/foo/auxiliary/source-code-bar.rs.html#14-16"]' 'bar::sub::Trait' -// @has - '//a[@href="../../src/foo/auxiliary/source-code-bar.rs.html#14-16"]' 'Trait' +// @has - '//a[@href="../../src/foo/auxiliary/source-code-bar.rs.html#14"]' 'bar::sub::Trait' +// @has - '//a[@href="../../src/foo/auxiliary/source-code-bar.rs.html#14"]' 'Trait' pub fn foo2<T: bar::sub::Trait, V: Trait>(t: &T, v: &V, b: bool) {} pub trait AnotherTrait {} diff --git a/src/test/rustdoc/const-value-display.rs b/src/test/rustdoc/const-value-display.rs index 0ae52592b64..5b2f3c48d57 100644 --- a/src/test/rustdoc/const-value-display.rs +++ b/src/test/rustdoc/const-value-display.rs @@ -1,9 +1,9 @@ #![crate_name = "foo"] // @has 'foo/constant.HOUR_IN_SECONDS.html' -// @has - '//*[@class="docblock item-decl"]//code' 'pub const HOUR_IN_SECONDS: u64 = 60 * 60; // 3_600u64' +// @has - '//*[@class="docblock item-decl"]//code' 'pub const HOUR_IN_SECONDS: u64 = _; // 3_600u64' pub const HOUR_IN_SECONDS: u64 = 60 * 60; // @has 'foo/constant.NEGATIVE.html' -// @has - '//*[@class="docblock item-decl"]//code' 'pub const NEGATIVE: i64 = -60 * 60; // -3_600i64' +// @has - '//*[@class="docblock item-decl"]//code' 'pub const NEGATIVE: i64 = _; // -3_600i64' pub const NEGATIVE: i64 = -60 * 60; diff --git a/src/test/rustdoc/decl-trailing-whitespace.declaration.html b/src/test/rustdoc/decl-trailing-whitespace.declaration.html new file mode 100644 index 00000000000..e60caaeff38 --- /dev/null +++ b/src/test/rustdoc/decl-trailing-whitespace.declaration.html @@ -0,0 +1,7 @@ +<code>pub trait Write { + fn <a href="#tymethod.poll_write" class="fnname">poll_write</a>(<br />        self: <a class="enum" href="{{channel}}/core/option/enum.Option.html" title="enum core::option::Option">Option</a><<a class="struct" href="{{channel}}/alloc/string/struct.String.html" title="struct alloc::string::String">String</a>>,<br />        cx: &mut <a class="enum" href="{{channel}}/core/option/enum.Option.html" title="enum core::option::Option">Option</a><<a class="struct" href="{{channel}}/alloc/string/struct.String.html" title="struct alloc::string::String">String</a>>,<br />        buf: &mut [<a class="primitive" href="{{channel}}/std/primitive.usize.html">usize</a>]<br />    ) -> <a class="enum" href="{{channel}}/core/option/enum.Option.html" title="enum core::option::Option">Option</a><<a class="enum" href="{{channel}}/core/result/enum.Result.html" title="enum core::result::Result">Result</a><<a class="primitive" href="{{channel}}/std/primitive.usize.html">usize</a>, <a class="struct" href="struct.Error.html" title="struct foo::Error">Error</a>>>; +<span class="item-spacer" /> fn <a href="#tymethod.poll_flush" class="fnname">poll_flush</a>(<br />        self: <a class="enum" href="{{channel}}/core/option/enum.Option.html" title="enum core::option::Option">Option</a><<a class="struct" href="{{channel}}/alloc/string/struct.String.html" title="struct alloc::string::String">String</a>>,<br />        cx: &mut <a class="enum" href="{{channel}}/core/option/enum.Option.html" title="enum core::option::Option">Option</a><<a class="struct" href="{{channel}}/alloc/string/struct.String.html" title="struct alloc::string::String">String</a>><br />    ) -> <a class="enum" href="{{channel}}/core/option/enum.Option.html" title="enum core::option::Option">Option</a><<a class="enum" href="{{channel}}/core/result/enum.Result.html" title="enum core::result::Result">Result</a><<a class="primitive" href="{{channel}}/std/primitive.unit.html">()</a>, <a class="struct" href="struct.Error.html" title="struct foo::Error">Error</a>>>; +<span class="item-spacer" /> fn <a href="#tymethod.poll_close" class="fnname">poll_close</a>(<br />        self: <a class="enum" href="{{channel}}/core/option/enum.Option.html" title="enum core::option::Option">Option</a><<a class="struct" href="{{channel}}/alloc/string/struct.String.html" title="struct alloc::string::String">String</a>>,<br />        cx: &mut <a class="enum" href="{{channel}}/core/option/enum.Option.html" title="enum core::option::Option">Option</a><<a class="struct" href="{{channel}}/alloc/string/struct.String.html" title="struct alloc::string::String">String</a>><br />    ) -> <a class="enum" href="{{channel}}/core/option/enum.Option.html" title="enum core::option::Option">Option</a><<a class="enum" href="{{channel}}/core/result/enum.Result.html" title="enum core::result::Result">Result</a><<a class="primitive" href="{{channel}}/std/primitive.unit.html">()</a>, <a class="struct" href="struct.Error.html" title="struct foo::Error">Error</a>>>; + + fn <a href="#method.poll_write_vectored" class="fnname">poll_write_vectored</a>(<br />        self: <a class="enum" href="{{channel}}/core/option/enum.Option.html" title="enum core::option::Option">Option</a><<a class="struct" href="{{channel}}/alloc/string/struct.String.html" title="struct alloc::string::String">String</a>>,<br />        cx: &mut <a class="enum" href="{{channel}}/core/option/enum.Option.html" title="enum core::option::Option">Option</a><<a class="struct" href="{{channel}}/alloc/string/struct.String.html" title="struct alloc::string::String">String</a>>,<br />        bufs: &[<a class="primitive" href="{{channel}}/std/primitive.usize.html">usize</a>]<br />    ) -> <a class="enum" href="{{channel}}/core/option/enum.Option.html" title="enum core::option::Option">Option</a><<a class="enum" href="{{channel}}/core/result/enum.Result.html" title="enum core::result::Result">Result</a><<a class="primitive" href="{{channel}}/std/primitive.usize.html">usize</a>, <a class="struct" href="struct.Error.html" title="struct foo::Error">Error</a>>> { ... } +}</code> diff --git a/src/test/rustdoc/decl-trailing-whitespace.rs b/src/test/rustdoc/decl-trailing-whitespace.rs new file mode 100644 index 00000000000..46a2307abef --- /dev/null +++ b/src/test/rustdoc/decl-trailing-whitespace.rs @@ -0,0 +1,30 @@ +// Regression test for <https://github.com/rust-lang/rust/issues/98803>. + +#![crate_name = "foo"] + +pub struct Error; + +// @has 'foo/trait.Write.html' + +pub trait Write { + // @snapshot 'declaration' - '//*[@class="docblock item-decl"]//code' + fn poll_write( + self: Option<String>, + cx: &mut Option<String>, + buf: &mut [usize] + ) -> Option<Result<usize, Error>>; + fn poll_flush( + self: Option<String>, + cx: &mut Option<String> + ) -> Option<Result<(), Error>>; + fn poll_close( + self: Option<String>, + cx: &mut Option<String>, + ) -> Option<Result<(), Error>>; + + fn poll_write_vectored( + self: Option<String>, + cx: &mut Option<String>, + bufs: &[usize] + ) -> Option<Result<usize, Error>> {} +} diff --git a/src/test/rustdoc/hide-complex-unevaluated-const-arguments.rs b/src/test/rustdoc/hide-complex-unevaluated-const-arguments.rs new file mode 100644 index 00000000000..644a6e1cf33 --- /dev/null +++ b/src/test/rustdoc/hide-complex-unevaluated-const-arguments.rs @@ -0,0 +1,82 @@ +// Test that certain unevaluated constant expression arguments that are +// deemed too verbose or complex and that may leak private or +// `doc(hidden)` struct fields are not displayed in the documentation. +// +// Read the documentation of `rustdoc::clean::utils::print_const_expr` +// for further details. +#![feature(const_trait_impl, generic_const_exprs)] +#![allow(incomplete_features)] + +// @has hide_complex_unevaluated_const_arguments/trait.Stage.html +pub trait Stage { + // A helper constant that prevents const expressions containing it + // from getting fully evaluated since it doesn't have a body and + // thus is non-reducible. This allows us to specifically test the + // pretty-printing of *unevaluated* consts. + const ABSTRACT: usize; + + // Currently considered "overly complex" by the `generic_const_exprs` + // feature. If / once this expression kind gets supported, this + // unevaluated const expression could leak the private struct field. + // + // FIXME: Once the line below compiles, make this a test that + // ensures that the private field is not printed. + // + //const ARRAY0: [u8; Struct { private: () } + Self::ABSTRACT]; + + // This assoc. const could leak the private assoc. function `Struct::new`. + // Ensure that this does not happen. + // + // @has - '//*[@id="associatedconstant.ARRAY1"]' \ + // 'const ARRAY1: [u8; { _ }]' + const ARRAY1: [u8; Struct::new(/* ... */) + Self::ABSTRACT * 1_000]; + + // @has - '//*[@id="associatedconstant.VERBOSE"]' \ + // 'const VERBOSE: [u16; { _ }]' + const VERBOSE: [u16; compute("thing", 9 + 9) * Self::ABSTRACT]; + + // Check that we do not leak the private struct field contained within + // the path. The output could definitely be improved upon + // (e.g. printing sth. akin to `<Self as Helper<{ _ }>>::OUT`) but + // right now “safe is safe”. + // + // @has - '//*[@id="associatedconstant.PATH"]' \ + // 'const PATH: usize = _' + const PATH: usize = <Self as Helper<{ Struct { private: () } }>>::OUT; +} + +const fn compute(input: &str, extra: usize) -> usize { + input.len() + extra +} + +pub trait Helper<const S: Struct> { + const OUT: usize; +} + +impl<const S: Struct, St: Stage + ?Sized> Helper<S> for St { + const OUT: usize = St::ABSTRACT; +} + +// Currently in rustdoc, const arguments are not evaluated in this position +// and therefore they fall under the realm of `print_const_expr`. +// If rustdoc gets patched to evaluate const arguments, it is fine to replace +// this test as long as one can ensure that private fields are not leaked! +// +// @has hide_complex_unevaluated_const_arguments/trait.Sub.html \ +// '//*[@class="rust trait"]' \ +// 'pub trait Sub: Sup<{ _ }, { _ }> { }' +pub trait Sub: Sup<{ 90 * 20 * 4 }, { Struct { private: () } }> {} + +pub trait Sup<const N: usize, const S: Struct> {} + +pub struct Struct { private: () } + +impl Struct { + const fn new() -> Self { Self { private: () } } +} + +impl const std::ops::Add<usize> for Struct { + type Output = usize; + + fn add(self, _: usize) -> usize { 0 } +} diff --git a/src/test/rustdoc/hide-complex-unevaluated-consts.rs b/src/test/rustdoc/hide-complex-unevaluated-consts.rs new file mode 100644 index 00000000000..ba623246a01 --- /dev/null +++ b/src/test/rustdoc/hide-complex-unevaluated-consts.rs @@ -0,0 +1,71 @@ +// Regression test for issue #97933. +// +// Test that certain unevaluated constant expressions that are +// deemed too verbose or complex and that may leak private or +// `doc(hidden)` struct fields are not displayed in the documentation. +// +// Read the documentation of `rustdoc::clean::utils::print_const_expr` +// for further details. + +// @has hide_complex_unevaluated_consts/trait.Container.html +pub trait Container { + // A helper constant that prevents const expressions containing it + // from getting fully evaluated since it doesn't have a body and + // thus is non-reducible. This allows us to specifically test the + // pretty-printing of *unevaluated* consts. + const ABSTRACT: i32; + + // Ensure that the private field does not get leaked: + // + // @has - '//*[@id="associatedconstant.STRUCT0"]' \ + // 'const STRUCT0: Struct = _' + const STRUCT0: Struct = Struct { private: () }; + + // @has - '//*[@id="associatedconstant.STRUCT1"]' \ + // 'const STRUCT1: (Struct,) = _' + const STRUCT1: (Struct,) = (Struct{private: /**/()},); + + // Although the struct field is public here, check that it is not + // displayed. In a future version of rustdoc, we definitely want to + // show it. However for the time being, the printing logic is a bit + // conservative. + // + // @has - '//*[@id="associatedconstant.STRUCT2"]' \ + // 'const STRUCT2: Record = _' + const STRUCT2: Record = Record { public: 5 }; + + // Test that we do not show the incredibly verbose match expr: + // + // @has - '//*[@id="associatedconstant.MATCH0"]' \ + // 'const MATCH0: i32 = _' + const MATCH0: i32 = match 234 { + 0 => 1, + _ => Self::ABSTRACT, + }; + + // @has - '//*[@id="associatedconstant.MATCH1"]' \ + // 'const MATCH1: bool = _' + const MATCH1: bool = match Self::ABSTRACT { + _ => true, + }; + + // Check that we hide complex (arithmetic) operations. + // In this case, it is a bit unfortunate since the expression + // is not *that* verbose and it might be quite useful to the reader. + // + // However in general, the expression might be quite large and + // contain match expressions and structs with private fields. + // We would need to recurse over the whole expression and even more + // importantly respect operator precedence when pretty-printing + // the potentially partially censored expression. + // For now, the implementation is quite simple and the choices + // rather conservative. + // + // @has - '//*[@id="associatedconstant.ARITH_OPS"]' \ + // 'const ARITH_OPS: i32 = _' + const ARITH_OPS: i32 = Self::ABSTRACT * 2 + 1; +} + +pub struct Struct { private: () } + +pub struct Record { pub public: i32 } diff --git a/src/test/rustdoc/inline_cross/macros.rs b/src/test/rustdoc/inline_cross/macros.rs index 13b4c3c7f61..5daa0d4baad 100644 --- a/src/test/rustdoc/inline_cross/macros.rs +++ b/src/test/rustdoc/inline_cross/macros.rs @@ -15,5 +15,5 @@ extern crate macros; // @has - '//*[@class="docblock"]' 'docs for my_macro' // @has - '//*[@class="stab deprecated"]' 'Deprecated since 1.2.3: text' // @has - '//*[@class="stab unstable"]' 'macro_test' -// @has - '//a/@href' '../src/macros/macros.rs.html#8-10' +// @has - '//a/@href' '../src/macros/macros.rs.html#8' pub use macros::my_macro; diff --git a/src/test/rustdoc/intra-doc/pub-use.rs b/src/test/rustdoc/intra-doc/pub-use.rs index 0c70cdee914..8a998496cf5 100644 --- a/src/test/rustdoc/intra-doc/pub-use.rs +++ b/src/test/rustdoc/intra-doc/pub-use.rs @@ -5,21 +5,11 @@ extern crate inner; /// [mod@std::env] [g] - -// FIXME: This can't be tested because rustdoc doesn't show documentation on pub re-exports. -// Until then, comment out the `htmldocck` test. -// This test still does something; namely check that no incorrect errors are emitted when -// documenting the re-export. - // @has outer/index.html -// @ has - '//a[@href="{{channel}}/std/env/fn.var.html"]' "std::env" -// @ has - '//a[@href="fn.f.html"]' "g" +// @has - '//a[@href="{{channel}}/std/env/index.html"]' "std::env" +// @has - '//a[@href="fn.f.html"]' "g" pub use f as g; -// FIXME: same as above -/// [std::env] -extern crate self as _; - // Make sure the documentation is actually correct by documenting an inlined re-export /// [mod@std::env] // @has outer/fn.f.html diff --git a/src/test/rustdoc/issue-98697.rs b/src/test/rustdoc/issue-98697.rs new file mode 100644 index 00000000000..25ab55acd77 --- /dev/null +++ b/src/test/rustdoc/issue-98697.rs @@ -0,0 +1,13 @@ +// aux-build:issue-98697-reexport-with-anonymous-lifetime.rs +// ignore-cross-compile + +// When reexporting a function with a HRTB with anonymous lifetimes, +// make sure the anonymous lifetimes are not rendered. +// +// https://github.com/rust-lang/rust/issues/98697 + +extern crate issue_98697_reexport_with_anonymous_lifetime; + +// @has issue_98697/fn.repro.html '//pre[@class="rust fn"]/code' 'fn repro<F>() where F: Fn(&str)' +// @!has issue_98697/fn.repro.html '//pre[@class="rust fn"]/code' 'for<' +pub use issue_98697_reexport_with_anonymous_lifetime::repro; diff --git a/src/test/rustdoc/show-const-contents.rs b/src/test/rustdoc/show-const-contents.rs index f5a356bcae6..48b60885974 100644 --- a/src/test/rustdoc/show-const-contents.rs +++ b/src/test/rustdoc/show-const-contents.rs @@ -21,7 +21,7 @@ pub const CONST_NEG_I32: i32 = -42; // @!has show_const_contents/constant.CONST_EQ_TO_VALUE_I32.html '// 42i32' pub const CONST_EQ_TO_VALUE_I32: i32 = 42i32; -// @has show_const_contents/constant.CONST_CALC_I32.html '= 42 + 1; // 43i32' +// @has show_const_contents/constant.CONST_CALC_I32.html '= _; // 43i32' pub const CONST_CALC_I32: i32 = 42 + 1; // @!has show_const_contents/constant.CONST_REF_I32.html '= &42;' diff --git a/src/test/rustdoc/whitespace-after-where-clause.enum.html b/src/test/rustdoc/whitespace-after-where-clause.enum.html new file mode 100644 index 00000000000..9e5bf45ae7d --- /dev/null +++ b/src/test/rustdoc/whitespace-after-where-clause.enum.html @@ -0,0 +1,4 @@ +<div class="docblock item-decl"><pre class="rust enum"><code>pub enum Cow<'a, B: ?<a class="trait" href="{{channel}}/core/marker/trait.Sized.html" title="trait core::marker::Sized">Sized</a> + 'a> <span class="where fmt-newline">where<br />    B: <a class="trait" href="trait.ToOwned.html" title="trait foo::ToOwned">ToOwned</a><dyn <a class="trait" href="{{channel}}/core/clone/trait.Clone.html" title="trait core::clone::Clone">Clone</a>>, </span>{ + Borrowed(<a class="primitive" href="{{channel}}/std/primitive.reference.html">&'a </a>B), + Whatever(<a class="primitive" href="{{channel}}/std/primitive.u32.html">u32</a>), +}</code></pre></div> diff --git a/src/test/rustdoc/whitespace-after-where-clause.enum2.html b/src/test/rustdoc/whitespace-after-where-clause.enum2.html new file mode 100644 index 00000000000..6bc47beaed1 --- /dev/null +++ b/src/test/rustdoc/whitespace-after-where-clause.enum2.html @@ -0,0 +1,4 @@ +<div class="docblock item-decl"><pre class="rust enum"><code>pub enum Cow2<'a, B: ?<a class="trait" href="{{channel}}/core/marker/trait.Sized.html" title="trait core::marker::Sized">Sized</a> + <a class="trait" href="trait.ToOwned.html" title="trait foo::ToOwned">ToOwned</a><dyn <a class="trait" href="{{channel}}/core/clone/trait.Clone.html" title="trait core::clone::Clone">Clone</a>> + 'a> { + Borrowed(<a class="primitive" href="{{channel}}/std/primitive.reference.html">&'a </a>B), + Whatever(<a class="primitive" href="{{channel}}/std/primitive.u32.html">u32</a>), +}</code></pre></div> diff --git a/src/test/rustdoc/whitespace-after-where-clause.rs b/src/test/rustdoc/whitespace-after-where-clause.rs new file mode 100644 index 00000000000..c36386a2aa2 --- /dev/null +++ b/src/test/rustdoc/whitespace-after-where-clause.rs @@ -0,0 +1,77 @@ +// This test ensures there is no whitespace before the first brace of +// trait, enum, struct and union items when they have a where clause. + +#![crate_name = "foo"] + +// @has 'foo/trait.ToOwned.html' +// @snapshot trait - '//*[@class="docblock item-decl"]' +pub trait ToOwned<T> +where T: Clone +{ + type Owned; + fn to_owned(&self) -> Self::Owned; + fn whatever(&self) -> T; +} + +// @has 'foo/trait.ToOwned2.html' +// @snapshot trait2 - '//*[@class="docblock item-decl"]' +// There should be a whitespace before `{` in this case! +pub trait ToOwned2<T: Clone> { + type Owned; + fn to_owned(&self) -> Self::Owned; + fn whatever(&self) -> T; +} + +// @has 'foo/enum.Cow.html' +// @snapshot enum - '//*[@class="docblock item-decl"]' +pub enum Cow<'a, B: ?Sized + 'a> +where + B: ToOwned<Clone>, +{ + Borrowed(&'a B), + Whatever(u32), +} + +// @has 'foo/enum.Cow2.html' +// @snapshot enum2 - '//*[@class="docblock item-decl"]' +// There should be a whitespace before `{` in this case! +pub enum Cow2<'a, B: ?Sized + ToOwned<Clone> + 'a> { + Borrowed(&'a B), + Whatever(u32), +} + +// @has 'foo/struct.Struct.html' +// @snapshot struct - '//*[@class="docblock item-decl"]' +pub struct Struct<'a, B: ?Sized + 'a> +where + B: ToOwned<Clone>, +{ + pub a: &'a B, + pub b: u32, +} + +// @has 'foo/struct.Struct2.html' +// @snapshot struct2 - '//*[@class="docblock item-decl"]' +// There should be a whitespace before `{` in this case! +pub struct Struct2<'a, B: ?Sized + ToOwned<Clone> + 'a> { + pub a: &'a B, + pub b: u32, +} + +// @has 'foo/union.Union.html' +// @snapshot union - '//*[@class="docblock item-decl"]' +pub union Union<'a, B: ?Sized + 'a> +where + B: ToOwned<Clone>, +{ + a: &'a B, + b: u32, +} + +// @has 'foo/union.Union2.html' +// @snapshot union2 - '//*[@class="docblock item-decl"]' +// There should be a whitespace before `{` in this case! +pub union Union2<'a, B: ?Sized + ToOwned<Clone> + 'a> { + a: &'a B, + b: u32, +} diff --git a/src/test/rustdoc/whitespace-after-where-clause.struct.html b/src/test/rustdoc/whitespace-after-where-clause.struct.html new file mode 100644 index 00000000000..236cc3b30d0 --- /dev/null +++ b/src/test/rustdoc/whitespace-after-where-clause.struct.html @@ -0,0 +1,4 @@ +<div class="docblock item-decl"><pre class="rust struct"><code>pub struct Struct<'a, B: ?<a class="trait" href="{{channel}}/core/marker/trait.Sized.html" title="trait core::marker::Sized">Sized</a> + 'a> <span class="where fmt-newline">where<br />    B: <a class="trait" href="trait.ToOwned.html" title="trait foo::ToOwned">ToOwned</a><dyn <a class="trait" href="{{channel}}/core/clone/trait.Clone.html" title="trait core::clone::Clone">Clone</a>>, </span>{ + pub a: <a class="primitive" href="{{channel}}/std/primitive.reference.html">&'a </a>B, + pub b: <a class="primitive" href="{{channel}}/std/primitive.u32.html">u32</a>, +}</code></pre></div> diff --git a/src/test/rustdoc/whitespace-after-where-clause.struct2.html b/src/test/rustdoc/whitespace-after-where-clause.struct2.html new file mode 100644 index 00000000000..47f5c6ba9c8 --- /dev/null +++ b/src/test/rustdoc/whitespace-after-where-clause.struct2.html @@ -0,0 +1,4 @@ +<div class="docblock item-decl"><pre class="rust struct"><code>pub struct Struct2<'a, B: ?<a class="trait" href="{{channel}}/core/marker/trait.Sized.html" title="trait core::marker::Sized">Sized</a> + <a class="trait" href="trait.ToOwned.html" title="trait foo::ToOwned">ToOwned</a><dyn <a class="trait" href="{{channel}}/core/clone/trait.Clone.html" title="trait core::clone::Clone">Clone</a>> + 'a> { + pub a: <a class="primitive" href="{{channel}}/std/primitive.reference.html">&'a </a>B, + pub b: <a class="primitive" href="{{channel}}/std/primitive.u32.html">u32</a>, +}</code></pre></div> diff --git a/src/test/rustdoc/whitespace-after-where-clause.trait.html b/src/test/rustdoc/whitespace-after-where-clause.trait.html new file mode 100644 index 00000000000..98f03b837b5 --- /dev/null +++ b/src/test/rustdoc/whitespace-after-where-clause.trait.html @@ -0,0 +1,6 @@ +<div class="docblock item-decl"><pre class="rust trait"><code>pub trait ToOwned<T> <span class="where fmt-newline">where<br />    T: <a class="trait" href="{{channel}}/core/clone/trait.Clone.html" title="trait core::clone::Clone">Clone</a>, </span>{ + type <a href="#associatedtype.Owned" class="associatedtype">Owned</a>; + + fn <a href="#tymethod.to_owned" class="fnname">to_owned</a>(&self) -> Self::<a class="associatedtype" href="trait.ToOwned.html#associatedtype.Owned" title="type foo::ToOwned::Owned">Owned</a>; +<span class="item-spacer" /> fn <a href="#tymethod.whatever" class="fnname">whatever</a>(&self) -> T; +}</code></pre></div> diff --git a/src/test/rustdoc/whitespace-after-where-clause.trait2.html b/src/test/rustdoc/whitespace-after-where-clause.trait2.html new file mode 100644 index 00000000000..35052869e76 --- /dev/null +++ b/src/test/rustdoc/whitespace-after-where-clause.trait2.html @@ -0,0 +1,6 @@ +<div class="docblock item-decl"><pre class="rust trait"><code>pub trait ToOwned2<T: <a class="trait" href="{{channel}}/core/clone/trait.Clone.html" title="trait core::clone::Clone">Clone</a>> { + type <a href="#associatedtype.Owned" class="associatedtype">Owned</a>; + + fn <a href="#tymethod.to_owned" class="fnname">to_owned</a>(&self) -> Self::<a class="associatedtype" href="trait.ToOwned2.html#associatedtype.Owned" title="type foo::ToOwned2::Owned">Owned</a>; +<span class="item-spacer" /> fn <a href="#tymethod.whatever" class="fnname">whatever</a>(&self) -> T; +}</code></pre></div> diff --git a/src/test/rustdoc/whitespace-after-where-clause.union.html b/src/test/rustdoc/whitespace-after-where-clause.union.html new file mode 100644 index 00000000000..97e1bbcf339 --- /dev/null +++ b/src/test/rustdoc/whitespace-after-where-clause.union.html @@ -0,0 +1,3 @@ +<div class="docblock item-decl"><pre class="rust union"><code>pub union Union<'a, B: ?<a class="trait" href="{{channel}}/core/marker/trait.Sized.html" title="trait core::marker::Sized">Sized</a> + 'a> <span class="where fmt-newline">where<br />    B: <a class="trait" href="trait.ToOwned.html" title="trait foo::ToOwned">ToOwned</a><dyn <a class="trait" href="{{channel}}/core/clone/trait.Clone.html" title="trait core::clone::Clone">Clone</a>>, </span>{ + /* private fields */ +}</code></pre></div> diff --git a/src/test/rustdoc/whitespace-after-where-clause.union2.html b/src/test/rustdoc/whitespace-after-where-clause.union2.html new file mode 100644 index 00000000000..6c752a8b4c5 --- /dev/null +++ b/src/test/rustdoc/whitespace-after-where-clause.union2.html @@ -0,0 +1,3 @@ +<div class="docblock item-decl"><pre class="rust union"><code>pub union Union2<'a, B: ?<a class="trait" href="{{channel}}/core/marker/trait.Sized.html" title="trait core::marker::Sized">Sized</a> + <a class="trait" href="trait.ToOwned.html" title="trait foo::ToOwned">ToOwned</a><dyn <a class="trait" href="{{channel}}/core/clone/trait.Clone.html" title="trait core::clone::Clone">Clone</a>> + 'a> { + /* private fields */ +}</code></pre></div> diff --git a/src/test/ui-fulldeps/internal-lints/existing_doc_keyword.stderr b/src/test/ui-fulldeps/internal-lints/existing_doc_keyword.stderr index bac44f338b7..bc9fcdd7bc7 100644 --- a/src/test/ui-fulldeps/internal-lints/existing_doc_keyword.stderr +++ b/src/test/ui-fulldeps/internal-lints/existing_doc_keyword.stderr @@ -1,4 +1,4 @@ -error: Found non-existing keyword `tadam` used in `#[doc(keyword = "...")]` +error: found non-existing keyword `tadam` used in `#[doc(keyword = \"...\")]` --> $DIR/existing_doc_keyword.rs:10:1 | LL | #[doc(keyword = "tadam")] diff --git a/src/test/ui-fulldeps/session-diagnostic/diagnostic-derive.rs b/src/test/ui-fulldeps/session-diagnostic/diagnostic-derive.rs index 7bec1897fa5..56e95d70fd5 100644 --- a/src/test/ui-fulldeps/session-diagnostic/diagnostic-derive.rs +++ b/src/test/ui-fulldeps/session-diagnostic/diagnostic-derive.rs @@ -1,6 +1,8 @@ // check-fail // Tests error conditions for specifying diagnostics using #[derive(SessionDiagnostic)] +// normalize-stderr-test "the following other types implement trait `IntoDiagnosticArg`:(?:.*\n){0,9}\s+and \d+ others" -> "normalized in stderr" + // The proc_macro2 crate handles spans differently when on beta/stable release rather than nightly, // changing the output of this test. Since SessionDiagnostic is strictly internal to the compiler // the test is just ignored on stable and beta: @@ -15,7 +17,7 @@ use rustc_span::symbol::Ident; use rustc_span::Span; extern crate rustc_macros; -use rustc_macros::{SessionDiagnostic, SessionSubdiagnostic}; +use rustc_macros::{SessionDiagnostic, LintDiagnostic, SessionSubdiagnostic}; extern crate rustc_middle; use rustc_middle::ty::Ty; @@ -533,3 +535,20 @@ struct LabelWithTrailingList { //~^ ERROR `#[label(...)]` is not a valid attribute span: Span, } + +#[derive(SessionDiagnostic)] +#[lint(typeck::ambiguous_lifetime_bound)] +//~^ ERROR only `#[error(..)]` and `#[warn(..)]` are supported +struct LintsBad { +} + +#[derive(LintDiagnostic)] +#[lint(typeck::ambiguous_lifetime_bound)] +struct LintsGood { +} + +#[derive(LintDiagnostic)] +#[error(typeck::ambiguous_lifetime_bound)] +//~^ ERROR only `#[lint(..)]` is supported +struct ErrorsBad { +} diff --git a/src/test/ui-fulldeps/session-diagnostic/diagnostic-derive.stderr b/src/test/ui-fulldeps/session-diagnostic/diagnostic-derive.stderr index 0d9690e1f5a..98c22af387e 100644 --- a/src/test/ui-fulldeps/session-diagnostic/diagnostic-derive.stderr +++ b/src/test/ui-fulldeps/session-diagnostic/diagnostic-derive.stderr @@ -1,5 +1,5 @@ error: `#[derive(SessionDiagnostic)]` can only be used on structs - --> $DIR/diagnostic-derive.rs:37:1 + --> $DIR/diagnostic-derive.rs:39:1 | LL | / #[error(typeck::ambiguous_lifetime_bound, code = "E0123")] LL | | @@ -10,13 +10,13 @@ LL | | } | |_^ error: `#[error = ...]` is not a valid attribute - --> $DIR/diagnostic-derive.rs:46:1 + --> $DIR/diagnostic-derive.rs:48:1 | LL | #[error = "E0123"] | ^^^^^^^^^^^^^^^^^^ error: `#[nonsense(...)]` is not a valid attribute - --> $DIR/diagnostic-derive.rs:51:1 + --> $DIR/diagnostic-derive.rs:53:1 | LL | #[nonsense(typeck::ambiguous_lifetime_bound, code = "E0123")] | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ @@ -24,7 +24,7 @@ LL | #[nonsense(typeck::ambiguous_lifetime_bound, code = "E0123")] = help: only `error`, `warning`, `help` and `note` are valid attributes error: diagnostic kind not specified - --> $DIR/diagnostic-derive.rs:51:1 + --> $DIR/diagnostic-derive.rs:53:1 | LL | / #[nonsense(typeck::ambiguous_lifetime_bound, code = "E0123")] LL | | @@ -36,7 +36,7 @@ LL | | struct InvalidStructAttr {} = help: use the `#[error(...)]` attribute to create an error error: `#[error("...")]` is not a valid attribute - --> $DIR/diagnostic-derive.rs:58:9 + --> $DIR/diagnostic-derive.rs:60:9 | LL | #[error("E0123")] | ^^^^^^^ @@ -44,7 +44,7 @@ LL | #[error("E0123")] = help: first argument of the attribute should be the diagnostic slug error: diagnostic slug not specified - --> $DIR/diagnostic-derive.rs:58:1 + --> $DIR/diagnostic-derive.rs:60:1 | LL | / #[error("E0123")] LL | | @@ -55,7 +55,7 @@ LL | | struct InvalidLitNestedAttr {} = help: specify the slug as the first argument to the attribute, such as `#[error(typeck::example_error)]` error: `#[error(nonsense(...))]` is not a valid attribute - --> $DIR/diagnostic-derive.rs:69:9 + --> $DIR/diagnostic-derive.rs:71:9 | LL | #[error(nonsense("foo"), code = "E0123", slug = "foo")] | ^^^^^^^^^^^^^^^ @@ -63,7 +63,7 @@ LL | #[error(nonsense("foo"), code = "E0123", slug = "foo")] = help: first argument of the attribute should be the diagnostic slug error: diagnostic slug not specified - --> $DIR/diagnostic-derive.rs:69:1 + --> $DIR/diagnostic-derive.rs:71:1 | LL | / #[error(nonsense("foo"), code = "E0123", slug = "foo")] LL | | @@ -74,7 +74,7 @@ LL | | struct InvalidNestedStructAttr1 {} = help: specify the slug as the first argument to the attribute, such as `#[error(typeck::example_error)]` error: `#[error(nonsense = ...)]` is not a valid attribute - --> $DIR/diagnostic-derive.rs:75:9 + --> $DIR/diagnostic-derive.rs:77:9 | LL | #[error(nonsense = "...", code = "E0123", slug = "foo")] | ^^^^^^^^^^^^^^^^ @@ -82,7 +82,7 @@ LL | #[error(nonsense = "...", code = "E0123", slug = "foo")] = help: first argument of the attribute should be the diagnostic slug error: diagnostic slug not specified - --> $DIR/diagnostic-derive.rs:75:1 + --> $DIR/diagnostic-derive.rs:77:1 | LL | / #[error(nonsense = "...", code = "E0123", slug = "foo")] LL | | @@ -93,7 +93,7 @@ LL | | struct InvalidNestedStructAttr2 {} = help: specify the slug as the first argument to the attribute, such as `#[error(typeck::example_error)]` error: `#[error(nonsense = ...)]` is not a valid attribute - --> $DIR/diagnostic-derive.rs:81:9 + --> $DIR/diagnostic-derive.rs:83:9 | LL | #[error(nonsense = 4, code = "E0123", slug = "foo")] | ^^^^^^^^^^^^ @@ -101,7 +101,7 @@ LL | #[error(nonsense = 4, code = "E0123", slug = "foo")] = help: first argument of the attribute should be the diagnostic slug error: diagnostic slug not specified - --> $DIR/diagnostic-derive.rs:81:1 + --> $DIR/diagnostic-derive.rs:83:1 | LL | / #[error(nonsense = 4, code = "E0123", slug = "foo")] LL | | @@ -112,7 +112,7 @@ LL | | struct InvalidNestedStructAttr3 {} = help: specify the slug as the first argument to the attribute, such as `#[error(typeck::example_error)]` error: `#[error(slug = ...)]` is not a valid attribute - --> $DIR/diagnostic-derive.rs:87:59 + --> $DIR/diagnostic-derive.rs:89:59 | LL | #[error(typeck::ambiguous_lifetime_bound, code = "E0123", slug = "foo")] | ^^^^^^^^^^^^ @@ -120,103 +120,103 @@ LL | #[error(typeck::ambiguous_lifetime_bound, code = "E0123", slug = "foo")] = help: only `code` is a valid nested attributes following the slug error: `#[suggestion = ...]` is not a valid attribute - --> $DIR/diagnostic-derive.rs:94:5 + --> $DIR/diagnostic-derive.rs:96:5 | LL | #[suggestion = "bar"] | ^^^^^^^^^^^^^^^^^^^^^ error: specified multiple times - --> $DIR/diagnostic-derive.rs:101:1 + --> $DIR/diagnostic-derive.rs:103:1 | LL | #[error(typeck::ambiguous_lifetime_bound, code = "E0456")] | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ | note: previously specified here - --> $DIR/diagnostic-derive.rs:100:1 + --> $DIR/diagnostic-derive.rs:102:1 | LL | #[error(typeck::ambiguous_lifetime_bound, code = "E0123")] | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ error: specified multiple times - --> $DIR/diagnostic-derive.rs:101:1 + --> $DIR/diagnostic-derive.rs:103:1 | LL | #[error(typeck::ambiguous_lifetime_bound, code = "E0456")] | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ | note: previously specified here - --> $DIR/diagnostic-derive.rs:100:1 + --> $DIR/diagnostic-derive.rs:102:1 | LL | #[error(typeck::ambiguous_lifetime_bound, code = "E0123")] | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ error: specified multiple times - --> $DIR/diagnostic-derive.rs:101:50 + --> $DIR/diagnostic-derive.rs:103:50 | LL | #[error(typeck::ambiguous_lifetime_bound, code = "E0456")] | ^^^^^^^ | note: previously specified here - --> $DIR/diagnostic-derive.rs:100:50 + --> $DIR/diagnostic-derive.rs:102:50 | LL | #[error(typeck::ambiguous_lifetime_bound, code = "E0123")] | ^^^^^^^ error: specified multiple times - --> $DIR/diagnostic-derive.rs:109:1 + --> $DIR/diagnostic-derive.rs:111:1 | LL | #[warning(typeck::ambiguous_lifetime_bound, code = "E0293")] | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ | note: previously specified here - --> $DIR/diagnostic-derive.rs:108:1 + --> $DIR/diagnostic-derive.rs:110:1 | LL | #[error(typeck::ambiguous_lifetime_bound, code = "E0123")] | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ error: specified multiple times - --> $DIR/diagnostic-derive.rs:109:1 + --> $DIR/diagnostic-derive.rs:111:1 | LL | #[warning(typeck::ambiguous_lifetime_bound, code = "E0293")] | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ | note: previously specified here - --> $DIR/diagnostic-derive.rs:108:1 + --> $DIR/diagnostic-derive.rs:110:1 | LL | #[error(typeck::ambiguous_lifetime_bound, code = "E0123")] | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ error: specified multiple times - --> $DIR/diagnostic-derive.rs:109:52 + --> $DIR/diagnostic-derive.rs:111:52 | LL | #[warning(typeck::ambiguous_lifetime_bound, code = "E0293")] | ^^^^^^^ | note: previously specified here - --> $DIR/diagnostic-derive.rs:108:50 + --> $DIR/diagnostic-derive.rs:110:50 | LL | #[error(typeck::ambiguous_lifetime_bound, code = "E0123")] | ^^^^^^^ error: specified multiple times - --> $DIR/diagnostic-derive.rs:116:66 + --> $DIR/diagnostic-derive.rs:118:66 | LL | #[error(typeck::ambiguous_lifetime_bound, code = "E0456", code = "E0457")] | ^^^^^^^ | note: previously specified here - --> $DIR/diagnostic-derive.rs:116:50 + --> $DIR/diagnostic-derive.rs:118:50 | LL | #[error(typeck::ambiguous_lifetime_bound, code = "E0456", code = "E0457")] | ^^^^^^^ error: `#[error(typeck::ambiguous_lifetime_bound)]` is not a valid attribute - --> $DIR/diagnostic-derive.rs:121:43 + --> $DIR/diagnostic-derive.rs:123:43 | LL | #[error(typeck::ambiguous_lifetime_bound, typeck::ambiguous_lifetime_bound, code = "E0456")] | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ error: diagnostic kind not specified - --> $DIR/diagnostic-derive.rs:126:1 + --> $DIR/diagnostic-derive.rs:128:1 | LL | struct KindNotProvided {} | ^^^^^^^^^^^^^^^^^^^^^^^^^ @@ -224,7 +224,7 @@ LL | struct KindNotProvided {} = help: use the `#[error(...)]` attribute to create an error error: diagnostic slug not specified - --> $DIR/diagnostic-derive.rs:129:1 + --> $DIR/diagnostic-derive.rs:131:1 | LL | / #[error(code = "E0456")] LL | | @@ -234,13 +234,13 @@ LL | | struct SlugNotProvided {} = help: specify the slug as the first argument to the attribute, such as `#[error(typeck::example_error)]` error: the `#[primary_span]` attribute can only be applied to fields of type `Span` - --> $DIR/diagnostic-derive.rs:140:5 + --> $DIR/diagnostic-derive.rs:142:5 | LL | #[primary_span] | ^^^^^^^^^^^^^^^ error: `#[nonsense]` is not a valid attribute - --> $DIR/diagnostic-derive.rs:148:5 + --> $DIR/diagnostic-derive.rs:150:5 | LL | #[nonsense] | ^^^^^^^^^^^ @@ -248,19 +248,19 @@ LL | #[nonsense] = help: only `skip_arg`, `primary_span`, `label`, `note`, `help` and `subdiagnostic` are valid field attributes error: the `#[label(...)]` attribute can only be applied to fields of type `Span` - --> $DIR/diagnostic-derive.rs:165:5 + --> $DIR/diagnostic-derive.rs:167:5 | LL | #[label(typeck::label)] | ^^^^^^^^^^^^^^^^^^^^^^^ error: `name` doesn't refer to a field on this type - --> $DIR/diagnostic-derive.rs:173:45 + --> $DIR/diagnostic-derive.rs:175:45 | LL | #[suggestion(typeck::suggestion, code = "{name}")] | ^^^^^^^^ error: invalid format string: expected `'}'` but string was terminated - --> $DIR/diagnostic-derive.rs:178:16 + --> $DIR/diagnostic-derive.rs:180:16 | LL | #[derive(SessionDiagnostic)] | - ^ expected `'}'` in format string @@ -271,7 +271,7 @@ LL | #[derive(SessionDiagnostic)] = note: this error originates in the derive macro `SessionDiagnostic` (in Nightly builds, run with -Z macro-backtrace for more info) error: invalid format string: unmatched `}` found - --> $DIR/diagnostic-derive.rs:188:15 + --> $DIR/diagnostic-derive.rs:190:15 | LL | #[derive(SessionDiagnostic)] | ^ unmatched `}` in format string @@ -280,13 +280,13 @@ LL | #[derive(SessionDiagnostic)] = note: this error originates in the derive macro `SessionDiagnostic` (in Nightly builds, run with -Z macro-backtrace for more info) error: the `#[label(...)]` attribute can only be applied to fields of type `Span` - --> $DIR/diagnostic-derive.rs:208:5 + --> $DIR/diagnostic-derive.rs:210:5 | LL | #[label(typeck::label)] | ^^^^^^^^^^^^^^^^^^^^^^^ error: `#[suggestion(nonsense = ...)]` is not a valid attribute - --> $DIR/diagnostic-derive.rs:233:18 + --> $DIR/diagnostic-derive.rs:235:18 | LL | #[suggestion(nonsense = "bar")] | ^^^^^^^^^^^^^^^^ @@ -294,7 +294,7 @@ LL | #[suggestion(nonsense = "bar")] = help: only `message`, `code` and `applicability` are valid field attributes error: `#[suggestion(msg = ...)]` is not a valid attribute - --> $DIR/diagnostic-derive.rs:241:18 + --> $DIR/diagnostic-derive.rs:243:18 | LL | #[suggestion(msg = "bar")] | ^^^^^^^^^^^ @@ -302,7 +302,7 @@ LL | #[suggestion(msg = "bar")] = help: only `message`, `code` and `applicability` are valid field attributes error: wrong field type for suggestion - --> $DIR/diagnostic-derive.rs:263:5 + --> $DIR/diagnostic-derive.rs:265:5 | LL | / #[suggestion(typeck::suggestion, code = "This is suggested code")] LL | | @@ -312,7 +312,7 @@ LL | | suggestion: Applicability, = help: `#[suggestion(...)]` should be applied to fields of type `Span` or `(Span, Applicability)` error: type of field annotated with `#[suggestion(...)]` contains more than one `Span` - --> $DIR/diagnostic-derive.rs:278:5 + --> $DIR/diagnostic-derive.rs:280:5 | LL | / #[suggestion(typeck::suggestion, code = "This is suggested code")] LL | | @@ -320,7 +320,7 @@ LL | | suggestion: (Span, Span, Applicability), | |___________________________________________^ error: type of field annotated with `#[suggestion(...)]` contains more than one Applicability - --> $DIR/diagnostic-derive.rs:286:5 + --> $DIR/diagnostic-derive.rs:288:5 | LL | / #[suggestion(typeck::suggestion, code = "This is suggested code")] LL | | @@ -328,72 +328,88 @@ LL | | suggestion: (Applicability, Applicability, Span), | |____________________________________________________^ error: `#[label = ...]` is not a valid attribute - --> $DIR/diagnostic-derive.rs:294:5 + --> $DIR/diagnostic-derive.rs:296:5 | LL | #[label = "bar"] | ^^^^^^^^^^^^^^^^ error: applicability cannot be set in both the field and attribute - --> $DIR/diagnostic-derive.rs:445:52 + --> $DIR/diagnostic-derive.rs:447:52 | LL | #[suggestion(typeck::suggestion, code = "...", applicability = "maybe-incorrect")] | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ error: invalid applicability - --> $DIR/diagnostic-derive.rs:453:52 + --> $DIR/diagnostic-derive.rs:455:52 | LL | #[suggestion(typeck::suggestion, code = "...", applicability = "batman")] | ^^^^^^^^^^^^^^^^^^^^^^^^ error: `#[label(...)]` is not a valid attribute - --> $DIR/diagnostic-derive.rs:516:5 + --> $DIR/diagnostic-derive.rs:518:5 | LL | #[label(typeck::label, foo)] | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ error: `#[label(...)]` is not a valid attribute - --> $DIR/diagnostic-derive.rs:524:5 + --> $DIR/diagnostic-derive.rs:526:5 | LL | #[label(typeck::label, foo = "...")] | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ error: `#[label(...)]` is not a valid attribute - --> $DIR/diagnostic-derive.rs:532:5 + --> $DIR/diagnostic-derive.rs:534:5 | LL | #[label(typeck::label, foo("..."))] | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ +error: only `#[error(..)]` and `#[warn(..)]` are supported + --> $DIR/diagnostic-derive.rs:540:1 + | +LL | / #[lint(typeck::ambiguous_lifetime_bound)] +LL | | +LL | | struct LintsBad { +LL | | } + | |_^ + | + = help: use the `#[error(...)]` attribute to create a error + +error: only `#[lint(..)]` is supported + --> $DIR/diagnostic-derive.rs:551:1 + | +LL | / #[error(typeck::ambiguous_lifetime_bound)] +LL | | +LL | | struct ErrorsBad { +LL | | } + | |_^ + | + = help: use the `#[lint(...)]` attribute to create a lint + error: cannot find attribute `nonsense` in this scope - --> $DIR/diagnostic-derive.rs:51:3 + --> $DIR/diagnostic-derive.rs:53:3 | LL | #[nonsense(typeck::ambiguous_lifetime_bound, code = "E0123")] | ^^^^^^^^ error: cannot find attribute `nonsense` in this scope - --> $DIR/diagnostic-derive.rs:148:7 + --> $DIR/diagnostic-derive.rs:150:7 | LL | #[nonsense] | ^^^^^^^^ error[E0425]: cannot find value `nonsense` in module `rustc_errors::fluent` - --> $DIR/diagnostic-derive.rs:64:9 + --> $DIR/diagnostic-derive.rs:66:9 | LL | #[error(nonsense, code = "E0123")] | ^^^^^^^^ not found in `rustc_errors::fluent` error[E0277]: the trait bound `Hello: IntoDiagnosticArg` is not satisfied - --> $DIR/diagnostic-derive.rs:338:10 + --> $DIR/diagnostic-derive.rs:340:10 | LL | #[derive(SessionDiagnostic)] | ^^^^^^^^^^^^^^^^^ the trait `IntoDiagnosticArg` is not implemented for `Hello` | - = help: the following other types implement trait `IntoDiagnosticArg`: - &'a str - Ident - String - Symbol - rustc_middle::ty::Ty<'tcx> - usize + = help: normalized in stderr note: required by a bound in `DiagnosticBuilder::<'a, G>::set_arg` --> $COMPILER_DIR/rustc_errors/src/diagnostic_builder.rs:538:19 | @@ -401,7 +417,7 @@ LL | arg: impl IntoDiagnosticArg, | ^^^^^^^^^^^^^^^^^ required by this bound in `DiagnosticBuilder::<'a, G>::set_arg` = note: this error originates in the derive macro `SessionDiagnostic` (in Nightly builds, run with -Z macro-backtrace for more info) -error: aborting due to 46 previous errors +error: aborting due to 48 previous errors Some errors have detailed explanations: E0277, E0425. For more information about an error, try `rustc --explain E0277`. diff --git a/src/test/ui/abi/rustcall-generic.rs b/src/test/ui/abi/rustcall-generic.rs index 2fa41a7e35a..411c98e1031 100644 --- a/src/test/ui/abi/rustcall-generic.rs +++ b/src/test/ui/abi/rustcall-generic.rs @@ -1,4 +1,7 @@ +// revisions: normal opt // check-pass +//[opt] compile-flags: -Zmir-opt-level=3 + #![feature(unboxed_closures)] extern "rust-call" fn foo<T>(_: T) {} diff --git a/src/test/ui/aligned_enum_cast.rs b/src/test/ui/aligned_enum_cast.rs index 4b5776a6aa8..1ddf127172e 100644 --- a/src/test/ui/aligned_enum_cast.rs +++ b/src/test/ui/aligned_enum_cast.rs @@ -11,5 +11,15 @@ enum Aligned { fn main() { let aligned = Aligned::Zero; let fo = aligned as u8; - println!("foo {}",fo); + println!("foo {}", fo); + assert_eq!(fo, 0); + println!("{}", tou8(Aligned::Zero)); + assert_eq!(tou8(Aligned::Zero), 0); +} + +#[inline(never)] +fn tou8(al: Aligned) -> u8 { + // Cast behind a function call so ConstProp does not see it + // (so that we can test codegen). + al as u8 } diff --git a/src/test/ui/array-slice-vec/array_const_index-0.stderr b/src/test/ui/array-slice-vec/array_const_index-0.stderr index b44251efdea..4832398713d 100644 --- a/src/test/ui/array-slice-vec/array_const_index-0.stderr +++ b/src/test/ui/array-slice-vec/array_const_index-0.stderr @@ -2,9 +2,7 @@ error: any use of this value will cause an error --> $DIR/array_const_index-0.rs:2:16 | LL | const B: i32 = (&A)[1]; - | ---------------^^^^^^^- - | | - | index out of bounds: the length is 0 but the index is 1 + | ------------ ^^^^^^^ index out of bounds: the length is 0 but the index is 1 | = note: `#[deny(const_err)]` on by default = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release! @@ -17,9 +15,7 @@ error: any use of this value will cause an error --> $DIR/array_const_index-0.rs:2:16 | LL | const B: i32 = (&A)[1]; - | ---------------^^^^^^^- - | | - | index out of bounds: the length is 0 but the index is 1 + | ------------ ^^^^^^^ index out of bounds: the length is 0 but the index is 1 | = note: `#[deny(const_err)]` on by default = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release! diff --git a/src/test/ui/array-slice-vec/array_const_index-1.stderr b/src/test/ui/array-slice-vec/array_const_index-1.stderr index 8beebafb04c..361f518c052 100644 --- a/src/test/ui/array-slice-vec/array_const_index-1.stderr +++ b/src/test/ui/array-slice-vec/array_const_index-1.stderr @@ -2,9 +2,7 @@ error: any use of this value will cause an error --> $DIR/array_const_index-1.rs:2:16 | LL | const B: i32 = A[1]; - | ---------------^^^^- - | | - | index out of bounds: the length is 0 but the index is 1 + | ------------ ^^^^ index out of bounds: the length is 0 but the index is 1 | = note: `#[deny(const_err)]` on by default = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release! @@ -17,9 +15,7 @@ error: any use of this value will cause an error --> $DIR/array_const_index-1.rs:2:16 | LL | const B: i32 = A[1]; - | ---------------^^^^- - | | - | index out of bounds: the length is 0 but the index is 1 + | ------------ ^^^^ index out of bounds: the length is 0 but the index is 1 | = note: `#[deny(const_err)]` on by default = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release! diff --git a/src/test/ui/array-slice-vec/infer_array_len.stderr b/src/test/ui/array-slice-vec/infer_array_len.stderr index 8da6d97251b..919550cac30 100644 --- a/src/test/ui/array-slice-vec/infer_array_len.stderr +++ b/src/test/ui/array-slice-vec/infer_array_len.stderr @@ -4,7 +4,6 @@ error[E0282]: type annotations needed LL | let [_, _] = a.into(); | ^^^^^^ | - = note: type must be known at this point help: consider giving this pattern a type | LL | let [_, _]: _ = a.into(); diff --git a/src/test/ui/array-slice-vec/slice-pat-type-mismatches.stderr b/src/test/ui/array-slice-vec/slice-pat-type-mismatches.stderr index 20a5b99845b..70a4cbebeee 100644 --- a/src/test/ui/array-slice-vec/slice-pat-type-mismatches.stderr +++ b/src/test/ui/array-slice-vec/slice-pat-type-mismatches.stderr @@ -27,8 +27,6 @@ error[E0282]: type annotations needed | LL | [] => {} | ^^ cannot infer type - | - = note: type must be known at this point error: aborting due to 5 previous errors diff --git a/src/test/ui/associated-consts/assoc-const-ty-mismatch.stderr b/src/test/ui/associated-consts/assoc-const-ty-mismatch.stderr index 703245145ce..58a8aceca2f 100644 --- a/src/test/ui/associated-consts/assoc-const-ty-mismatch.stderr +++ b/src/test/ui/associated-consts/assoc-const-ty-mismatch.stderr @@ -8,7 +8,7 @@ note: associated constant defined here does not match type --> $DIR/assoc-const-ty-mismatch.rs:5:3 | LL | const N: usize; - | ^^^^^^^^^^^^^^^ + | ^^^^^^^^^^^^^^ error: mismatch in bind of associated type, got const --> $DIR/assoc-const-ty-mismatch.rs:25:18 @@ -20,7 +20,7 @@ note: associated type defined here does not match const --> $DIR/assoc-const-ty-mismatch.rs:9:3 | LL | type T; - | ^^^^^^^ + | ^^^^^^ error: aborting due to 2 previous errors diff --git a/src/test/ui/associated-consts/associated-const-ambiguity-report.stderr b/src/test/ui/associated-consts/associated-const-ambiguity-report.stderr index 60cf9a533cd..5435f22321c 100644 --- a/src/test/ui/associated-consts/associated-const-ambiguity-report.stderr +++ b/src/test/ui/associated-consts/associated-const-ambiguity-report.stderr @@ -8,12 +8,12 @@ note: candidate #1 is defined in an impl of the trait `Foo` for the type `i32` --> $DIR/associated-const-ambiguity-report.rs:10:5 | LL | const ID: i32 = 1; - | ^^^^^^^^^^^^^^^^^^ + | ^^^^^^^^^^^^^ note: candidate #2 is defined in an impl of the trait `Bar` for the type `i32` --> $DIR/associated-const-ambiguity-report.rs:14:5 | LL | const ID: i32 = 3; - | ^^^^^^^^^^^^^^^^^^ + | ^^^^^^^^^^^^^ help: disambiguate the associated constant for candidate #1 | LL | const X: i32 = <i32 as Foo>::ID; diff --git a/src/test/ui/associated-consts/associated-const-dead-code.stderr b/src/test/ui/associated-consts/associated-const-dead-code.stderr index 7a4dbfe087b..cc701cc4b94 100644 --- a/src/test/ui/associated-consts/associated-const-dead-code.stderr +++ b/src/test/ui/associated-consts/associated-const-dead-code.stderr @@ -1,8 +1,8 @@ error: associated constant `BAR` is never used - --> $DIR/associated-const-dead-code.rs:6:5 + --> $DIR/associated-const-dead-code.rs:6:11 | LL | const BAR: u32 = 1; - | ^^^^^^^^^^^^^^^^^^^ + | ^^^ | note: the lint level is defined here --> $DIR/associated-const-dead-code.rs:1:9 diff --git a/src/test/ui/associated-consts/associated-const-private-impl.stderr b/src/test/ui/associated-consts/associated-const-private-impl.stderr index aa356c596f8..a3fa3002e1e 100644 --- a/src/test/ui/associated-consts/associated-const-private-impl.stderr +++ b/src/test/ui/associated-consts/associated-const-private-impl.stderr @@ -2,7 +2,7 @@ error[E0624]: associated constant `ID` is private --> $DIR/associated-const-private-impl.rs:13:30 | LL | const ID: i32 = 1; - | ------------------ private associated constant defined here + | ------------- private associated constant defined here ... LL | assert_eq!(1, bar1::Foo::ID); | ^^ private associated constant diff --git a/src/test/ui/associated-consts/defaults-cyclic-fail.stderr b/src/test/ui/associated-consts/defaults-cyclic-fail.stderr index c4cd9c2a49f..582473905cf 100644 --- a/src/test/ui/associated-consts/defaults-cyclic-fail.stderr +++ b/src/test/ui/associated-consts/defaults-cyclic-fail.stderr @@ -2,13 +2,13 @@ error[E0391]: cycle detected when const-evaluating + checking `Tr::A` --> $DIR/defaults-cyclic-fail.rs:5:5 | LL | const A: u8 = Self::B; - | ^^^^^^^^^^^^^^^^^^^^^^ + | ^^^^^^^^^^^ | note: ...which requires const-evaluating + checking `Tr::B`... --> $DIR/defaults-cyclic-fail.rs:8:5 | LL | const B: u8 = Self::A; - | ^^^^^^^^^^^^^^^^^^^^^^ + | ^^^^^^^^^^^ = note: ...which again requires const-evaluating + checking `Tr::A`, completing the cycle note: cycle used when const-evaluating + checking `main::promoted[1]` --> $DIR/defaults-cyclic-fail.rs:16:16 diff --git a/src/test/ui/associated-consts/defaults-not-assumed-fail.stderr b/src/test/ui/associated-consts/defaults-not-assumed-fail.stderr index f04ea0b7477..66ee6031c71 100644 --- a/src/test/ui/associated-consts/defaults-not-assumed-fail.stderr +++ b/src/test/ui/associated-consts/defaults-not-assumed-fail.stderr @@ -2,9 +2,7 @@ error: any use of this value will cause an error --> $DIR/defaults-not-assumed-fail.rs:8:19 | LL | const B: u8 = Self::A + 1; - | --------------^^^^^^^^^^^- - | | - | attempt to compute `u8::MAX + 1_u8`, which would overflow + | ----------- ^^^^^^^^^^^ attempt to compute `u8::MAX + 1_u8`, which would overflow | = note: `#[deny(const_err)]` on by default = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release! @@ -34,9 +32,7 @@ error: any use of this value will cause an error --> $DIR/defaults-not-assumed-fail.rs:8:19 | LL | const B: u8 = Self::A + 1; - | --------------^^^^^^^^^^^- - | | - | attempt to compute `u8::MAX + 1_u8`, which would overflow + | ----------- ^^^^^^^^^^^ attempt to compute `u8::MAX + 1_u8`, which would overflow | = note: `#[deny(const_err)]` on by default = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release! diff --git a/src/test/ui/associated-consts/issue-24949-assoc-const-static-recursion-impl.stderr b/src/test/ui/associated-consts/issue-24949-assoc-const-static-recursion-impl.stderr index b4dc730d863..51a50cfdaf9 100644 --- a/src/test/ui/associated-consts/issue-24949-assoc-const-static-recursion-impl.stderr +++ b/src/test/ui/associated-consts/issue-24949-assoc-const-static-recursion-impl.stderr @@ -1,4 +1,4 @@ -error[E0391]: cycle detected when elaborating drops for `<impl at $DIR/issue-24949-assoc-const-static-recursion-impl.rs:11:1: 13:2>::BAR` +error[E0391]: cycle detected when elaborating drops for `<impl at $DIR/issue-24949-assoc-const-static-recursion-impl.rs:11:1: 11:19>::BAR` --> $DIR/issue-24949-assoc-const-static-recursion-impl.rs:12:22 | LL | const BAR: u32 = IMPL_REF_BAR; @@ -8,23 +8,23 @@ note: ...which requires const-evaluating + checking `IMPL_REF_BAR`... --> $DIR/issue-24949-assoc-const-static-recursion-impl.rs:7:1 | LL | const IMPL_REF_BAR: u32 = GlobalImplRef::BAR; - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | ^^^^^^^^^^^^^^^^^^^^^^^ note: ...which requires const-evaluating + checking `IMPL_REF_BAR`... --> $DIR/issue-24949-assoc-const-static-recursion-impl.rs:7:1 | LL | const IMPL_REF_BAR: u32 = GlobalImplRef::BAR; - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ -note: ...which requires const-evaluating + checking `<impl at $DIR/issue-24949-assoc-const-static-recursion-impl.rs:11:1: 13:2>::BAR`... + | ^^^^^^^^^^^^^^^^^^^^^^^ +note: ...which requires const-evaluating + checking `<impl at $DIR/issue-24949-assoc-const-static-recursion-impl.rs:11:1: 11:19>::BAR`... --> $DIR/issue-24949-assoc-const-static-recursion-impl.rs:12:5 | LL | const BAR: u32 = IMPL_REF_BAR; - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ -note: ...which requires caching mir of `<impl at $DIR/issue-24949-assoc-const-static-recursion-impl.rs:11:1: 13:2>::BAR` for CTFE... + | ^^^^^^^^^^^^^^ +note: ...which requires caching mir of `<impl at $DIR/issue-24949-assoc-const-static-recursion-impl.rs:11:1: 11:19>::BAR` for CTFE... --> $DIR/issue-24949-assoc-const-static-recursion-impl.rs:12:5 | LL | const BAR: u32 = IMPL_REF_BAR; - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ - = note: ...which again requires elaborating drops for `<impl at $DIR/issue-24949-assoc-const-static-recursion-impl.rs:11:1: 13:2>::BAR`, completing the cycle + | ^^^^^^^^^^^^^^ + = note: ...which again requires elaborating drops for `<impl at $DIR/issue-24949-assoc-const-static-recursion-impl.rs:11:1: 11:19>::BAR`, completing the cycle = note: cycle used when running analysis passes on this crate error: aborting due to previous error diff --git a/src/test/ui/associated-consts/issue-24949-assoc-const-static-recursion-trait-default.stderr b/src/test/ui/associated-consts/issue-24949-assoc-const-static-recursion-trait-default.stderr index 97ede6ad388..b9d1808feb3 100644 --- a/src/test/ui/associated-consts/issue-24949-assoc-const-static-recursion-trait-default.stderr +++ b/src/test/ui/associated-consts/issue-24949-assoc-const-static-recursion-trait-default.stderr @@ -8,22 +8,22 @@ note: ...which requires const-evaluating + checking `DEFAULT_REF_BAR`... --> $DIR/issue-24949-assoc-const-static-recursion-trait-default.rs:11:1 | LL | const DEFAULT_REF_BAR: u32 = <GlobalDefaultRef>::BAR; - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | ^^^^^^^^^^^^^^^^^^^^^^^^^^ note: ...which requires const-evaluating + checking `DEFAULT_REF_BAR`... --> $DIR/issue-24949-assoc-const-static-recursion-trait-default.rs:11:1 | LL | const DEFAULT_REF_BAR: u32 = <GlobalDefaultRef>::BAR; - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | ^^^^^^^^^^^^^^^^^^^^^^^^^^ note: ...which requires const-evaluating + checking `FooDefault::BAR`... --> $DIR/issue-24949-assoc-const-static-recursion-trait-default.rs:8:5 | LL | const BAR: u32 = DEFAULT_REF_BAR; - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | ^^^^^^^^^^^^^^ note: ...which requires caching mir of `FooDefault::BAR` for CTFE... --> $DIR/issue-24949-assoc-const-static-recursion-trait-default.rs:8:5 | LL | const BAR: u32 = DEFAULT_REF_BAR; - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | ^^^^^^^^^^^^^^ = note: ...which again requires elaborating drops for `FooDefault::BAR`, completing the cycle = note: cycle used when running analysis passes on this crate diff --git a/src/test/ui/associated-consts/issue-24949-assoc-const-static-recursion-trait.stderr b/src/test/ui/associated-consts/issue-24949-assoc-const-static-recursion-trait.stderr index bd97c31229e..271e69206cd 100644 --- a/src/test/ui/associated-consts/issue-24949-assoc-const-static-recursion-trait.stderr +++ b/src/test/ui/associated-consts/issue-24949-assoc-const-static-recursion-trait.stderr @@ -1,4 +1,4 @@ -error[E0391]: cycle detected when elaborating drops for `<impl at $DIR/issue-24949-assoc-const-static-recursion-trait.rs:11:1: 13:2>::BAR` +error[E0391]: cycle detected when elaborating drops for `<impl at $DIR/issue-24949-assoc-const-static-recursion-trait.rs:11:1: 11:28>::BAR` --> $DIR/issue-24949-assoc-const-static-recursion-trait.rs:12:22 | LL | const BAR: u32 = TRAIT_REF_BAR; @@ -8,23 +8,23 @@ note: ...which requires const-evaluating + checking `TRAIT_REF_BAR`... --> $DIR/issue-24949-assoc-const-static-recursion-trait.rs:7:1 | LL | const TRAIT_REF_BAR: u32 = <GlobalTraitRef>::BAR; - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | ^^^^^^^^^^^^^^^^^^^^^^^^ note: ...which requires const-evaluating + checking `TRAIT_REF_BAR`... --> $DIR/issue-24949-assoc-const-static-recursion-trait.rs:7:1 | LL | const TRAIT_REF_BAR: u32 = <GlobalTraitRef>::BAR; - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ -note: ...which requires const-evaluating + checking `<impl at $DIR/issue-24949-assoc-const-static-recursion-trait.rs:11:1: 13:2>::BAR`... + | ^^^^^^^^^^^^^^^^^^^^^^^^ +note: ...which requires const-evaluating + checking `<impl at $DIR/issue-24949-assoc-const-static-recursion-trait.rs:11:1: 11:28>::BAR`... --> $DIR/issue-24949-assoc-const-static-recursion-trait.rs:12:5 | LL | const BAR: u32 = TRAIT_REF_BAR; - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ -note: ...which requires caching mir of `<impl at $DIR/issue-24949-assoc-const-static-recursion-trait.rs:11:1: 13:2>::BAR` for CTFE... + | ^^^^^^^^^^^^^^ +note: ...which requires caching mir of `<impl at $DIR/issue-24949-assoc-const-static-recursion-trait.rs:11:1: 11:28>::BAR` for CTFE... --> $DIR/issue-24949-assoc-const-static-recursion-trait.rs:12:5 | LL | const BAR: u32 = TRAIT_REF_BAR; - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ - = note: ...which again requires elaborating drops for `<impl at $DIR/issue-24949-assoc-const-static-recursion-trait.rs:11:1: 13:2>::BAR`, completing the cycle + | ^^^^^^^^^^^^^^ + = note: ...which again requires elaborating drops for `<impl at $DIR/issue-24949-assoc-const-static-recursion-trait.rs:11:1: 11:28>::BAR`, completing the cycle = note: cycle used when running analysis passes on this crate error: aborting due to previous error 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 ad21b38d07e..f4efd131248 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 @@ -2,7 +2,7 @@ error[E0201]: duplicate definitions with name `bar`: --> $DIR/associated-item-duplicate-names-2.rs:5:5 | LL | const bar: bool = true; - | ----------------------- previous definition of `bar` here + | --------------- previous definition of `bar` here LL | fn bar() {} | ^^^^^^^^ duplicate definition diff --git a/src/test/ui/associated-item/associated-item-duplicate-names-3.stderr b/src/test/ui/associated-item/associated-item-duplicate-names-3.stderr index 57495863c98..03782f66348 100644 --- a/src/test/ui/associated-item/associated-item-duplicate-names-3.stderr +++ b/src/test/ui/associated-item/associated-item-duplicate-names-3.stderr @@ -2,9 +2,9 @@ error[E0201]: duplicate definitions with name `Bar`: --> $DIR/associated-item-duplicate-names-3.rs:14:5 | LL | type Bar = i16; - | --------------- previous definition of `Bar` here + | -------- previous definition of `Bar` here LL | type Bar = u16; - | ^^^^^^^^^^^^^^^ duplicate definition + | ^^^^^^^^ duplicate definition error: aborting due to previous error diff --git a/src/test/ui/associated-item/associated-item-duplicate-names.stderr b/src/test/ui/associated-item/associated-item-duplicate-names.stderr index f4af9e02939..c9119c10271 100644 --- a/src/test/ui/associated-item/associated-item-duplicate-names.stderr +++ b/src/test/ui/associated-item/associated-item-duplicate-names.stderr @@ -2,17 +2,17 @@ error[E0201]: duplicate definitions with name `Ty`: --> $DIR/associated-item-duplicate-names.rs:11:5 | LL | type Ty = (); - | ------------- previous definition of `Ty` here + | ------- previous definition of `Ty` here LL | type Ty = usize; - | ^^^^^^^^^^^^^^^^ duplicate definition + | ^^^^^^^ duplicate definition error[E0201]: duplicate definitions with name `BAR`: --> $DIR/associated-item-duplicate-names.rs:13:5 | LL | const BAR: u32 = 7; - | ------------------- previous definition of `BAR` here + | -------------- previous definition of `BAR` here LL | const BAR: u32 = 8; - | ^^^^^^^^^^^^^^^^^^^ duplicate definition + | ^^^^^^^^^^^^^^ duplicate definition error: aborting due to 2 previous errors diff --git a/src/test/ui/associated-types/associated-type-projection-ambig-between-bound-and-where-clause.stderr b/src/test/ui/associated-types/associated-type-projection-ambig-between-bound-and-where-clause.stderr index 19fc2f652c6..236552baf92 100644 --- a/src/test/ui/associated-types/associated-type-projection-ambig-between-bound-and-where-clause.stderr +++ b/src/test/ui/associated-types/associated-type-projection-ambig-between-bound-and-where-clause.stderr @@ -2,10 +2,10 @@ error[E0221]: ambiguous associated type `Color` in bounds of `C` --> $DIR/associated-type-projection-ambig-between-bound-and-where-clause.rs:16:24 | LL | type Color; - | ----------- ambiguous `Color` from `Vehicle` + | ---------- ambiguous `Color` from `Vehicle` ... LL | type Color; - | ----------- ambiguous `Color` from `Box` + | ---------- ambiguous `Color` from `Box` ... LL | fn a<C:Vehicle+Box>(_: C::Color) { | ^^^^^^^^ ambiguous associated type `Color` @@ -23,10 +23,10 @@ error[E0221]: ambiguous associated type `Color` in bounds of `C` --> $DIR/associated-type-projection-ambig-between-bound-and-where-clause.rs:20:12 | LL | type Color; - | ----------- ambiguous `Color` from `Vehicle` + | ---------- ambiguous `Color` from `Vehicle` ... LL | type Color; - | ----------- ambiguous `Color` from `Box` + | ---------- ambiguous `Color` from `Box` ... LL | fn b<C>(_: C::Color) where C : Vehicle+Box { | ^^^^^^^^ ambiguous associated type `Color` @@ -44,10 +44,10 @@ error[E0221]: ambiguous associated type `Color` in bounds of `C` --> $DIR/associated-type-projection-ambig-between-bound-and-where-clause.rs:24:12 | LL | type Color; - | ----------- ambiguous `Color` from `Vehicle` + | ---------- ambiguous `Color` from `Vehicle` ... LL | type Color; - | ----------- ambiguous `Color` from `Box` + | ---------- ambiguous `Color` from `Box` ... LL | fn c<C>(_: C::Color) where C : Vehicle, C : Box { | ^^^^^^^^ ambiguous associated type `Color` @@ -65,10 +65,10 @@ error[E0221]: ambiguous associated type `Color` in bounds of `X` --> $DIR/associated-type-projection-ambig-between-bound-and-where-clause.rs:35:20 | LL | type Color; - | ----------- ambiguous `Color` from `Vehicle` + | ---------- ambiguous `Color` from `Vehicle` ... LL | type Color; - | ----------- ambiguous `Color` from `Box` + | ---------- ambiguous `Color` from `Box` ... LL | fn e(&self, _: X::Color) where X : Box; | ^^^^^^^^ ambiguous associated type `Color` @@ -86,10 +86,10 @@ error[E0221]: ambiguous associated type `Color` in bounds of `X` --> $DIR/associated-type-projection-ambig-between-bound-and-where-clause.rs:38:20 | LL | type Color; - | ----------- ambiguous `Color` from `Vehicle` + | ---------- ambiguous `Color` from `Vehicle` ... LL | type Color; - | ----------- ambiguous `Color` from `Box` + | ---------- ambiguous `Color` from `Box` ... LL | fn f(&self, _: X::Color) where X : Box { } | ^^^^^^^^ ambiguous associated type `Color` @@ -107,10 +107,10 @@ error[E0221]: ambiguous associated type `Color` in bounds of `X` --> $DIR/associated-type-projection-ambig-between-bound-and-where-clause.rs:30:20 | LL | type Color; - | ----------- ambiguous `Color` from `Vehicle` + | ---------- ambiguous `Color` from `Vehicle` ... LL | type Color; - | ----------- ambiguous `Color` from `Box` + | ---------- ambiguous `Color` from `Box` ... LL | fn d(&self, _: X::Color) where X : Box { } | ^^^^^^^^ ambiguous associated type `Color` diff --git a/src/test/ui/associated-types/associated-type-projection-from-multiple-supertraits.stderr b/src/test/ui/associated-types/associated-type-projection-from-multiple-supertraits.stderr index 66a4899c77f..e765f932398 100644 --- a/src/test/ui/associated-types/associated-type-projection-from-multiple-supertraits.stderr +++ b/src/test/ui/associated-types/associated-type-projection-from-multiple-supertraits.stderr @@ -10,10 +10,10 @@ error[E0221]: ambiguous associated type `Color` in bounds of `C` --> $DIR/associated-type-projection-from-multiple-supertraits.rs:19:32 | LL | type Color; - | ----------- ambiguous `Color` from `Vehicle` + | ---------- ambiguous `Color` from `Vehicle` ... LL | type Color; - | ----------- ambiguous `Color` from `Box` + | ---------- ambiguous `Color` from `Box` ... LL | fn dent<C:BoxCar>(c: C, color: C::Color) { | ^^^^^^^^ ambiguous associated type `Color` @@ -31,10 +31,10 @@ error[E0222]: ambiguous associated type `Color` in bounds of `BoxCar` --> $DIR/associated-type-projection-from-multiple-supertraits.rs:23:37 | LL | type Color; - | ----------- ambiguous `Color` from `Vehicle` + | ---------- ambiguous `Color` from `Vehicle` ... LL | type Color; - | ----------- ambiguous `Color` from `Box` + | ---------- ambiguous `Color` from `Box` ... LL | fn dent_object<COLOR>(c: dyn BoxCar<Color=COLOR>) { | ^^^^^^^^^^^ ambiguous associated type `Color` @@ -49,10 +49,10 @@ error[E0191]: the value of the associated types `Color` (from trait `Box`), `Col --> $DIR/associated-type-projection-from-multiple-supertraits.rs:23:30 | LL | type Color; - | ----------- `Vehicle::Color` defined here + | ---------- `Vehicle::Color` defined here ... LL | type Color; - | ----------- `Box::Color` defined here + | ---------- `Box::Color` defined here ... LL | fn dent_object<COLOR>(c: dyn BoxCar<Color=COLOR>) { | ^^^^^^^^^^^^^^^^^^^ associated types `Color` (from trait `Vehicle`), `Color` (from trait `Box`) must be specified @@ -63,10 +63,10 @@ error[E0221]: ambiguous associated type `Color` in bounds of `C` --> $DIR/associated-type-projection-from-multiple-supertraits.rs:28:29 | LL | type Color; - | ----------- ambiguous `Color` from `Vehicle` + | ---------- ambiguous `Color` from `Vehicle` ... LL | type Color; - | ----------- ambiguous `Color` from `Box` + | ---------- ambiguous `Color` from `Box` ... LL | fn paint<C:BoxCar>(c: C, d: C::Color) { | ^^^^^^^^ ambiguous associated type `Color` @@ -84,10 +84,10 @@ error[E0191]: the value of the associated types `Color` (from trait `Box`), `Col --> $DIR/associated-type-projection-from-multiple-supertraits.rs:32:32 | LL | type Color; - | ----------- `Vehicle::Color` defined here + | ---------- `Vehicle::Color` defined here ... LL | type Color; - | ----------- `Box::Color` defined here + | ---------- `Box::Color` defined here ... LL | fn dent_object_2<COLOR>(c: dyn BoxCar) where <dyn BoxCar as Vehicle>::Color = COLOR { | ^^^^^^ associated types `Color` (from trait `Vehicle`), `Color` (from trait `Box`) must be specified diff --git a/src/test/ui/associated-types/associated-types-coherence-failure.stderr b/src/test/ui/associated-types/associated-types-coherence-failure.stderr index 211613b3714..40c02dca32f 100644 --- a/src/test/ui/associated-types/associated-types-coherence-failure.stderr +++ b/src/test/ui/associated-types/associated-types-coherence-failure.stderr @@ -2,19 +2,19 @@ error[E0119]: conflicting implementations of trait `IntoCow<'_, _>` for type `Co --> $DIR/associated-types-coherence-failure.rs:21:1 | LL | impl<'a, B: ?Sized> IntoCow<'a, B> for <B as ToOwned>::Owned where B: ToOwned { - | ----------------------------------------------------------------------------- first implementation here + | ------------------------------------------------------------ first implementation here ... LL | impl<'a, B: ?Sized> IntoCow<'a, B> for Cow<'a, B> where B: ToOwned { - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ conflicting implementation for `Cow<'_, _>` + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ conflicting implementation for `Cow<'_, _>` error[E0119]: conflicting implementations of trait `IntoCow<'_, _>` for type `&_` --> $DIR/associated-types-coherence-failure.rs:28:1 | LL | impl<'a, B: ?Sized> IntoCow<'a, B> for <B as ToOwned>::Owned where B: ToOwned { - | ----------------------------------------------------------------------------- first implementation here + | ------------------------------------------------------------ first implementation here ... LL | impl<'a, B: ?Sized> IntoCow<'a, B> for &'a B where B: ToOwned { - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ conflicting implementation for `&_` + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ conflicting implementation for `&_` error: aborting due to 2 previous errors diff --git a/src/test/ui/associated-types/associated-types-incomplete-object.stderr b/src/test/ui/associated-types/associated-types-incomplete-object.stderr index 24732271c42..32866c71468 100644 --- a/src/test/ui/associated-types/associated-types-incomplete-object.stderr +++ b/src/test/ui/associated-types/associated-types-incomplete-object.stderr @@ -2,7 +2,7 @@ error[E0191]: the value of the associated type `B` (from trait `Foo`) must be sp --> $DIR/associated-types-incomplete-object.rs:23:30 | LL | type B; - | ------- `B` defined here + | ------ `B` defined here ... LL | let b = &42isize as &dyn Foo<A=usize>; | ^^^^^^^^^^^^ help: specify the associated type: `Foo<A=usize, B = Type>` @@ -11,7 +11,7 @@ error[E0191]: the value of the associated type `A` (from trait `Foo`) must be sp --> $DIR/associated-types-incomplete-object.rs:26:30 | LL | type A; - | ------- `A` defined here + | ------ `A` defined here ... LL | let c = &42isize as &dyn Foo<B=char>; | ^^^^^^^^^^^ help: specify the associated type: `Foo<B=char, A = Type>` @@ -20,9 +20,9 @@ error[E0191]: the value of the associated types `A` (from trait `Foo`), `B` (fro --> $DIR/associated-types-incomplete-object.rs:29:30 | LL | type A; - | ------- `A` defined here + | ------ `A` defined here LL | type B; - | ------- `B` defined here + | ------ `B` defined here ... LL | let d = &42isize as &dyn Foo; | ^^^ help: specify the associated types: `Foo<A = Type, B = Type>` diff --git a/src/test/ui/associated-types/associated-types-issue-17359.stderr b/src/test/ui/associated-types/associated-types-issue-17359.stderr index 575a072c558..9e40d809586 100644 --- a/src/test/ui/associated-types/associated-types-issue-17359.stderr +++ b/src/test/ui/associated-types/associated-types-issue-17359.stderr @@ -2,7 +2,7 @@ error[E0046]: not all trait items implemented, missing: `Type` --> $DIR/associated-types-issue-17359.rs:8:1 | LL | type Type; - | ---------- `Type` from trait + | --------- `Type` from trait ... LL | impl Trait for isize {} | ^^^^^^^^^^^^^^^^^^^^ missing `Type` in implementation diff --git a/src/test/ui/associated-types/associated-types-path-1.stderr b/src/test/ui/associated-types/associated-types-path-1.stderr index 6512d60b2c2..a67f77e37c7 100644 --- a/src/test/ui/associated-types/associated-types-path-1.stderr +++ b/src/test/ui/associated-types/associated-types-path-1.stderr @@ -8,10 +8,10 @@ error[E0221]: ambiguous associated type `A` in bounds of `T` --> $DIR/associated-types-path-1.rs:11:34 | LL | type A; - | ------- ambiguous `A` from `Foo` + | ------ ambiguous `A` from `Foo` ... LL | type A; - | ------- ambiguous `A` from `Bar` + | ------ ambiguous `A` from `Bar` ... LL | pub fn f2<T: Foo + Bar>(a: T, x: T::A) {} | ^^^^ ambiguous associated type `A` diff --git a/src/test/ui/associated-types/defaults-mixed.stderr b/src/test/ui/associated-types/defaults-mixed.stderr index 69ddd5f2326..0f4a6968c70 100644 --- a/src/test/ui/associated-types/defaults-mixed.stderr +++ b/src/test/ui/associated-types/defaults-mixed.stderr @@ -2,7 +2,7 @@ error[E0046]: not all trait items implemented, missing: `Bar` --> $DIR/defaults-mixed.rs:11:1 | LL | type Bar; - | --------- `Bar` from trait + | -------- `Bar` from trait ... LL | impl Trait for () {} | ^^^^^^^^^^^^^^^^^ missing `Bar` in implementation @@ -11,7 +11,7 @@ error[E0046]: not all trait items implemented, missing: `Bar` --> $DIR/defaults-mixed.rs:14:1 | LL | type Bar; - | --------- `Bar` from trait + | -------- `Bar` from trait ... LL | impl Trait for bool { | ^^^^^^^^^^^^^^^^^^^ missing `Bar` in implementation 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 1d3b7097da6..e007f5a163b 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 @@ -1,13 +1,8 @@ error[E0275]: overflow evaluating the requirement `for<'b> u32: X<'b>` --> $DIR/hr-associated-type-bound-2.rs:11:1 | -LL | / impl X<'_> for u32 -LL | | where -LL | | for<'b> <Self as X<'b>>::U: Clone, -LL | | { -LL | | type U = str; -LL | | } - | |_^ +LL | impl X<'_> for u32 + | ^^^^^^^^^^^^^^^^^^ | = 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` 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 6f60128b8ef..939c9bbdb6b 100644 --- a/src/test/ui/associated-types/impl-wf-cycle-1.stderr +++ b/src/test/ui/associated-types/impl-wf-cycle-1.stderr @@ -1,14 +1,8 @@ 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 | | type B = bool; -LL | | } - | |_^ +LL | impl<T: Grault> Grault for (T,) + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ | note: required because of the requirements on the impl of `Grault` for `(T,)` --> $DIR/impl-wf-cycle-1.rs:15:17 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 ba14ffefae5..d02ed2cacdf 100644 --- a/src/test/ui/associated-types/impl-wf-cycle-2.stderr +++ b/src/test/ui/associated-types/impl-wf-cycle-2.stderr @@ -1,14 +1,8 @@ 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 | impl<T: Grault> Grault for (T,) + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ | note: required because of the requirements on the impl of `Grault` for `(T,)` --> $DIR/impl-wf-cycle-2.rs:7:17 diff --git a/src/test/ui/associated-types/issue-22560.stderr b/src/test/ui/associated-types/issue-22560.stderr index 71655d54baa..700923c1b3f 100644 --- a/src/test/ui/associated-types/issue-22560.stderr +++ b/src/test/ui/associated-types/issue-22560.stderr @@ -1,26 +1,22 @@ error[E0393]: the type parameter `Rhs` must be explicitly specified --> $DIR/issue-22560.rs:9:23 | -LL | / trait Sub<Rhs=Self> { -LL | | type Output; -LL | | } - | |_- type parameter `Rhs` must be specified for this -LL | -LL | type Test = dyn Add + Sub; - | ^^^ help: set the type parameter to the desired type: `Sub<Rhs>` +LL | trait Sub<Rhs=Self> { + | ------------------- type parameter `Rhs` must be specified for this +... +LL | type Test = dyn Add + Sub; + | ^^^ help: set the type parameter to the desired type: `Sub<Rhs>` | = note: because of the default `Self` reference, type parameters must be specified on object types error[E0393]: the type parameter `Rhs` must be explicitly specified --> $DIR/issue-22560.rs:9:17 | -LL | / trait Add<Rhs=Self> { -LL | | type Output; -LL | | } - | |_- type parameter `Rhs` must be specified for this +LL | trait Add<Rhs=Self> { + | ------------------- type parameter `Rhs` must be specified for this ... -LL | type Test = dyn Add + Sub; - | ^^^ help: set the type parameter to the desired type: `Add<Rhs>` +LL | type Test = dyn Add + Sub; + | ^^^ help: set the type parameter to the desired type: `Add<Rhs>` | = note: because of the default `Self` reference, type parameters must be specified on object types @@ -39,10 +35,10 @@ error[E0191]: the value of the associated types `Output` (from trait `Add`), `Ou --> $DIR/issue-22560.rs:9:17 | LL | type Output; - | ------------ `Output` defined here + | ----------- `Output` defined here ... LL | type Output; - | ------------ `Output` defined here + | ----------- `Output` defined here ... LL | type Test = dyn Add + Sub; | ^^^ ^^^ associated type `Output` must be specified diff --git a/src/test/ui/associated-types/issue-23595-1.stderr b/src/test/ui/associated-types/issue-23595-1.stderr index bb455684ee3..4307477a56a 100644 --- a/src/test/ui/associated-types/issue-23595-1.stderr +++ b/src/test/ui/associated-types/issue-23595-1.stderr @@ -2,14 +2,11 @@ error[E0191]: the value of the associated types `ChildKey` (from trait `Hierarch --> $DIR/issue-23595-1.rs:8:58 | LL | type Value; - | ----------- `Value` defined here + | ---------- `Value` defined here LL | type ChildKey; - | -------------- `ChildKey` defined here + | ------------- `ChildKey` defined here LL | type Children = dyn Index<Self::ChildKey, Output=dyn Hierarchy>; - | -----------------------------------------------------^^^^^^^^^-- - | | | - | | help: specify the associated types: `Hierarchy<Value = Type, ChildKey = Type, Children = Type>` - | `Children` defined here + | ------------- `Children` defined here ^^^^^^^^^ help: specify the associated types: `Hierarchy<Value = Type, ChildKey = Type, Children = Type>` error: aborting due to previous error diff --git a/src/test/ui/associated-types/issue-59324.stderr b/src/test/ui/associated-types/issue-59324.stderr index 5cd781d9a0c..a84b599b52b 100644 --- a/src/test/ui/associated-types/issue-59324.stderr +++ b/src/test/ui/associated-types/issue-59324.stderr @@ -5,10 +5,7 @@ LL | / pub trait ThriftService<Bug: NotFoo>: LL | | LL | | LL | | Service<AssocType = <Bug as Foo>::OnlyFoo> -... | -LL | | -LL | | } - | |_^ the trait `Foo` is not implemented for `Bug` + | |______________________________________________^ the trait `Foo` is not implemented for `Bug` | help: consider further restricting this bound | diff --git a/src/test/ui/associated-types/issue-85103.stderr b/src/test/ui/associated-types/issue-85103.stderr index 142f3c411ec..bddd1dce8e6 100644 --- a/src/test/ui/associated-types/issue-85103.stderr +++ b/src/test/ui/associated-types/issue-85103.stderr @@ -2,7 +2,7 @@ error: layout error: NormalizationFailure(<[E] as std::borrow::ToOwned>::Owned, --> $DIR/issue-85103.rs:6:1 | LL | type Edges<'a, E> = Cow<'a, [E]>; - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | ^^^^^^^^^^^^^^^^^ error: aborting due to previous error diff --git a/src/test/ui/associated-types/missing-associated-types.stderr b/src/test/ui/associated-types/missing-associated-types.stderr index 8c52736b02c..f617df984ae 100644 --- a/src/test/ui/associated-types/missing-associated-types.stderr +++ b/src/test/ui/associated-types/missing-associated-types.stderr @@ -13,7 +13,7 @@ error[E0191]: the value of the associated types `A` (from trait `Y`), `Output` ( --> $DIR/missing-associated-types.rs:12:21 | LL | type A; - | ------- `A` defined here + | ------ `A` defined here ... LL | type Foo<Rhs> = dyn Add<Rhs> + Sub<Rhs> + X<Rhs> + Y<Rhs>; | ^^^^^^^^ ^^^^^^^^ ^^^^^^ ^^^^^^ associated type `A` must be specified @@ -42,9 +42,9 @@ error[E0191]: the value of the associated types `A` (from trait `Z`), `B` (from --> $DIR/missing-associated-types.rs:15:21 | LL | type A; - | ------- `A` defined here + | ------ `A` defined here LL | type B; - | ------- `B` defined here + | ------ `B` defined here ... LL | type Bar<Rhs> = dyn Add<Rhs> + Sub<Rhs> + X<Rhs> + Z<Rhs>; | ^^^^^^^^ ^^^^^^^^ ^^^^^^ ^^^^^^ associated types `A`, `B`, `Output` must be specified @@ -78,7 +78,7 @@ error[E0191]: the value of the associated types `A` (from trait `Y`), `Output` ( --> $DIR/missing-associated-types.rs:18:21 | LL | type A; - | ------- `A` defined here + | ------ `A` defined here ... LL | type Baz<Rhs> = dyn Add<Rhs> + Sub<Rhs> + Y<Rhs>; | ^^^^^^^^ ^^^^^^^^ ^^^^^^ associated type `A` must be specified diff --git a/src/test/ui/auto-traits/suspicious-impls-lint.stderr b/src/test/ui/auto-traits/suspicious-impls-lint.stderr index 03460b28dcd..97b2d7221fd 100644 --- a/src/test/ui/auto-traits/suspicious-impls-lint.stderr +++ b/src/test/ui/auto-traits/suspicious-impls-lint.stderr @@ -2,7 +2,7 @@ error: cross-crate traits with a default impl, like `Send`, should not be specia --> $DIR/suspicious-impls-lint.rs:9:1 | LL | unsafe impl<T: Send> Send for MayImplementSendErr<&T> {} - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ | note: the lint level is defined here --> $DIR/suspicious-impls-lint.rs:1:9 @@ -16,13 +16,13 @@ note: try using the same sequence of generic parameters as the struct definition --> $DIR/suspicious-impls-lint.rs:8:1 | LL | struct MayImplementSendErr<T>(T); - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ error: cross-crate traits with a default impl, like `Send`, should not be specialized --> $DIR/suspicious-impls-lint.rs:21:1 | LL | unsafe impl Send for ContainsVec<i32> {} - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ | = warning: this will change its meaning in a future release! = note: for more information, see issue #93367 <https://github.com/rust-lang/rust/issues/93367> @@ -31,13 +31,13 @@ note: try using the same sequence of generic parameters as the struct definition --> $DIR/suspicious-impls-lint.rs:20:1 | LL | struct ContainsVec<T>(Vec<T>); - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | ^^^^^^^^^^^^^^^^^^^^^ error: cross-crate traits with a default impl, like `Send`, should not be specialized --> $DIR/suspicious-impls-lint.rs:32:1 | LL | unsafe impl<T: Send> Send for TwoParamsSame<T, T> {} - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ | = warning: this will change its meaning in a future release! = note: for more information, see issue #93367 <https://github.com/rust-lang/rust/issues/93367> @@ -46,13 +46,13 @@ note: try using the same sequence of generic parameters as the struct definition --> $DIR/suspicious-impls-lint.rs:31:1 | LL | struct TwoParamsSame<T, U>(T, U); - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | ^^^^^^^^^^^^^^^^^^^^^^^^^^ error: cross-crate traits with a default impl, like `Send`, should not be specialized --> $DIR/suspicious-impls-lint.rs:40:1 | LL | unsafe impl<T> Send for WithPhantomDataSend<*const T, i8> {} - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ | = warning: this will change its meaning in a future release! = note: for more information, see issue #93367 <https://github.com/rust-lang/rust/issues/93367> @@ -61,13 +61,13 @@ note: try using the same sequence of generic parameters as the struct definition --> $DIR/suspicious-impls-lint.rs:39:1 | LL | pub struct WithPhantomDataSend<T, U>(PhantomData<T>, U); - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ error: cross-crate traits with a default impl, like `Sync`, should not be specialized --> $DIR/suspicious-impls-lint.rs:46:1 | LL | unsafe impl<T> Sync for WithLifetime<'static, Vec<T>> {} - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ | = warning: this will change its meaning in a future release! = note: for more information, see issue #93367 <https://github.com/rust-lang/rust/issues/93367> @@ -76,7 +76,7 @@ note: try using the same sequence of generic parameters as the struct definition --> $DIR/suspicious-impls-lint.rs:44:1 | LL | pub struct WithLifetime<'a, T>(&'a (), T); - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ error: aborting due to 5 previous errors diff --git a/src/test/ui/binop/issue-28837.stderr b/src/test/ui/binop/issue-28837.stderr index 1875ea06a06..b9c7e1bea70 100644 --- a/src/test/ui/binop/issue-28837.stderr +++ b/src/test/ui/binop/issue-28837.stderr @@ -10,18 +10,12 @@ note: an implementation of `Add<_>` might be missing for `A` --> $DIR/issue-28837.rs:1:1 | LL | struct A; - | ^^^^^^^^^ must implement `Add<_>` + | ^^^^^^^^ must implement `Add<_>` note: the following trait must be implemented --> $SRC_DIR/core/src/ops/arith.rs:LL:COL | -LL | / pub trait Add<Rhs = Self> { -LL | | /// The resulting type after applying the `+` operator. -LL | | #[stable(feature = "rust1", since = "1.0.0")] -LL | | type Output; -... | -LL | | fn add(self, rhs: Rhs) -> Self::Output; -LL | | } - | |_^ +LL | pub trait Add<Rhs = Self> { + | ^^^^^^^^^^^^^^^^^^^^^^^^^ error[E0369]: cannot subtract `A` from `A` --> $DIR/issue-28837.rs:8:7 @@ -35,18 +29,12 @@ note: an implementation of `Sub<_>` might be missing for `A` --> $DIR/issue-28837.rs:1:1 | LL | struct A; - | ^^^^^^^^^ must implement `Sub<_>` + | ^^^^^^^^ must implement `Sub<_>` note: the following trait must be implemented --> $SRC_DIR/core/src/ops/arith.rs:LL:COL | -LL | / pub trait Sub<Rhs = Self> { -LL | | /// The resulting type after applying the `-` operator. -LL | | #[stable(feature = "rust1", since = "1.0.0")] -LL | | type Output; -... | -LL | | fn sub(self, rhs: Rhs) -> Self::Output; -LL | | } - | |_^ +LL | pub trait Sub<Rhs = Self> { + | ^^^^^^^^^^^^^^^^^^^^^^^^^ error[E0369]: cannot multiply `A` by `A` --> $DIR/issue-28837.rs:10:7 @@ -60,18 +48,12 @@ note: an implementation of `Mul<_>` might be missing for `A` --> $DIR/issue-28837.rs:1:1 | LL | struct A; - | ^^^^^^^^^ must implement `Mul<_>` + | ^^^^^^^^ must implement `Mul<_>` note: the following trait must be implemented --> $SRC_DIR/core/src/ops/arith.rs:LL:COL | -LL | / pub trait Mul<Rhs = Self> { -LL | | /// The resulting type after applying the `*` operator. -LL | | #[stable(feature = "rust1", since = "1.0.0")] -LL | | type Output; -... | -LL | | fn mul(self, rhs: Rhs) -> Self::Output; -LL | | } - | |_^ +LL | pub trait Mul<Rhs = Self> { + | ^^^^^^^^^^^^^^^^^^^^^^^^^ error[E0369]: cannot divide `A` by `A` --> $DIR/issue-28837.rs:12:7 @@ -85,18 +67,12 @@ note: an implementation of `Div<_>` might be missing for `A` --> $DIR/issue-28837.rs:1:1 | LL | struct A; - | ^^^^^^^^^ must implement `Div<_>` + | ^^^^^^^^ must implement `Div<_>` note: the following trait must be implemented --> $SRC_DIR/core/src/ops/arith.rs:LL:COL | -LL | / pub trait Div<Rhs = Self> { -LL | | /// The resulting type after applying the `/` operator. -LL | | #[stable(feature = "rust1", since = "1.0.0")] -LL | | type Output; -... | -LL | | fn div(self, rhs: Rhs) -> Self::Output; -LL | | } - | |_^ +LL | pub trait Div<Rhs = Self> { + | ^^^^^^^^^^^^^^^^^^^^^^^^^ error[E0369]: cannot mod `A` by `A` --> $DIR/issue-28837.rs:14:7 @@ -110,18 +86,12 @@ note: an implementation of `Rem<_>` might be missing for `A` --> $DIR/issue-28837.rs:1:1 | LL | struct A; - | ^^^^^^^^^ must implement `Rem<_>` + | ^^^^^^^^ must implement `Rem<_>` note: the following trait must be implemented --> $SRC_DIR/core/src/ops/arith.rs:LL:COL | -LL | / pub trait Rem<Rhs = Self> { -LL | | /// The resulting type after applying the `%` operator. -LL | | #[stable(feature = "rust1", since = "1.0.0")] -LL | | type Output; -... | -LL | | fn rem(self, rhs: Rhs) -> Self::Output; -LL | | } - | |_^ +LL | pub trait Rem<Rhs = Self> { + | ^^^^^^^^^^^^^^^^^^^^^^^^^ error[E0369]: no implementation for `A & A` --> $DIR/issue-28837.rs:16:7 @@ -135,18 +105,12 @@ note: an implementation of `BitAnd<_>` might be missing for `A` --> $DIR/issue-28837.rs:1:1 | LL | struct A; - | ^^^^^^^^^ must implement `BitAnd<_>` + | ^^^^^^^^ must implement `BitAnd<_>` note: the following trait must be implemented --> $SRC_DIR/core/src/ops/bit.rs:LL:COL | -LL | / pub trait BitAnd<Rhs = Self> { -LL | | /// The resulting type after applying the `&` operator. -LL | | #[stable(feature = "rust1", since = "1.0.0")] -LL | | type Output; -... | -LL | | fn bitand(self, rhs: Rhs) -> Self::Output; -LL | | } - | |_^ +LL | pub trait BitAnd<Rhs = Self> { + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ error[E0369]: no implementation for `A | A` --> $DIR/issue-28837.rs:18:7 @@ -160,18 +124,12 @@ note: an implementation of `BitOr<_>` might be missing for `A` --> $DIR/issue-28837.rs:1:1 | LL | struct A; - | ^^^^^^^^^ must implement `BitOr<_>` + | ^^^^^^^^ must implement `BitOr<_>` note: the following trait must be implemented --> $SRC_DIR/core/src/ops/bit.rs:LL:COL | -LL | / pub trait BitOr<Rhs = Self> { -LL | | /// The resulting type after applying the `|` operator. -LL | | #[stable(feature = "rust1", since = "1.0.0")] -LL | | type Output; -... | -LL | | fn bitor(self, rhs: Rhs) -> Self::Output; -LL | | } - | |_^ +LL | pub trait BitOr<Rhs = Self> { + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^ error[E0369]: no implementation for `A << A` --> $DIR/issue-28837.rs:20:7 @@ -185,18 +143,12 @@ note: an implementation of `Shl<_>` might be missing for `A` --> $DIR/issue-28837.rs:1:1 | LL | struct A; - | ^^^^^^^^^ must implement `Shl<_>` + | ^^^^^^^^ must implement `Shl<_>` note: the following trait must be implemented --> $SRC_DIR/core/src/ops/bit.rs:LL:COL | -LL | / pub trait Shl<Rhs = Self> { -LL | | /// The resulting type after applying the `<<` operator. -LL | | #[stable(feature = "rust1", since = "1.0.0")] -LL | | type Output; -... | -LL | | fn shl(self, rhs: Rhs) -> Self::Output; -LL | | } - | |_^ +LL | pub trait Shl<Rhs = Self> { + | ^^^^^^^^^^^^^^^^^^^^^^^^^ error[E0369]: no implementation for `A >> A` --> $DIR/issue-28837.rs:22:7 @@ -210,18 +162,12 @@ note: an implementation of `Shr<_>` might be missing for `A` --> $DIR/issue-28837.rs:1:1 | LL | struct A; - | ^^^^^^^^^ must implement `Shr<_>` + | ^^^^^^^^ must implement `Shr<_>` note: the following trait must be implemented --> $SRC_DIR/core/src/ops/bit.rs:LL:COL | -LL | / pub trait Shr<Rhs = Self> { -LL | | /// The resulting type after applying the `>>` operator. -LL | | #[stable(feature = "rust1", since = "1.0.0")] -LL | | type Output; -... | -LL | | fn shr(self, rhs: Rhs) -> Self::Output; -LL | | } - | |_^ +LL | pub trait Shr<Rhs = Self> { + | ^^^^^^^^^^^^^^^^^^^^^^^^^ error[E0369]: binary operation `==` cannot be applied to type `A` --> $DIR/issue-28837.rs:24:7 @@ -235,7 +181,7 @@ note: an implementation of `PartialEq<_>` might be missing for `A` --> $DIR/issue-28837.rs:1:1 | LL | struct A; - | ^^^^^^^^^ must implement `PartialEq<_>` + | ^^^^^^^^ must implement `PartialEq<_>` help: consider annotating `A` with `#[derive(PartialEq)]` | LL | #[derive(PartialEq)] @@ -253,7 +199,7 @@ note: an implementation of `PartialEq<_>` might be missing for `A` --> $DIR/issue-28837.rs:1:1 | LL | struct A; - | ^^^^^^^^^ must implement `PartialEq<_>` + | ^^^^^^^^ must implement `PartialEq<_>` help: consider annotating `A` with `#[derive(PartialEq)]` | LL | #[derive(PartialEq)] @@ -271,7 +217,7 @@ note: an implementation of `PartialOrd<_>` might be missing for `A` --> $DIR/issue-28837.rs:1:1 | LL | struct A; - | ^^^^^^^^^ must implement `PartialOrd<_>` + | ^^^^^^^^ must implement `PartialOrd<_>` help: consider annotating `A` with `#[derive(PartialEq, PartialOrd)]` | LL | #[derive(PartialEq, PartialOrd)] @@ -289,7 +235,7 @@ note: an implementation of `PartialOrd<_>` might be missing for `A` --> $DIR/issue-28837.rs:1:1 | LL | struct A; - | ^^^^^^^^^ must implement `PartialOrd<_>` + | ^^^^^^^^ must implement `PartialOrd<_>` help: consider annotating `A` with `#[derive(PartialEq, PartialOrd)]` | LL | #[derive(PartialEq, PartialOrd)] @@ -307,7 +253,7 @@ note: an implementation of `PartialOrd<_>` might be missing for `A` --> $DIR/issue-28837.rs:1:1 | LL | struct A; - | ^^^^^^^^^ must implement `PartialOrd<_>` + | ^^^^^^^^ must implement `PartialOrd<_>` help: consider annotating `A` with `#[derive(PartialEq, PartialOrd)]` | LL | #[derive(PartialEq, PartialOrd)] @@ -325,7 +271,7 @@ note: an implementation of `PartialOrd<_>` might be missing for `A` --> $DIR/issue-28837.rs:1:1 | LL | struct A; - | ^^^^^^^^^ must implement `PartialOrd<_>` + | ^^^^^^^^ must implement `PartialOrd<_>` help: consider annotating `A` with `#[derive(PartialEq, PartialOrd)]` | LL | #[derive(PartialEq, PartialOrd)] diff --git a/src/test/ui/binop/issue-3820.stderr b/src/test/ui/binop/issue-3820.stderr index d5c24e1bb6c..f21f8906911 100644 --- a/src/test/ui/binop/issue-3820.stderr +++ b/src/test/ui/binop/issue-3820.stderr @@ -14,14 +14,8 @@ LL | struct Thing { note: the following trait must be implemented --> $SRC_DIR/core/src/ops/arith.rs:LL:COL | -LL | / pub trait Mul<Rhs = Self> { -LL | | /// The resulting type after applying the `*` operator. -LL | | #[stable(feature = "rust1", since = "1.0.0")] -LL | | type Output; -... | -LL | | fn mul(self, rhs: Rhs) -> Self::Output; -LL | | } - | |_^ +LL | pub trait Mul<Rhs = Self> { + | ^^^^^^^^^^^^^^^^^^^^^^^^^ error: aborting due to previous error diff --git a/src/test/ui/blind/blind-item-block-middle.stderr b/src/test/ui/blind/blind-item-block-middle.stderr index dd83f6edf62..eb64fea9433 100644 --- a/src/test/ui/blind/blind-item-block-middle.stderr +++ b/src/test/ui/blind/blind-item-block-middle.stderr @@ -2,7 +2,7 @@ error[E0308]: mismatched types --> $DIR/blind-item-block-middle.rs:6:9 | LL | mod foo { pub struct bar; } - | --------------- unit struct defined here + | -------------- unit struct defined here ... LL | let bar = 5; | ^^^ - this expression has type `{integer}` diff --git a/src/test/ui/borrowck/issue-81365-1.stderr b/src/test/ui/borrowck/issue-81365-1.stderr index ef88d7f14a3..d79394834dc 100644 --- a/src/test/ui/borrowck/issue-81365-1.stderr +++ b/src/test/ui/borrowck/issue-81365-1.stderr @@ -13,7 +13,7 @@ note: deref defined here --> $DIR/issue-81365-1.rs:12:5 | LL | type Target = DerefTarget; - | ^^^^^^^^^^^^^^^^^^^^^^^^^^ + | ^^^^^^^^^^^ error: aborting due to previous error diff --git a/src/test/ui/borrowck/issue-81365-2.stderr b/src/test/ui/borrowck/issue-81365-2.stderr index e71edb50964..764eaaa7cc7 100644 --- a/src/test/ui/borrowck/issue-81365-2.stderr +++ b/src/test/ui/borrowck/issue-81365-2.stderr @@ -13,7 +13,7 @@ note: deref defined here --> $DIR/issue-81365-2.rs:12:5 | LL | type Target = DerefTarget; - | ^^^^^^^^^^^^^^^^^^^^^^^^^^ + | ^^^^^^^^^^^ error: aborting due to previous error diff --git a/src/test/ui/borrowck/issue-81365-3.stderr b/src/test/ui/borrowck/issue-81365-3.stderr index 70bb6bb93a9..9447174fd21 100644 --- a/src/test/ui/borrowck/issue-81365-3.stderr +++ b/src/test/ui/borrowck/issue-81365-3.stderr @@ -13,7 +13,7 @@ note: deref defined here --> $DIR/issue-81365-3.rs:23:5 | LL | type Target = Container; - | ^^^^^^^^^^^^^^^^^^^^^^^^ + | ^^^^^^^^^^^ error: aborting due to previous error diff --git a/src/test/ui/borrowck/issue-81365-4.stderr b/src/test/ui/borrowck/issue-81365-4.stderr index e714bb86d1c..0ab3fa92706 100644 --- a/src/test/ui/borrowck/issue-81365-4.stderr +++ b/src/test/ui/borrowck/issue-81365-4.stderr @@ -13,7 +13,7 @@ note: deref defined here --> $DIR/issue-81365-4.rs:24:5 | LL | type Target = Container; - | ^^^^^^^^^^^^^^^^^^^^^^^^ + | ^^^^^^^^^^^ error: aborting due to previous error diff --git a/src/test/ui/borrowck/issue-81365-5.stderr b/src/test/ui/borrowck/issue-81365-5.stderr index 8201894c6db..20ff229ffe7 100644 --- a/src/test/ui/borrowck/issue-81365-5.stderr +++ b/src/test/ui/borrowck/issue-81365-5.stderr @@ -13,7 +13,7 @@ note: deref defined here --> $DIR/issue-81365-5.rs:19:5 | LL | type Target = DerefTarget; - | ^^^^^^^^^^^^^^^^^^^^^^^^^^ + | ^^^^^^^^^^^ error: aborting due to previous error diff --git a/src/test/ui/borrowck/issue-81365-6.stderr b/src/test/ui/borrowck/issue-81365-6.stderr index 85ed6acca3d..575aed73b46 100644 --- a/src/test/ui/borrowck/issue-81365-6.stderr +++ b/src/test/ui/borrowck/issue-81365-6.stderr @@ -13,7 +13,7 @@ note: deref defined here --> $DIR/issue-81365-6.rs:9:5 | LL | type Target = [()]; - | ^^^^^^^^^^^^^^^^^^^ + | ^^^^^^^^^^^ error: aborting due to previous error diff --git a/src/test/ui/borrowck/issue-81365-7.stderr b/src/test/ui/borrowck/issue-81365-7.stderr index 506732ec0c5..52d2d9e75a9 100644 --- a/src/test/ui/borrowck/issue-81365-7.stderr +++ b/src/test/ui/borrowck/issue-81365-7.stderr @@ -13,7 +13,7 @@ note: deref defined here --> $DIR/issue-81365-7.rs:12:5 | LL | type Target = DerefTarget; - | ^^^^^^^^^^^^^^^^^^^^^^^^^^ + | ^^^^^^^^^^^ error: aborting due to previous error diff --git a/src/test/ui/borrowck/issue-81365-8.stderr b/src/test/ui/borrowck/issue-81365-8.stderr index 716b6e9b51f..fd83e10a295 100644 --- a/src/test/ui/borrowck/issue-81365-8.stderr +++ b/src/test/ui/borrowck/issue-81365-8.stderr @@ -13,7 +13,7 @@ note: deref defined here --> $DIR/issue-81365-8.rs:12:5 | LL | type Target = DerefTarget; - | ^^^^^^^^^^^^^^^^^^^^^^^^^^ + | ^^^^^^^^^^^ error: aborting due to previous error diff --git a/src/test/ui/borrowck/issue-81899.stderr b/src/test/ui/borrowck/issue-81899.stderr index e7345ff3f9a..29288be4934 100644 --- a/src/test/ui/borrowck/issue-81899.stderr +++ b/src/test/ui/borrowck/issue-81899.stderr @@ -16,9 +16,7 @@ error: any use of this value will cause an error --> $DIR/issue-81899.rs:4:23 | LL | const _CONST: &[u8] = &f(&[], |_| {}); - | ----------------------^^^^^^^^^^^^^^^- - | | - | referenced constant has errors + | ------------------- ^^^^^^^^^^^^^^^ referenced constant has errors | = note: `#[deny(const_err)]` on by default = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release! @@ -32,9 +30,7 @@ error: any use of this value will cause an error --> $DIR/issue-81899.rs:4:23 | LL | const _CONST: &[u8] = &f(&[], |_| {}); - | ----------------------^^^^^^^^^^^^^^^- - | | - | referenced constant has errors + | ------------------- ^^^^^^^^^^^^^^^ referenced constant has errors | = note: `#[deny(const_err)]` on by default = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release! diff --git a/src/test/ui/borrowck/issue-88434-minimal-example.stderr b/src/test/ui/borrowck/issue-88434-minimal-example.stderr index 47d83c65355..daded200bd9 100644 --- a/src/test/ui/borrowck/issue-88434-minimal-example.stderr +++ b/src/test/ui/borrowck/issue-88434-minimal-example.stderr @@ -16,9 +16,7 @@ error: any use of this value will cause an error --> $DIR/issue-88434-minimal-example.rs:3:21 | LL | const _CONST: &() = &f(&|_| {}); - | --------------------^^^^^^^^^^^- - | | - | referenced constant has errors + | ----------------- ^^^^^^^^^^^ referenced constant has errors | = note: `#[deny(const_err)]` on by default = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release! @@ -32,9 +30,7 @@ error: any use of this value will cause an error --> $DIR/issue-88434-minimal-example.rs:3:21 | LL | const _CONST: &() = &f(&|_| {}); - | --------------------^^^^^^^^^^^- - | | - | referenced constant has errors + | ----------------- ^^^^^^^^^^^ referenced constant has errors | = note: `#[deny(const_err)]` on by default = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release! diff --git a/src/test/ui/borrowck/issue-88434-removal-index-should-be-less.stderr b/src/test/ui/borrowck/issue-88434-removal-index-should-be-less.stderr index b08a7cfc7fe..ce6a37ee418 100644 --- a/src/test/ui/borrowck/issue-88434-removal-index-should-be-less.stderr +++ b/src/test/ui/borrowck/issue-88434-removal-index-should-be-less.stderr @@ -16,9 +16,7 @@ error: any use of this value will cause an error --> $DIR/issue-88434-removal-index-should-be-less.rs:3:23 | LL | const _CONST: &[u8] = &f(&[], |_| {}); - | ----------------------^^^^^^^^^^^^^^^- - | | - | referenced constant has errors + | ------------------- ^^^^^^^^^^^^^^^ referenced constant has errors | = note: `#[deny(const_err)]` on by default = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release! @@ -32,9 +30,7 @@ error: any use of this value will cause an error --> $DIR/issue-88434-removal-index-should-be-less.rs:3:23 | LL | const _CONST: &[u8] = &f(&[], |_| {}); - | ----------------------^^^^^^^^^^^^^^^- - | | - | referenced constant has errors + | ------------------- ^^^^^^^^^^^^^^^ referenced constant has errors | = note: `#[deny(const_err)]` on by default = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release! diff --git a/src/test/ui/cast/issue-85586.stderr b/src/test/ui/cast/issue-85586.stderr index 271885a133a..ed8a6fc62e9 100644 --- a/src/test/ui/cast/issue-85586.stderr +++ b/src/test/ui/cast/issue-85586.stderr @@ -3,8 +3,6 @@ error[E0282]: type annotations needed | LL | let b = (a + 1) as usize; | ^^^^^^^ cannot infer type - | - = note: type must be known at this point error: aborting due to previous error diff --git a/src/test/ui/closures/2229_closure_analysis/issue-87987.stderr b/src/test/ui/closures/2229_closure_analysis/issue-87987.stderr index 57b8f7ae609..5696a010c3f 100644 --- a/src/test/ui/closures/2229_closure_analysis/issue-87987.stderr +++ b/src/test/ui/closures/2229_closure_analysis/issue-87987.stderr @@ -4,9 +4,9 @@ warning: fields `field_1` and `field_2` are never read LL | struct Props { | ----- fields in this struct LL | field_1: u32, - | ^^^^^^^^^^^^ + | ^^^^^^^ LL | field_2: u32, - | ^^^^^^^^^^^^ + | ^^^^^^^ | = note: `#[warn(dead_code)]` on by default diff --git a/src/test/ui/closures/2229_closure_analysis/match/non-exhaustive-match.stderr b/src/test/ui/closures/2229_closure_analysis/match/non-exhaustive-match.stderr index 32d36274ff6..e0678bc718f 100644 --- a/src/test/ui/closures/2229_closure_analysis/match/non-exhaustive-match.stderr +++ b/src/test/ui/closures/2229_closure_analysis/match/non-exhaustive-match.stderr @@ -25,7 +25,7 @@ note: `E1` defined here --> $DIR/auxiliary/match_non_exhaustive_lib.rs:2:1 | LL | pub enum E1 {} - | ^^^^^^^^^^^^^^ + | ^^^^^^^^^^^ = note: the matched value is of type `E1`, which is marked as non-exhaustive help: ensure that all possible cases are being handled by adding a match arm with a wildcard pattern as shown | @@ -44,7 +44,7 @@ note: `E2` defined here --> $DIR/auxiliary/match_non_exhaustive_lib.rs:5:1 | LL | pub enum E2 { A, B } - | ^^^^^^^^^^^^^^^^^^^^ + | ^^^^^^^^^^^ = note: the matched value is of type `E2`, which is marked as non-exhaustive help: ensure that all possible cases are being handled by adding a match arm with a wildcard pattern or an explicit pattern as shown | diff --git a/src/test/ui/coherence/coherence-overlap-downstream.stderr b/src/test/ui/coherence/coherence-overlap-downstream.stderr index 9ab099489d9..7f373e595a3 100644 --- a/src/test/ui/coherence/coherence-overlap-downstream.stderr +++ b/src/test/ui/coherence/coherence-overlap-downstream.stderr @@ -10,7 +10,7 @@ error[E0119]: conflicting implementations of trait `Foo<_>` for type `i32` --> $DIR/coherence-overlap-downstream.rs:14:1 | LL | impl<X, T> Foo<X> for T where T: Bar<X> {} - | --------------------------------------- first implementation here + | ----------------------- first implementation here LL | impl<X> Foo<X> for i32 {} | ^^^^^^^^^^^^^^^^^^^^^^ conflicting implementation for `i32` | diff --git a/src/test/ui/coherence/coherence-overlap-trait-alias.stderr b/src/test/ui/coherence/coherence-overlap-trait-alias.stderr index 421c86ee51a..e324c1e799f 100644 --- a/src/test/ui/coherence/coherence-overlap-trait-alias.stderr +++ b/src/test/ui/coherence/coherence-overlap-trait-alias.stderr @@ -1,8 +1,8 @@ -error[E0283]: type annotations needed +error[E0283]: type annotations needed: cannot satisfy `u32: C` --> $DIR/coherence-overlap-trait-alias.rs:15:6 | LL | impl C for u32 {} - | ^ cannot infer type for type `u32` + | ^ | note: multiple `impl`s satisfying `u32: C` found --> $DIR/coherence-overlap-trait-alias.rs:14:1 diff --git a/src/test/ui/coherence/coherence-overlap-upstream.stderr b/src/test/ui/coherence/coherence-overlap-upstream.stderr index 8272c887586..f6145c1883a 100644 --- a/src/test/ui/coherence/coherence-overlap-upstream.stderr +++ b/src/test/ui/coherence/coherence-overlap-upstream.stderr @@ -2,7 +2,7 @@ error[E0119]: conflicting implementations of trait `Foo` for type `i16` --> $DIR/coherence-overlap-upstream.rs:13:1 | LL | impl<T> Foo for T where T: Remote {} - | --------------------------------- first implementation here + | ----------------- first implementation here LL | impl Foo for i16 {} | ^^^^^^^^^^^^^^^^ conflicting implementation for `i16` | diff --git a/src/test/ui/coherence/coherence-wasm-bindgen.stderr b/src/test/ui/coherence/coherence-wasm-bindgen.stderr index 432646e5321..aa74e231539 100644 --- a/src/test/ui/coherence/coherence-wasm-bindgen.stderr +++ b/src/test/ui/coherence/coherence-wasm-bindgen.stderr @@ -1,22 +1,11 @@ error: conflicting implementations of trait `IntoWasmAbi` for type `&dyn std::ops::Fn(&_) -> _` --> $DIR/coherence-wasm-bindgen.rs:28:1 | -LL | / impl<'a, 'b, A, R> IntoWasmAbi for &'a (dyn Fn(A) -> R + 'b) -LL | | where -LL | | A: FromWasmAbi, -LL | | R: ReturnWasmAbi, -LL | | { -LL | | } - | |_- first implementation here +LL | impl<'a, 'b, A, R> IntoWasmAbi for &'a (dyn Fn(A) -> R + 'b) + | ------------------------------------------------------------ first implementation here ... -LL | / impl<'a, 'b, A, R> IntoWasmAbi for &'a (dyn for<'x> Fn(&'x A) -> R + 'b) -LL | | where -LL | | A: RefFromWasmAbi, -LL | | R: ReturnWasmAbi, -... | -LL | | -LL | | } - | |_^ conflicting implementation for `&dyn std::ops::Fn(&_) -> _` +LL | impl<'a, 'b, A, R> IntoWasmAbi for &'a (dyn for<'x> Fn(&'x A) -> R + 'b) + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ conflicting implementation for `&dyn std::ops::Fn(&_) -> _` | note: the lint level is defined here --> $DIR/coherence-wasm-bindgen.rs:10:9 diff --git a/src/test/ui/conflicting-repr-hints.stderr b/src/test/ui/conflicting-repr-hints.stderr index 0f32fc0481b..0c7c50d6730 100644 --- a/src/test/ui/conflicting-repr-hints.stderr +++ b/src/test/ui/conflicting-repr-hints.stderr @@ -21,72 +21,61 @@ error[E0587]: type has conflicting packed and align representation hints --> $DIR/conflicting-repr-hints.rs:29:1 | LL | struct F(i32); - | ^^^^^^^^^^^^^^ + | ^^^^^^^^ error[E0587]: type has conflicting packed and align representation hints --> $DIR/conflicting-repr-hints.rs:33:1 | LL | struct G(i32); - | ^^^^^^^^^^^^^^ + | ^^^^^^^^ error[E0587]: type has conflicting packed and align representation hints --> $DIR/conflicting-repr-hints.rs:37:1 | LL | struct H(i32); - | ^^^^^^^^^^^^^^ + | ^^^^^^^^ error[E0634]: type has conflicting packed representation hints --> $DIR/conflicting-repr-hints.rs:40:1 | LL | struct I(i32); - | ^^^^^^^^^^^^^^ + | ^^^^^^^^ error[E0634]: type has conflicting packed representation hints --> $DIR/conflicting-repr-hints.rs:44:1 | LL | struct J(i32); - | ^^^^^^^^^^^^^^ + | ^^^^^^^^ error[E0587]: type has conflicting packed and align representation hints --> $DIR/conflicting-repr-hints.rs:50:1 | -LL | / union X { -LL | | -LL | | i: i32, -LL | | } - | |_^ +LL | union X { + | ^^^^^^^ error[E0587]: type has conflicting packed and align representation hints --> $DIR/conflicting-repr-hints.rs:57:1 | -LL | / union Y { -LL | | -LL | | i: i32, -LL | | } - | |_^ +LL | union Y { + | ^^^^^^^ error[E0587]: type has conflicting packed and align representation hints --> $DIR/conflicting-repr-hints.rs:64:1 | -LL | / union Z { -LL | | -LL | | i: i32, -LL | | } - | |_^ +LL | union Z { + | ^^^^^^^ error[E0587]: type has conflicting packed and align representation hints --> $DIR/conflicting-repr-hints.rs:70:1 | LL | pub struct S(u16); - | ^^^^^^^^^^^^^^^^^^ + | ^^^^^^^^^^^^ error[E0587]: type has conflicting packed and align representation hints --> $DIR/conflicting-repr-hints.rs:73:1 | -LL | / pub union U { -LL | | u: u16 -LL | | } - | |_^ +LL | pub union U { + | ^^^^^^^^^^^ error: aborting due to 12 previous errors diff --git a/src/test/ui/const-generics/generic_arg_infer/issue-91614.stderr b/src/test/ui/const-generics/generic_arg_infer/issue-91614.stderr index 463605e2431..688db695fa8 100644 --- a/src/test/ui/const-generics/generic_arg_infer/issue-91614.stderr +++ b/src/test/ui/const-generics/generic_arg_infer/issue-91614.stderr @@ -2,7 +2,7 @@ error[E0283]: type annotations needed for `Mask<_, LANES>` --> $DIR/issue-91614.rs:6:9 | LL | let y = Mask::<_, _>::splat(false); - | ^ + | ^ ------------------- type must be known at this point | = note: cannot satisfy `_: MaskElement` note: required by a bound in `Mask::<T, LANES>::splat` diff --git a/src/test/ui/const-generics/generic_const_exprs/eval-privacy.stderr b/src/test/ui/const-generics/generic_const_exprs/eval-privacy.stderr index c6b0ce93145..2d9de8805bb 100644 --- a/src/test/ui/const-generics/generic_const_exprs/eval-privacy.stderr +++ b/src/test/ui/const-generics/generic_const_exprs/eval-privacy.stderr @@ -2,7 +2,7 @@ error[E0446]: private type `fn(u8) -> u8 {my_const_fn}` in public interface --> $DIR/eval-privacy.rs:16:5 | LL | type AssocTy = Const<{ my_const_fn(U) }>; - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ can't leak private type + | ^^^^^^^^^^^^ can't leak private type ... LL | const fn my_const_fn(val: u8) -> u8 { | ----------------------------------- `fn(u8) -> u8 {my_const_fn}` declared as private diff --git a/src/test/ui/const-generics/generic_const_exprs/issue-72787.min.stderr b/src/test/ui/const-generics/generic_const_exprs/issue-72787.min.stderr index 02dce4f7a97..41afaec86b6 100644 --- a/src/test/ui/const-generics/generic_const_exprs/issue-72787.min.stderr +++ b/src/test/ui/const-generics/generic_const_exprs/issue-72787.min.stderr @@ -34,19 +34,19 @@ LL | IsLessOrEqual<{ 8 - I }, { 8 - J }>: True, = help: const parameters may only be used as standalone arguments, i.e. `J` = help: use `#![feature(generic_const_exprs)]` to allow generic const expressions -error[E0283]: type annotations needed +error[E0283]: type annotations needed: cannot satisfy `IsLessOrEqual<I, 8_u32>: True` --> $DIR/issue-72787.rs:21:26 | LL | IsLessOrEqual<I, 8>: True, - | ^^^^ cannot infer type for struct `IsLessOrEqual<I, 8_u32>` + | ^^^^ | = note: cannot satisfy `IsLessOrEqual<I, 8_u32>: True` -error[E0283]: type annotations needed +error[E0283]: type annotations needed: cannot satisfy `IsLessOrEqual<I, 8_u32>: True` --> $DIR/issue-72787.rs:21:26 | LL | IsLessOrEqual<I, 8>: True, - | ^^^^ cannot infer type for struct `IsLessOrEqual<I, 8_u32>` + | ^^^^ | = note: cannot satisfy `IsLessOrEqual<I, 8_u32>: True` diff --git a/src/test/ui/const-generics/generic_const_exprs/issue-72787.rs b/src/test/ui/const-generics/generic_const_exprs/issue-72787.rs index 77ad57f0640..c651bf1c8de 100644 --- a/src/test/ui/const-generics/generic_const_exprs/issue-72787.rs +++ b/src/test/ui/const-generics/generic_const_exprs/issue-72787.rs @@ -19,8 +19,8 @@ struct S<const I: u32, const J: u32>; impl<const I: u32, const J: u32> S<I, J> where IsLessOrEqual<I, 8>: True, -//[min]~^ Error type annotations needed [E0283] -//[min]~| Error type annotations needed [E0283] +//[min]~^ Error type annotations needed +//[min]~| Error type annotations needed IsLessOrEqual<J, 8>: True, IsLessOrEqual<{ 8 - I }, { 8 - J }>: True, //[min]~^ Error generic parameters may not be used in const operations diff --git a/src/test/ui/const-generics/generic_const_exprs/issue-97047-ice-1.rs b/src/test/ui/const-generics/generic_const_exprs/issue-97047-ice-1.rs new file mode 100644 index 00000000000..67e30232e2f --- /dev/null +++ b/src/test/ui/const-generics/generic_const_exprs/issue-97047-ice-1.rs @@ -0,0 +1,25 @@ +// check-pass + +#![feature(adt_const_params, generic_const_exprs)] +//~^ WARN the feature `adt_const_params` is incomplete and may not be safe to use and/or cause compiler crashes [incomplete_features] +//~^^ WARN the feature `generic_const_exprs` is incomplete and may not be safe to use and/or cause compiler crashes [incomplete_features] + +pub struct Changes<const CHANGES: &'static [&'static str]> +where + [(); CHANGES.len()]:, +{ + changes: [usize; CHANGES.len()], +} + +impl<const CHANGES: &'static [&'static str]> Changes<CHANGES> +where + [(); CHANGES.len()]:, +{ + pub const fn new() -> Self { + Self { + changes: [0; CHANGES.len()], + } + } +} + +pub fn main() {} diff --git a/src/test/ui/const-generics/generic_const_exprs/issue-97047-ice-1.stderr b/src/test/ui/const-generics/generic_const_exprs/issue-97047-ice-1.stderr new file mode 100644 index 00000000000..b5b2b0e405a --- /dev/null +++ b/src/test/ui/const-generics/generic_const_exprs/issue-97047-ice-1.stderr @@ -0,0 +1,19 @@ +warning: the feature `adt_const_params` is incomplete and may not be safe to use and/or cause compiler crashes + --> $DIR/issue-97047-ice-1.rs:3:12 + | +LL | #![feature(adt_const_params, generic_const_exprs)] + | ^^^^^^^^^^^^^^^^ + | + = note: `#[warn(incomplete_features)]` on by default + = note: see issue #95174 <https://github.com/rust-lang/rust/issues/95174> for more information + +warning: the feature `generic_const_exprs` is incomplete and may not be safe to use and/or cause compiler crashes + --> $DIR/issue-97047-ice-1.rs:3:30 + | +LL | #![feature(adt_const_params, generic_const_exprs)] + | ^^^^^^^^^^^^^^^^^^^ + | + = note: see issue #76560 <https://github.com/rust-lang/rust/issues/76560> for more information + +warning: 2 warnings emitted + diff --git a/src/test/ui/const-generics/generic_const_exprs/issue-97047-ice-2.rs b/src/test/ui/const-generics/generic_const_exprs/issue-97047-ice-2.rs new file mode 100644 index 00000000000..00568a08944 --- /dev/null +++ b/src/test/ui/const-generics/generic_const_exprs/issue-97047-ice-2.rs @@ -0,0 +1,23 @@ +// check-pass + +#![feature(adt_const_params, generic_const_exprs)] +//~^ WARN the feature `adt_const_params` is incomplete and may not be safe to use and/or cause compiler crashes [incomplete_features] +//~^^ WARN the feature `generic_const_exprs` is incomplete and may not be safe to use and/or cause compiler crashes [incomplete_features] + +pub struct Changes<const CHANGES: &'static [&'static str]> +where + [(); CHANGES.len()]:, +{ + changes: [usize; CHANGES.len()], +} + +impl<const CHANGES: &'static [&'static str]> Changes<CHANGES> +where + [(); CHANGES.len()]:, +{ + pub fn combine(&mut self, other: &Self) { + for _change in &self.changes {} + } +} + +pub fn main() {} diff --git a/src/test/ui/const-generics/generic_const_exprs/issue-97047-ice-2.stderr b/src/test/ui/const-generics/generic_const_exprs/issue-97047-ice-2.stderr new file mode 100644 index 00000000000..5dfbd87ccd4 --- /dev/null +++ b/src/test/ui/const-generics/generic_const_exprs/issue-97047-ice-2.stderr @@ -0,0 +1,19 @@ +warning: the feature `adt_const_params` is incomplete and may not be safe to use and/or cause compiler crashes + --> $DIR/issue-97047-ice-2.rs:3:12 + | +LL | #![feature(adt_const_params, generic_const_exprs)] + | ^^^^^^^^^^^^^^^^ + | + = note: `#[warn(incomplete_features)]` on by default + = note: see issue #95174 <https://github.com/rust-lang/rust/issues/95174> for more information + +warning: the feature `generic_const_exprs` is incomplete and may not be safe to use and/or cause compiler crashes + --> $DIR/issue-97047-ice-2.rs:3:30 + | +LL | #![feature(adt_const_params, generic_const_exprs)] + | ^^^^^^^^^^^^^^^^^^^ + | + = note: see issue #76560 <https://github.com/rust-lang/rust/issues/76560> for more information + +warning: 2 warnings emitted + diff --git a/src/test/ui/const-generics/issue-46511.rs b/src/test/ui/const-generics/issue-46511.rs new file mode 100644 index 00000000000..71c50e2f3f7 --- /dev/null +++ b/src/test/ui/const-generics/issue-46511.rs @@ -0,0 +1,8 @@ +// check-fail + +struct Foo<'a> //~ ERROR parameter `'a` is never used [E0392] +{ + _a: [u8; std::mem::size_of::<&'a mut u8>()] //~ ERROR a non-static lifetime is not allowed in a `const` +} + +pub fn main() {} diff --git a/src/test/ui/const-generics/issue-46511.stderr b/src/test/ui/const-generics/issue-46511.stderr new file mode 100644 index 00000000000..b21afa56dcb --- /dev/null +++ b/src/test/ui/const-generics/issue-46511.stderr @@ -0,0 +1,21 @@ +error[E0658]: a non-static lifetime is not allowed in a `const` + --> $DIR/issue-46511.rs:5:35 + | +LL | _a: [u8; std::mem::size_of::<&'a mut u8>()] + | ^^ + | + = note: see issue #76560 <https://github.com/rust-lang/rust/issues/76560> for more information + = help: add `#![feature(generic_const_exprs)]` to the crate attributes to enable + +error[E0392]: parameter `'a` is never used + --> $DIR/issue-46511.rs:3:12 + | +LL | struct Foo<'a> + | ^^ unused parameter + | + = help: consider removing `'a`, referring to it in a field, or using a marker such as `PhantomData` + +error: aborting due to 2 previous errors + +Some errors have detailed explanations: E0392, E0658. +For more information about an error, try `rustc --explain E0392`. diff --git a/src/test/ui/const-generics/issues/issue-83765.stderr b/src/test/ui/const-generics/issues/issue-83765.stderr index 98931a3936f..28ddddf1be6 100644 --- a/src/test/ui/const-generics/issues/issue-83765.stderr +++ b/src/test/ui/const-generics/issues/issue-83765.stderr @@ -2,7 +2,7 @@ error[E0391]: cycle detected when resolving instance `<LazyUpdim<T, { T::DIM }, --> $DIR/issue-83765.rs:5:5 | LL | const DIM: usize; - | ^^^^^^^^^^^^^^^^^ + | ^^^^^^^^^^^^^^^^ | note: ...which requires checking if `TensorDimension` fulfills its obligations... --> $DIR/issue-83765.rs:4:1 diff --git a/src/test/ui/const-ptr/forbidden_slices.32bit.stderr b/src/test/ui/const-ptr/forbidden_slices.32bit.stderr index d29e020339b..c0092ff3be6 100644 --- a/src/test/ui/const-ptr/forbidden_slices.32bit.stderr +++ b/src/test/ui/const-ptr/forbidden_slices.32bit.stderr @@ -4,7 +4,7 @@ error[E0080]: could not evaluate static initializer LL | &*ptr::slice_from_raw_parts(data, len) | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ | | - | dereferencing pointer failed: null pointer is not a valid pointer + | dereferencing pointer failed: null pointer is a dangling pointer (it has no provenance) | inside `std::slice::from_raw_parts::<u32>` at $SRC_DIR/core/src/slice/raw.rs:LL:COL | ::: $DIR/forbidden_slices.rs:19:34 @@ -18,7 +18,7 @@ error[E0080]: could not evaluate static initializer LL | &*ptr::slice_from_raw_parts(data, len) | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ | | - | dereferencing pointer failed: null pointer is not a valid pointer + | dereferencing pointer failed: null pointer is a dangling pointer (it has no provenance) | inside `std::slice::from_raw_parts::<()>` at $SRC_DIR/core/src/slice/raw.rs:LL:COL | ::: $DIR/forbidden_slices.rs:20:33 @@ -44,7 +44,7 @@ error[E0080]: it is undefined behavior to use this value --> $DIR/forbidden_slices.rs:26:1 | LL | pub static S4: &[u8] = unsafe { from_raw_parts((&D1) as *const _ as _, 1) }; - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ constructing invalid value at .<deref>[0]: encountered uninitialized bytes + | ^^^^^^^^^^^^^^^^^^^^ constructing invalid value at .<deref>[0]: encountered uninitialized bytes | = note: The rules on what exactly is undefined behavior aren't clear, so this check might be overzealous. Please open an issue on the rustc repository if you believe it should not be considered undefined behavior. = note: the raw bytes of the constant (size: 8, align: 4) { @@ -55,7 +55,7 @@ error[E0080]: it is undefined behavior to use this value --> $DIR/forbidden_slices.rs:28:1 | LL | pub static S5: &[u8] = unsafe { from_raw_parts((&D3) as *const _ as _, size_of::<&u32>()) }; - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ constructing invalid value at .<deref>: encountered a pointer, but expected plain (non-pointer) bytes + | ^^^^^^^^^^^^^^^^^^^^ constructing invalid value at .<deref>: encountered a pointer, but expected plain (non-pointer) bytes | = note: The rules on what exactly is undefined behavior aren't clear, so this check might be overzealous. Please open an issue on the rustc repository if you believe it should not be considered undefined behavior. = note: the raw bytes of the constant (size: 8, align: 4) { @@ -66,7 +66,7 @@ error[E0080]: it is undefined behavior to use this value --> $DIR/forbidden_slices.rs:30:1 | LL | pub static S6: &[bool] = unsafe { from_raw_parts((&D0) as *const _ as _, 4) }; - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ constructing invalid value at .<deref>[0]: encountered 0x11, but expected a boolean + | ^^^^^^^^^^^^^^^^^^^^^^ constructing invalid value at .<deref>[0]: encountered 0x11, but expected a boolean | = note: The rules on what exactly is undefined behavior aren't clear, so this check might be overzealous. Please open an issue on the rustc repository if you believe it should not be considered undefined behavior. = note: the raw bytes of the constant (size: 8, align: 4) { @@ -76,13 +76,8 @@ LL | pub static S6: &[bool] = unsafe { from_raw_parts((&D0) as *const _ as _, 4) error[E0080]: it is undefined behavior to use this value --> $DIR/forbidden_slices.rs:33:1 | -LL | / pub static S7: &[u16] = unsafe { -LL | | -LL | | let ptr = (&D2 as *const Struct as *const u16).byte_add(1); -LL | | -LL | | from_raw_parts(ptr, 4) -LL | | }; - | |__^ constructing invalid value: encountered an unaligned reference (required 2 byte alignment but found 1) +LL | pub static S7: &[u16] = unsafe { + | ^^^^^^^^^^^^^^^^^^^^^ constructing invalid value: encountered an unaligned reference (required 2 byte alignment but found 1) | = note: The rules on what exactly is undefined behavior aren't clear, so this check might be overzealous. Please open an issue on the rustc repository if you believe it should not be considered undefined behavior. = note: the raw bytes of the constant (size: 8, align: 4) { @@ -109,7 +104,7 @@ error[E0080]: could not evaluate static initializer LL | unsafe { intrinsics::ptr_offset_from_unsigned(self, origin) } | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ | | - | out-of-bounds offset_from: null pointer is not a valid pointer + | out-of-bounds offset_from: null pointer is a dangling pointer (it has no provenance) | inside `ptr::const_ptr::<impl *const u32>::sub_ptr` at $SRC_DIR/core/src/ptr/const_ptr.rs:LL:COL | ::: $SRC_DIR/core/src/slice/raw.rs:LL:COL @@ -149,7 +144,7 @@ error[E0080]: could not evaluate static initializer LL | unsafe { intrinsics::offset(self, count) } | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ | | - | pointer arithmetic failed: ALLOC_ID has size 4, so pointer to 8 bytes starting at offset 0 is out-of-bounds + | out-of-bounds pointer arithmetic: ALLOC_ID has size 4, so pointer to 8 bytes starting at offset 0 is out-of-bounds | inside `ptr::const_ptr::<impl *const u32>::offset` at $SRC_DIR/core/src/ptr/const_ptr.rs:LL:COL ... LL | unsafe { self.offset(count as isize) } @@ -163,12 +158,8 @@ LL | from_ptr_range(ptr..ptr.add(2)) error[E0080]: it is undefined behavior to use this value --> $DIR/forbidden_slices.rs:53:1 | -LL | / pub static R4: &[u8] = unsafe { -LL | | -LL | | let ptr = (&D1) as *const MaybeUninit<&u32> as *const u8; -LL | | from_ptr_range(ptr..ptr.add(1)) -LL | | }; - | |__^ constructing invalid value at .<deref>[0]: encountered uninitialized bytes +LL | pub static R4: &[u8] = unsafe { + | ^^^^^^^^^^^^^^^^^^^^ constructing invalid value at .<deref>[0]: encountered uninitialized bytes | = note: The rules on what exactly is undefined behavior aren't clear, so this check might be overzealous. Please open an issue on the rustc repository if you believe it should not be considered undefined behavior. = note: the raw bytes of the constant (size: 8, align: 4) { @@ -178,12 +169,8 @@ LL | | }; error[E0080]: it is undefined behavior to use this value --> $DIR/forbidden_slices.rs:58:1 | -LL | / pub static R5: &[u8] = unsafe { -LL | | -LL | | let ptr = &D3 as *const &u32; -LL | | from_ptr_range(ptr.cast()..ptr.add(1).cast()) -LL | | }; - | |__^ constructing invalid value at .<deref>: encountered a pointer, but expected plain (non-pointer) bytes +LL | pub static R5: &[u8] = unsafe { + | ^^^^^^^^^^^^^^^^^^^^ constructing invalid value at .<deref>: encountered a pointer, but expected plain (non-pointer) bytes | = note: The rules on what exactly is undefined behavior aren't clear, so this check might be overzealous. Please open an issue on the rustc repository if you believe it should not be considered undefined behavior. = note: the raw bytes of the constant (size: 8, align: 4) { @@ -193,12 +180,8 @@ LL | | }; error[E0080]: it is undefined behavior to use this value --> $DIR/forbidden_slices.rs:63:1 | -LL | / pub static R6: &[bool] = unsafe { -LL | | -LL | | let ptr = &D0 as *const u32 as *const bool; -LL | | from_ptr_range(ptr..ptr.add(4)) -LL | | }; - | |__^ constructing invalid value at .<deref>[0]: encountered 0x11, but expected a boolean +LL | pub static R6: &[bool] = unsafe { + | ^^^^^^^^^^^^^^^^^^^^^^ constructing invalid value at .<deref>[0]: encountered 0x11, but expected a boolean | = note: The rules on what exactly is undefined behavior aren't clear, so this check might be overzealous. Please open an issue on the rustc repository if you believe it should not be considered undefined behavior. = note: the raw bytes of the constant (size: 8, align: 4) { @@ -208,12 +191,8 @@ LL | | }; error[E0080]: it is undefined behavior to use this value --> $DIR/forbidden_slices.rs:68:1 | -LL | / pub static R7: &[u16] = unsafe { -LL | | -LL | | let ptr = (&D2 as *const Struct as *const u16).byte_add(1); -LL | | from_ptr_range(ptr..ptr.add(4)) -LL | | }; - | |__^ constructing invalid value: encountered an unaligned reference (required 2 byte alignment but found 1) +LL | pub static R7: &[u16] = unsafe { + | ^^^^^^^^^^^^^^^^^^^^^ constructing invalid value: encountered an unaligned reference (required 2 byte alignment but found 1) | = note: The rules on what exactly is undefined behavior aren't clear, so this check might be overzealous. Please open an issue on the rustc repository if you believe it should not be considered undefined behavior. = note: the raw bytes of the constant (size: 8, align: 4) { @@ -226,7 +205,7 @@ error[E0080]: could not evaluate static initializer LL | unsafe { intrinsics::offset(self, count) } | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ | | - | pointer arithmetic failed: ALLOC_ID has size 8, so pointer to 8 bytes starting at offset 1 is out-of-bounds + | out-of-bounds pointer arithmetic: ALLOC_ID has size 8, so pointer to 8 bytes starting at offset 1 is out-of-bounds | inside `ptr::const_ptr::<impl *const u64>::offset` at $SRC_DIR/core/src/ptr/const_ptr.rs:LL:COL ... LL | unsafe { self.offset(count as isize) } diff --git a/src/test/ui/const-ptr/forbidden_slices.64bit.stderr b/src/test/ui/const-ptr/forbidden_slices.64bit.stderr index f22a708e339..0aa37452f1c 100644 --- a/src/test/ui/const-ptr/forbidden_slices.64bit.stderr +++ b/src/test/ui/const-ptr/forbidden_slices.64bit.stderr @@ -4,7 +4,7 @@ error[E0080]: could not evaluate static initializer LL | &*ptr::slice_from_raw_parts(data, len) | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ | | - | dereferencing pointer failed: null pointer is not a valid pointer + | dereferencing pointer failed: null pointer is a dangling pointer (it has no provenance) | inside `std::slice::from_raw_parts::<u32>` at $SRC_DIR/core/src/slice/raw.rs:LL:COL | ::: $DIR/forbidden_slices.rs:19:34 @@ -18,7 +18,7 @@ error[E0080]: could not evaluate static initializer LL | &*ptr::slice_from_raw_parts(data, len) | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ | | - | dereferencing pointer failed: null pointer is not a valid pointer + | dereferencing pointer failed: null pointer is a dangling pointer (it has no provenance) | inside `std::slice::from_raw_parts::<()>` at $SRC_DIR/core/src/slice/raw.rs:LL:COL | ::: $DIR/forbidden_slices.rs:20:33 @@ -44,7 +44,7 @@ error[E0080]: it is undefined behavior to use this value --> $DIR/forbidden_slices.rs:26:1 | LL | pub static S4: &[u8] = unsafe { from_raw_parts((&D1) as *const _ as _, 1) }; - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ constructing invalid value at .<deref>[0]: encountered uninitialized bytes + | ^^^^^^^^^^^^^^^^^^^^ constructing invalid value at .<deref>[0]: encountered uninitialized bytes | = note: The rules on what exactly is undefined behavior aren't clear, so this check might be overzealous. Please open an issue on the rustc repository if you believe it should not be considered undefined behavior. = note: the raw bytes of the constant (size: 16, align: 8) { @@ -55,7 +55,7 @@ error[E0080]: it is undefined behavior to use this value --> $DIR/forbidden_slices.rs:28:1 | LL | pub static S5: &[u8] = unsafe { from_raw_parts((&D3) as *const _ as _, size_of::<&u32>()) }; - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ constructing invalid value at .<deref>: encountered a pointer, but expected plain (non-pointer) bytes + | ^^^^^^^^^^^^^^^^^^^^ constructing invalid value at .<deref>: encountered a pointer, but expected plain (non-pointer) bytes | = note: The rules on what exactly is undefined behavior aren't clear, so this check might be overzealous. Please open an issue on the rustc repository if you believe it should not be considered undefined behavior. = note: the raw bytes of the constant (size: 16, align: 8) { @@ -66,7 +66,7 @@ error[E0080]: it is undefined behavior to use this value --> $DIR/forbidden_slices.rs:30:1 | LL | pub static S6: &[bool] = unsafe { from_raw_parts((&D0) as *const _ as _, 4) }; - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ constructing invalid value at .<deref>[0]: encountered 0x11, but expected a boolean + | ^^^^^^^^^^^^^^^^^^^^^^ constructing invalid value at .<deref>[0]: encountered 0x11, but expected a boolean | = note: The rules on what exactly is undefined behavior aren't clear, so this check might be overzealous. Please open an issue on the rustc repository if you believe it should not be considered undefined behavior. = note: the raw bytes of the constant (size: 16, align: 8) { @@ -76,13 +76,8 @@ LL | pub static S6: &[bool] = unsafe { from_raw_parts((&D0) as *const _ as _, 4) error[E0080]: it is undefined behavior to use this value --> $DIR/forbidden_slices.rs:33:1 | -LL | / pub static S7: &[u16] = unsafe { -LL | | -LL | | let ptr = (&D2 as *const Struct as *const u16).byte_add(1); -LL | | -LL | | from_raw_parts(ptr, 4) -LL | | }; - | |__^ constructing invalid value: encountered an unaligned reference (required 2 byte alignment but found 1) +LL | pub static S7: &[u16] = unsafe { + | ^^^^^^^^^^^^^^^^^^^^^ constructing invalid value: encountered an unaligned reference (required 2 byte alignment but found 1) | = note: The rules on what exactly is undefined behavior aren't clear, so this check might be overzealous. Please open an issue on the rustc repository if you believe it should not be considered undefined behavior. = note: the raw bytes of the constant (size: 16, align: 8) { @@ -109,7 +104,7 @@ error[E0080]: could not evaluate static initializer LL | unsafe { intrinsics::ptr_offset_from_unsigned(self, origin) } | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ | | - | out-of-bounds offset_from: null pointer is not a valid pointer + | out-of-bounds offset_from: null pointer is a dangling pointer (it has no provenance) | inside `ptr::const_ptr::<impl *const u32>::sub_ptr` at $SRC_DIR/core/src/ptr/const_ptr.rs:LL:COL | ::: $SRC_DIR/core/src/slice/raw.rs:LL:COL @@ -149,7 +144,7 @@ error[E0080]: could not evaluate static initializer LL | unsafe { intrinsics::offset(self, count) } | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ | | - | pointer arithmetic failed: ALLOC_ID has size 4, so pointer to 8 bytes starting at offset 0 is out-of-bounds + | out-of-bounds pointer arithmetic: ALLOC_ID has size 4, so pointer to 8 bytes starting at offset 0 is out-of-bounds | inside `ptr::const_ptr::<impl *const u32>::offset` at $SRC_DIR/core/src/ptr/const_ptr.rs:LL:COL ... LL | unsafe { self.offset(count as isize) } @@ -163,12 +158,8 @@ LL | from_ptr_range(ptr..ptr.add(2)) error[E0080]: it is undefined behavior to use this value --> $DIR/forbidden_slices.rs:53:1 | -LL | / pub static R4: &[u8] = unsafe { -LL | | -LL | | let ptr = (&D1) as *const MaybeUninit<&u32> as *const u8; -LL | | from_ptr_range(ptr..ptr.add(1)) -LL | | }; - | |__^ constructing invalid value at .<deref>[0]: encountered uninitialized bytes +LL | pub static R4: &[u8] = unsafe { + | ^^^^^^^^^^^^^^^^^^^^ constructing invalid value at .<deref>[0]: encountered uninitialized bytes | = note: The rules on what exactly is undefined behavior aren't clear, so this check might be overzealous. Please open an issue on the rustc repository if you believe it should not be considered undefined behavior. = note: the raw bytes of the constant (size: 16, align: 8) { @@ -178,12 +169,8 @@ LL | | }; error[E0080]: it is undefined behavior to use this value --> $DIR/forbidden_slices.rs:58:1 | -LL | / pub static R5: &[u8] = unsafe { -LL | | -LL | | let ptr = &D3 as *const &u32; -LL | | from_ptr_range(ptr.cast()..ptr.add(1).cast()) -LL | | }; - | |__^ constructing invalid value at .<deref>: encountered a pointer, but expected plain (non-pointer) bytes +LL | pub static R5: &[u8] = unsafe { + | ^^^^^^^^^^^^^^^^^^^^ constructing invalid value at .<deref>: encountered a pointer, but expected plain (non-pointer) bytes | = note: The rules on what exactly is undefined behavior aren't clear, so this check might be overzealous. Please open an issue on the rustc repository if you believe it should not be considered undefined behavior. = note: the raw bytes of the constant (size: 16, align: 8) { @@ -193,12 +180,8 @@ LL | | }; error[E0080]: it is undefined behavior to use this value --> $DIR/forbidden_slices.rs:63:1 | -LL | / pub static R6: &[bool] = unsafe { -LL | | -LL | | let ptr = &D0 as *const u32 as *const bool; -LL | | from_ptr_range(ptr..ptr.add(4)) -LL | | }; - | |__^ constructing invalid value at .<deref>[0]: encountered 0x11, but expected a boolean +LL | pub static R6: &[bool] = unsafe { + | ^^^^^^^^^^^^^^^^^^^^^^ constructing invalid value at .<deref>[0]: encountered 0x11, but expected a boolean | = note: The rules on what exactly is undefined behavior aren't clear, so this check might be overzealous. Please open an issue on the rustc repository if you believe it should not be considered undefined behavior. = note: the raw bytes of the constant (size: 16, align: 8) { @@ -208,12 +191,8 @@ LL | | }; error[E0080]: it is undefined behavior to use this value --> $DIR/forbidden_slices.rs:68:1 | -LL | / pub static R7: &[u16] = unsafe { -LL | | -LL | | let ptr = (&D2 as *const Struct as *const u16).byte_add(1); -LL | | from_ptr_range(ptr..ptr.add(4)) -LL | | }; - | |__^ constructing invalid value: encountered an unaligned reference (required 2 byte alignment but found 1) +LL | pub static R7: &[u16] = unsafe { + | ^^^^^^^^^^^^^^^^^^^^^ constructing invalid value: encountered an unaligned reference (required 2 byte alignment but found 1) | = note: The rules on what exactly is undefined behavior aren't clear, so this check might be overzealous. Please open an issue on the rustc repository if you believe it should not be considered undefined behavior. = note: the raw bytes of the constant (size: 16, align: 8) { @@ -226,7 +205,7 @@ error[E0080]: could not evaluate static initializer LL | unsafe { intrinsics::offset(self, count) } | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ | | - | pointer arithmetic failed: ALLOC_ID has size 8, so pointer to 8 bytes starting at offset 1 is out-of-bounds + | out-of-bounds pointer arithmetic: ALLOC_ID has size 8, so pointer to 8 bytes starting at offset 1 is out-of-bounds | inside `ptr::const_ptr::<impl *const u64>::offset` at $SRC_DIR/core/src/ptr/const_ptr.rs:LL:COL ... LL | unsafe { self.offset(count as isize) } diff --git a/src/test/ui/consts/assert-type-intrinsics.stderr b/src/test/ui/consts/assert-type-intrinsics.stderr index 89f8f2ffc55..f3b9170d428 100644 --- a/src/test/ui/consts/assert-type-intrinsics.stderr +++ b/src/test/ui/consts/assert-type-intrinsics.stderr @@ -1,11 +1,10 @@ error: any use of this value will cause an error --> $DIR/assert-type-intrinsics.rs:14:9 | -LL | / const _BAD1: () = unsafe { -LL | | MaybeUninit::<!>::uninit().assume_init(); - | | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ aborted execution: attempted to instantiate uninhabited type `!` -LL | | }; - | |______- +LL | const _BAD1: () = unsafe { + | --------------- +LL | MaybeUninit::<!>::uninit().assume_init(); + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ aborted execution: attempted to instantiate uninhabited type `!` | = note: `#[deny(const_err)]` on by default = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release! @@ -14,11 +13,10 @@ LL | | }; error: any use of this value will cause an error --> $DIR/assert-type-intrinsics.rs:17:9 | -LL | / const _BAD2: () = unsafe { -LL | | intrinsics::assert_uninit_valid::<bool>(); - | | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ aborted execution: attempted to leave type `bool` uninitialized, which is invalid -LL | | }; - | |______- +LL | const _BAD2: () = unsafe { + | --------------- +LL | intrinsics::assert_uninit_valid::<bool>(); + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ aborted execution: attempted to leave type `bool` uninitialized, which is invalid | = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release! = note: for more information, see issue #71800 <https://github.com/rust-lang/rust/issues/71800> @@ -26,11 +24,10 @@ LL | | }; error: any use of this value will cause an error --> $DIR/assert-type-intrinsics.rs:20:9 | -LL | / const _BAD3: () = unsafe { -LL | | intrinsics::assert_zero_valid::<&'static i32>(); - | | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ aborted execution: attempted to zero-initialize type `&i32`, which is invalid -LL | | }; - | |______- +LL | const _BAD3: () = unsafe { + | --------------- +LL | intrinsics::assert_zero_valid::<&'static i32>(); + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ aborted execution: attempted to zero-initialize type `&i32`, which is invalid | = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release! = note: for more information, see issue #71800 <https://github.com/rust-lang/rust/issues/71800> @@ -41,11 +38,10 @@ Future incompatibility report: Future breakage diagnostic: error: any use of this value will cause an error --> $DIR/assert-type-intrinsics.rs:14:9 | -LL | / const _BAD1: () = unsafe { -LL | | MaybeUninit::<!>::uninit().assume_init(); - | | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ aborted execution: attempted to instantiate uninhabited type `!` -LL | | }; - | |______- +LL | const _BAD1: () = unsafe { + | --------------- +LL | MaybeUninit::<!>::uninit().assume_init(); + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ aborted execution: attempted to instantiate uninhabited type `!` | = note: `#[deny(const_err)]` on by default = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release! @@ -55,11 +51,10 @@ Future breakage diagnostic: error: any use of this value will cause an error --> $DIR/assert-type-intrinsics.rs:17:9 | -LL | / const _BAD2: () = unsafe { -LL | | intrinsics::assert_uninit_valid::<bool>(); - | | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ aborted execution: attempted to leave type `bool` uninitialized, which is invalid -LL | | }; - | |______- +LL | const _BAD2: () = unsafe { + | --------------- +LL | intrinsics::assert_uninit_valid::<bool>(); + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ aborted execution: attempted to leave type `bool` uninitialized, which is invalid | = note: `#[deny(const_err)]` on by default = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release! @@ -69,11 +64,10 @@ Future breakage diagnostic: error: any use of this value will cause an error --> $DIR/assert-type-intrinsics.rs:20:9 | -LL | / const _BAD3: () = unsafe { -LL | | intrinsics::assert_zero_valid::<&'static i32>(); - | | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ aborted execution: attempted to zero-initialize type `&i32`, which is invalid -LL | | }; - | |______- +LL | const _BAD3: () = unsafe { + | --------------- +LL | intrinsics::assert_zero_valid::<&'static i32>(); + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ aborted execution: attempted to zero-initialize type `&i32`, which is invalid | = note: `#[deny(const_err)]` on by default = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release! diff --git a/src/test/ui/consts/assoc_const_generic_impl.stderr b/src/test/ui/consts/assoc_const_generic_impl.stderr index cccf62a8ff6..17cbaef1f06 100644 --- a/src/test/ui/consts/assoc_const_generic_impl.stderr +++ b/src/test/ui/consts/assoc_const_generic_impl.stderr @@ -2,9 +2,7 @@ warning: any use of this value will cause an error --> $DIR/assoc_const_generic_impl.rs:11:34 | LL | const I_AM_ZERO_SIZED: () = [()][std::mem::size_of::<Self>()]; - | -----------------------------^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^- - | | - | index out of bounds: the length is 1 but the index is 4 + | ------------------------- ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ index out of bounds: the length is 1 but the index is 4 | note: the lint level is defined here --> $DIR/assoc_const_generic_impl.rs:3:9 @@ -27,9 +25,7 @@ warning: any use of this value will cause an error --> $DIR/assoc_const_generic_impl.rs:11:34 | LL | const I_AM_ZERO_SIZED: () = [()][std::mem::size_of::<Self>()]; - | -----------------------------^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^- - | | - | index out of bounds: the length is 1 but the index is 4 + | ------------------------- ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ index out of bounds: the length is 1 but the index is 4 | note: the lint level is defined here --> $DIR/assoc_const_generic_impl.rs:3:9 diff --git a/src/test/ui/consts/const-as-fn.stderr b/src/test/ui/consts/const-as-fn.stderr index b8dd4134b28..6c51ed89393 100644 --- a/src/test/ui/consts/const-as-fn.stderr +++ b/src/test/ui/consts/const-as-fn.stderr @@ -2,7 +2,7 @@ error[E0618]: expected function, found `usize` --> $DIR/const-as-fn.rs:4:5 | LL | const FOO: usize = 0; - | --------------------- `FOO` defined here + | ---------------- `FOO` defined here ... LL | FOO(); | ^^^-- diff --git a/src/test/ui/consts/const-deref-ptr.stderr b/src/test/ui/consts/const-deref-ptr.stderr index 7606afdc4ff..22cb6451e87 100644 --- a/src/test/ui/consts/const-deref-ptr.stderr +++ b/src/test/ui/consts/const-deref-ptr.stderr @@ -2,7 +2,7 @@ error[E0080]: could not evaluate static initializer --> $DIR/const-deref-ptr.rs:4:29 | LL | static C: u64 = unsafe {*(0xdeadbeef as *const u64)}; - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^ dereferencing pointer failed: 0xdeadbeef is not a valid pointer + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^ dereferencing pointer failed: 0xdeadbeef[noalloc] is a dangling pointer (it has no provenance) error: aborting due to previous error diff --git a/src/test/ui/consts/const-enum-cast.rs b/src/test/ui/consts/const-enum-cast.rs index a3255c2f601..39968495144 100644 --- a/src/test/ui/consts/const-enum-cast.rs +++ b/src/test/ui/consts/const-enum-cast.rs @@ -4,6 +4,19 @@ enum A { A1, A2 } enum B { B1=4, B2=2 } +#[allow(dead_code)] +#[repr(align(8))] +enum Aligned { + Zero = 0, + One = 1, +} + +// regression test for https://github.com/rust-lang/rust/issues/96185 +const X: u8 = { + let aligned = Aligned::Zero; + aligned as u8 +}; + pub fn main () { static c1: isize = A::A2 as isize; static c2: isize = B::B2 as isize; @@ -23,4 +36,6 @@ pub fn main () { assert_eq!(c2_2, 4); assert_eq!(a1_2, 0); assert_eq!(a2_2, 4); + + assert_eq!(X, 0); } diff --git a/src/test/ui/consts/const-err-early.stderr b/src/test/ui/consts/const-err-early.stderr index 385e770eb4f..1b94aa080dd 100644 --- a/src/test/ui/consts/const-err-early.stderr +++ b/src/test/ui/consts/const-err-early.stderr @@ -2,9 +2,7 @@ error: any use of this value will cause an error --> $DIR/const-err-early.rs:3:19 | LL | pub const A: i8 = -i8::MIN; - | ------------------^^^^^^^^- - | | - | attempt to negate `i8::MIN`, which would overflow + | --------------- ^^^^^^^^ attempt to negate `i8::MIN`, which would overflow | note: the lint level is defined here --> $DIR/const-err-early.rs:1:9 @@ -18,9 +16,7 @@ error: any use of this value will cause an error --> $DIR/const-err-early.rs:5:19 | LL | pub const B: u8 = 200u8 + 200u8; - | ------------------^^^^^^^^^^^^^- - | | - | attempt to compute `200_u8 + 200_u8`, which would overflow + | --------------- ^^^^^^^^^^^^^ attempt to compute `200_u8 + 200_u8`, which would overflow | = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release! = note: for more information, see issue #71800 <https://github.com/rust-lang/rust/issues/71800> @@ -29,9 +25,7 @@ error: any use of this value will cause an error --> $DIR/const-err-early.rs:7:19 | LL | pub const C: u8 = 200u8 * 4; - | ------------------^^^^^^^^^- - | | - | attempt to compute `200_u8 * 4_u8`, which would overflow + | --------------- ^^^^^^^^^ attempt to compute `200_u8 * 4_u8`, which would overflow | = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release! = note: for more information, see issue #71800 <https://github.com/rust-lang/rust/issues/71800> @@ -40,9 +34,7 @@ error: any use of this value will cause an error --> $DIR/const-err-early.rs:9:19 | LL | pub const D: u8 = 42u8 - (42u8 + 1); - | ------------------^^^^^^^^^^^^^^^^^- - | | - | attempt to compute `42_u8 - 43_u8`, which would overflow + | --------------- ^^^^^^^^^^^^^^^^^ attempt to compute `42_u8 - 43_u8`, which would overflow | = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release! = note: for more information, see issue #71800 <https://github.com/rust-lang/rust/issues/71800> @@ -51,9 +43,7 @@ error: any use of this value will cause an error --> $DIR/const-err-early.rs:11:19 | LL | pub const E: u8 = [5u8][1]; - | ------------------^^^^^^^^- - | | - | index out of bounds: the length is 1 but the index is 1 + | --------------- ^^^^^^^^ index out of bounds: the length is 1 but the index is 1 | = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release! = note: for more information, see issue #71800 <https://github.com/rust-lang/rust/issues/71800> @@ -65,9 +55,7 @@ error: any use of this value will cause an error --> $DIR/const-err-early.rs:3:19 | LL | pub const A: i8 = -i8::MIN; - | ------------------^^^^^^^^- - | | - | attempt to negate `i8::MIN`, which would overflow + | --------------- ^^^^^^^^ attempt to negate `i8::MIN`, which would overflow | note: the lint level is defined here --> $DIR/const-err-early.rs:1:9 @@ -82,9 +70,7 @@ error: any use of this value will cause an error --> $DIR/const-err-early.rs:5:19 | LL | pub const B: u8 = 200u8 + 200u8; - | ------------------^^^^^^^^^^^^^- - | | - | attempt to compute `200_u8 + 200_u8`, which would overflow + | --------------- ^^^^^^^^^^^^^ attempt to compute `200_u8 + 200_u8`, which would overflow | note: the lint level is defined here --> $DIR/const-err-early.rs:1:9 @@ -99,9 +85,7 @@ error: any use of this value will cause an error --> $DIR/const-err-early.rs:7:19 | LL | pub const C: u8 = 200u8 * 4; - | ------------------^^^^^^^^^- - | | - | attempt to compute `200_u8 * 4_u8`, which would overflow + | --------------- ^^^^^^^^^ attempt to compute `200_u8 * 4_u8`, which would overflow | note: the lint level is defined here --> $DIR/const-err-early.rs:1:9 @@ -116,9 +100,7 @@ error: any use of this value will cause an error --> $DIR/const-err-early.rs:9:19 | LL | pub const D: u8 = 42u8 - (42u8 + 1); - | ------------------^^^^^^^^^^^^^^^^^- - | | - | attempt to compute `42_u8 - 43_u8`, which would overflow + | --------------- ^^^^^^^^^^^^^^^^^ attempt to compute `42_u8 - 43_u8`, which would overflow | note: the lint level is defined here --> $DIR/const-err-early.rs:1:9 @@ -133,9 +115,7 @@ error: any use of this value will cause an error --> $DIR/const-err-early.rs:11:19 | LL | pub const E: u8 = [5u8][1]; - | ------------------^^^^^^^^- - | | - | index out of bounds: the length is 1 but the index is 1 + | --------------- ^^^^^^^^ index out of bounds: the length is 1 but the index is 1 | note: the lint level is defined here --> $DIR/const-err-early.rs:1:9 diff --git a/src/test/ui/consts/const-err-multi.stderr b/src/test/ui/consts/const-err-multi.stderr index a195459ff08..f179843654e 100644 --- a/src/test/ui/consts/const-err-multi.stderr +++ b/src/test/ui/consts/const-err-multi.stderr @@ -2,9 +2,7 @@ error: any use of this value will cause an error --> $DIR/const-err-multi.rs:3:19 | LL | pub const A: i8 = -i8::MIN; - | ------------------^^^^^^^^- - | | - | attempt to negate `i8::MIN`, which would overflow + | --------------- ^^^^^^^^ attempt to negate `i8::MIN`, which would overflow | note: the lint level is defined here --> $DIR/const-err-multi.rs:1:9 @@ -18,9 +16,7 @@ error: any use of this value will cause an error --> $DIR/const-err-multi.rs:6:19 | LL | pub const B: i8 = A; - | ------------------^- - | | - | referenced constant has errors + | --------------- ^ referenced constant has errors | = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release! = note: for more information, see issue #71800 <https://github.com/rust-lang/rust/issues/71800> @@ -29,9 +25,7 @@ error: any use of this value will cause an error --> $DIR/const-err-multi.rs:9:19 | LL | pub const C: u8 = A as u8; - | ------------------^------- - | | - | referenced constant has errors + | --------------- ^ referenced constant has errors | = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release! = note: for more information, see issue #71800 <https://github.com/rust-lang/rust/issues/71800> @@ -40,9 +34,7 @@ error: any use of this value will cause an error --> $DIR/const-err-multi.rs:12:24 | LL | pub const D: i8 = 50 - A; - | -----------------------^- - | | - | referenced constant has errors + | --------------- ^ referenced constant has errors | = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release! = note: for more information, see issue #71800 <https://github.com/rust-lang/rust/issues/71800> @@ -54,9 +46,7 @@ error: any use of this value will cause an error --> $DIR/const-err-multi.rs:3:19 | LL | pub const A: i8 = -i8::MIN; - | ------------------^^^^^^^^- - | | - | attempt to negate `i8::MIN`, which would overflow + | --------------- ^^^^^^^^ attempt to negate `i8::MIN`, which would overflow | note: the lint level is defined here --> $DIR/const-err-multi.rs:1:9 @@ -71,9 +61,7 @@ error: any use of this value will cause an error --> $DIR/const-err-multi.rs:6:19 | LL | pub const B: i8 = A; - | ------------------^- - | | - | referenced constant has errors + | --------------- ^ referenced constant has errors | note: the lint level is defined here --> $DIR/const-err-multi.rs:1:9 @@ -88,9 +76,7 @@ error: any use of this value will cause an error --> $DIR/const-err-multi.rs:9:19 | LL | pub const C: u8 = A as u8; - | ------------------^------- - | | - | referenced constant has errors + | --------------- ^ referenced constant has errors | note: the lint level is defined here --> $DIR/const-err-multi.rs:1:9 @@ -105,9 +91,7 @@ error: any use of this value will cause an error --> $DIR/const-err-multi.rs:12:24 | LL | pub const D: i8 = 50 - A; - | -----------------------^- - | | - | referenced constant has errors + | --------------- ^ referenced constant has errors | note: the lint level is defined here --> $DIR/const-err-multi.rs:1:9 diff --git a/src/test/ui/consts/const-err.stderr b/src/test/ui/consts/const-err.stderr index 3b03e702dc4..e3b0d29c853 100644 --- a/src/test/ui/consts/const-err.stderr +++ b/src/test/ui/consts/const-err.stderr @@ -2,9 +2,7 @@ warning: any use of this value will cause an error --> $DIR/const-err.rs:11:17 | LL | const FOO: u8 = [5u8][1]; - | ----------------^^^^^^^^- - | | - | index out of bounds: the length is 1 but the index is 1 + | ------------- ^^^^^^^^ index out of bounds: the length is 1 but the index is 1 | note: the lint level is defined here --> $DIR/const-err.rs:5:9 @@ -34,9 +32,7 @@ warning: any use of this value will cause an error --> $DIR/const-err.rs:11:17 | LL | const FOO: u8 = [5u8][1]; - | ----------------^^^^^^^^- - | | - | index out of bounds: the length is 1 but the index is 1 + | ------------- ^^^^^^^^ index out of bounds: the length is 1 but the index is 1 | note: the lint level is defined here --> $DIR/const-err.rs:5:9 diff --git a/src/test/ui/consts/const-eval/conditional_array_execution.stderr b/src/test/ui/consts/const-eval/conditional_array_execution.stderr index f88bf445426..2312e2a45db 100644 --- a/src/test/ui/consts/const-eval/conditional_array_execution.stderr +++ b/src/test/ui/consts/const-eval/conditional_array_execution.stderr @@ -2,9 +2,7 @@ warning: any use of this value will cause an error --> $DIR/conditional_array_execution.rs:7:19 | LL | const FOO: u32 = [X - Y, Y - X][(X < Y) as usize]; - | ------------------^^^^^--------------------------- - | | - | attempt to compute `5_u32 - 6_u32`, which would overflow + | -------------- ^^^^^ attempt to compute `5_u32 - 6_u32`, which would overflow | note: the lint level is defined here --> $DIR/conditional_array_execution.rs:3:9 @@ -38,9 +36,7 @@ warning: any use of this value will cause an error --> $DIR/conditional_array_execution.rs:7:19 | LL | const FOO: u32 = [X - Y, Y - X][(X < Y) as usize]; - | ------------------^^^^^--------------------------- - | | - | attempt to compute `5_u32 - 6_u32`, which would overflow + | -------------- ^^^^^ attempt to compute `5_u32 - 6_u32`, which would overflow | note: the lint level is defined here --> $DIR/conditional_array_execution.rs:3:9 diff --git a/src/test/ui/consts/const-eval/const-eval-overflow-2.stderr b/src/test/ui/consts/const-eval/const-eval-overflow-2.stderr index 1c74b978827..cf50c19caa7 100644 --- a/src/test/ui/consts/const-eval/const-eval-overflow-2.stderr +++ b/src/test/ui/consts/const-eval/const-eval-overflow-2.stderr @@ -17,9 +17,7 @@ warning: any use of this value will cause an error --> $DIR/const-eval-overflow-2.rs:11:25 | LL | const NEG_NEG_128: i8 = -NEG_128; - | ------------------------^^^^^^^^- - | | - | attempt to negate `i8::MIN`, which would overflow + | --------------------- ^^^^^^^^ attempt to negate `i8::MIN`, which would overflow | note: the lint level is defined here --> $DIR/const-eval-overflow-2.rs:4:36 diff --git a/src/test/ui/consts/const-eval/const-eval-overflow2.stderr b/src/test/ui/consts/const-eval/const-eval-overflow2.stderr index 948ead521ea..dab9a76c7d4 100644 --- a/src/test/ui/consts/const-eval/const-eval-overflow2.stderr +++ b/src/test/ui/consts/const-eval/const-eval-overflow2.stderr @@ -1,12 +1,11 @@ error: any use of this value will cause an error --> $DIR/const-eval-overflow2.rs:14:6 | -LL | / const VALS_I8: (i8,) = -LL | | ( -LL | | i8::MIN - 1, - | | ^^^^^^^^^^^ attempt to compute `i8::MIN - 1_i8`, which would overflow -LL | | ); - | |_______- +LL | const VALS_I8: (i8,) = + | -------------------- +LL | ( +LL | i8::MIN - 1, + | ^^^^^^^^^^^ attempt to compute `i8::MIN - 1_i8`, which would overflow | note: the lint level is defined here --> $DIR/const-eval-overflow2.rs:8:9 @@ -19,12 +18,11 @@ LL | #![deny(const_err)] error: any use of this value will cause an error --> $DIR/const-eval-overflow2.rs:21:6 | -LL | / const VALS_I16: (i16,) = -LL | | ( -LL | | i16::MIN - 1, - | | ^^^^^^^^^^^^ attempt to compute `i16::MIN - 1_i16`, which would overflow -LL | | ); - | |_______- +LL | const VALS_I16: (i16,) = + | ---------------------- +LL | ( +LL | i16::MIN - 1, + | ^^^^^^^^^^^^ attempt to compute `i16::MIN - 1_i16`, which would overflow | = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release! = note: for more information, see issue #71800 <https://github.com/rust-lang/rust/issues/71800> @@ -32,12 +30,11 @@ LL | | ); error: any use of this value will cause an error --> $DIR/const-eval-overflow2.rs:28:6 | -LL | / const VALS_I32: (i32,) = -LL | | ( -LL | | i32::MIN - 1, - | | ^^^^^^^^^^^^ attempt to compute `i32::MIN - 1_i32`, which would overflow -LL | | ); - | |_______- +LL | const VALS_I32: (i32,) = + | ---------------------- +LL | ( +LL | i32::MIN - 1, + | ^^^^^^^^^^^^ attempt to compute `i32::MIN - 1_i32`, which would overflow | = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release! = note: for more information, see issue #71800 <https://github.com/rust-lang/rust/issues/71800> @@ -45,12 +42,11 @@ LL | | ); error: any use of this value will cause an error --> $DIR/const-eval-overflow2.rs:35:6 | -LL | / const VALS_I64: (i64,) = -LL | | ( -LL | | i64::MIN - 1, - | | ^^^^^^^^^^^^ attempt to compute `i64::MIN - 1_i64`, which would overflow -LL | | ); - | |_______- +LL | const VALS_I64: (i64,) = + | ---------------------- +LL | ( +LL | i64::MIN - 1, + | ^^^^^^^^^^^^ attempt to compute `i64::MIN - 1_i64`, which would overflow | = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release! = note: for more information, see issue #71800 <https://github.com/rust-lang/rust/issues/71800> @@ -58,12 +54,11 @@ LL | | ); error: any use of this value will cause an error --> $DIR/const-eval-overflow2.rs:42:6 | -LL | / const VALS_U8: (u8,) = -LL | | ( -LL | | u8::MIN - 1, - | | ^^^^^^^^^^^ attempt to compute `0_u8 - 1_u8`, which would overflow -LL | | ); - | |_______- +LL | const VALS_U8: (u8,) = + | -------------------- +LL | ( +LL | u8::MIN - 1, + | ^^^^^^^^^^^ attempt to compute `0_u8 - 1_u8`, which would overflow | = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release! = note: for more information, see issue #71800 <https://github.com/rust-lang/rust/issues/71800> @@ -71,11 +66,10 @@ LL | | ); error: any use of this value will cause an error --> $DIR/const-eval-overflow2.rs:48:6 | -LL | / const VALS_U16: (u16,) = ( -LL | | u16::MIN - 1, - | | ^^^^^^^^^^^^ attempt to compute `0_u16 - 1_u16`, which would overflow -LL | | ); - | |_______- +LL | const VALS_U16: (u16,) = ( + | ---------------------- +LL | u16::MIN - 1, + | ^^^^^^^^^^^^ attempt to compute `0_u16 - 1_u16`, which would overflow | = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release! = note: for more information, see issue #71800 <https://github.com/rust-lang/rust/issues/71800> @@ -83,11 +77,10 @@ LL | | ); error: any use of this value will cause an error --> $DIR/const-eval-overflow2.rs:54:6 | -LL | / const VALS_U32: (u32,) = ( -LL | | u32::MIN - 1, - | | ^^^^^^^^^^^^ attempt to compute `0_u32 - 1_u32`, which would overflow -LL | | ); - | |_______- +LL | const VALS_U32: (u32,) = ( + | ---------------------- +LL | u32::MIN - 1, + | ^^^^^^^^^^^^ attempt to compute `0_u32 - 1_u32`, which would overflow | = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release! = note: for more information, see issue #71800 <https://github.com/rust-lang/rust/issues/71800> @@ -95,12 +88,11 @@ LL | | ); error: any use of this value will cause an error --> $DIR/const-eval-overflow2.rs:61:6 | -LL | / const VALS_U64: (u64,) = -LL | | ( -LL | | u64::MIN - 1, - | | ^^^^^^^^^^^^ attempt to compute `0_u64 - 1_u64`, which would overflow -LL | | ); - | |_______- +LL | const VALS_U64: (u64,) = + | ---------------------- +LL | ( +LL | u64::MIN - 1, + | ^^^^^^^^^^^^ attempt to compute `0_u64 - 1_u64`, which would overflow | = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release! = note: for more information, see issue #71800 <https://github.com/rust-lang/rust/issues/71800> @@ -111,12 +103,11 @@ Future incompatibility report: Future breakage diagnostic: error: any use of this value will cause an error --> $DIR/const-eval-overflow2.rs:14:6 | -LL | / const VALS_I8: (i8,) = -LL | | ( -LL | | i8::MIN - 1, - | | ^^^^^^^^^^^ attempt to compute `i8::MIN - 1_i8`, which would overflow -LL | | ); - | |_______- +LL | const VALS_I8: (i8,) = + | -------------------- +LL | ( +LL | i8::MIN - 1, + | ^^^^^^^^^^^ attempt to compute `i8::MIN - 1_i8`, which would overflow | note: the lint level is defined here --> $DIR/const-eval-overflow2.rs:8:9 @@ -130,12 +121,11 @@ Future breakage diagnostic: error: any use of this value will cause an error --> $DIR/const-eval-overflow2.rs:21:6 | -LL | / const VALS_I16: (i16,) = -LL | | ( -LL | | i16::MIN - 1, - | | ^^^^^^^^^^^^ attempt to compute `i16::MIN - 1_i16`, which would overflow -LL | | ); - | |_______- +LL | const VALS_I16: (i16,) = + | ---------------------- +LL | ( +LL | i16::MIN - 1, + | ^^^^^^^^^^^^ attempt to compute `i16::MIN - 1_i16`, which would overflow | note: the lint level is defined here --> $DIR/const-eval-overflow2.rs:8:9 @@ -149,12 +139,11 @@ Future breakage diagnostic: error: any use of this value will cause an error --> $DIR/const-eval-overflow2.rs:28:6 | -LL | / const VALS_I32: (i32,) = -LL | | ( -LL | | i32::MIN - 1, - | | ^^^^^^^^^^^^ attempt to compute `i32::MIN - 1_i32`, which would overflow -LL | | ); - | |_______- +LL | const VALS_I32: (i32,) = + | ---------------------- +LL | ( +LL | i32::MIN - 1, + | ^^^^^^^^^^^^ attempt to compute `i32::MIN - 1_i32`, which would overflow | note: the lint level is defined here --> $DIR/const-eval-overflow2.rs:8:9 @@ -168,12 +157,11 @@ Future breakage diagnostic: error: any use of this value will cause an error --> $DIR/const-eval-overflow2.rs:35:6 | -LL | / const VALS_I64: (i64,) = -LL | | ( -LL | | i64::MIN - 1, - | | ^^^^^^^^^^^^ attempt to compute `i64::MIN - 1_i64`, which would overflow -LL | | ); - | |_______- +LL | const VALS_I64: (i64,) = + | ---------------------- +LL | ( +LL | i64::MIN - 1, + | ^^^^^^^^^^^^ attempt to compute `i64::MIN - 1_i64`, which would overflow | note: the lint level is defined here --> $DIR/const-eval-overflow2.rs:8:9 @@ -187,12 +175,11 @@ Future breakage diagnostic: error: any use of this value will cause an error --> $DIR/const-eval-overflow2.rs:42:6 | -LL | / const VALS_U8: (u8,) = -LL | | ( -LL | | u8::MIN - 1, - | | ^^^^^^^^^^^ attempt to compute `0_u8 - 1_u8`, which would overflow -LL | | ); - | |_______- +LL | const VALS_U8: (u8,) = + | -------------------- +LL | ( +LL | u8::MIN - 1, + | ^^^^^^^^^^^ attempt to compute `0_u8 - 1_u8`, which would overflow | note: the lint level is defined here --> $DIR/const-eval-overflow2.rs:8:9 @@ -206,11 +193,10 @@ Future breakage diagnostic: error: any use of this value will cause an error --> $DIR/const-eval-overflow2.rs:48:6 | -LL | / const VALS_U16: (u16,) = ( -LL | | u16::MIN - 1, - | | ^^^^^^^^^^^^ attempt to compute `0_u16 - 1_u16`, which would overflow -LL | | ); - | |_______- +LL | const VALS_U16: (u16,) = ( + | ---------------------- +LL | u16::MIN - 1, + | ^^^^^^^^^^^^ attempt to compute `0_u16 - 1_u16`, which would overflow | note: the lint level is defined here --> $DIR/const-eval-overflow2.rs:8:9 @@ -224,11 +210,10 @@ Future breakage diagnostic: error: any use of this value will cause an error --> $DIR/const-eval-overflow2.rs:54:6 | -LL | / const VALS_U32: (u32,) = ( -LL | | u32::MIN - 1, - | | ^^^^^^^^^^^^ attempt to compute `0_u32 - 1_u32`, which would overflow -LL | | ); - | |_______- +LL | const VALS_U32: (u32,) = ( + | ---------------------- +LL | u32::MIN - 1, + | ^^^^^^^^^^^^ attempt to compute `0_u32 - 1_u32`, which would overflow | note: the lint level is defined here --> $DIR/const-eval-overflow2.rs:8:9 @@ -242,12 +227,11 @@ Future breakage diagnostic: error: any use of this value will cause an error --> $DIR/const-eval-overflow2.rs:61:6 | -LL | / const VALS_U64: (u64,) = -LL | | ( -LL | | u64::MIN - 1, - | | ^^^^^^^^^^^^ attempt to compute `0_u64 - 1_u64`, which would overflow -LL | | ); - | |_______- +LL | const VALS_U64: (u64,) = + | ---------------------- +LL | ( +LL | u64::MIN - 1, + | ^^^^^^^^^^^^ attempt to compute `0_u64 - 1_u64`, which would overflow | note: the lint level is defined here --> $DIR/const-eval-overflow2.rs:8:9 diff --git a/src/test/ui/consts/const-eval/const-eval-overflow2b.stderr b/src/test/ui/consts/const-eval/const-eval-overflow2b.stderr index 5db6a49a98b..5fe9917437e 100644 --- a/src/test/ui/consts/const-eval/const-eval-overflow2b.stderr +++ b/src/test/ui/consts/const-eval/const-eval-overflow2b.stderr @@ -1,12 +1,11 @@ error: any use of this value will cause an error --> $DIR/const-eval-overflow2b.rs:14:6 | -LL | / const VALS_I8: (i8,) = -LL | | ( -LL | | i8::MAX + 1, - | | ^^^^^^^^^^^ attempt to compute `i8::MAX + 1_i8`, which would overflow -LL | | ); - | |_______- +LL | const VALS_I8: (i8,) = + | -------------------- +LL | ( +LL | i8::MAX + 1, + | ^^^^^^^^^^^ attempt to compute `i8::MAX + 1_i8`, which would overflow | note: the lint level is defined here --> $DIR/const-eval-overflow2b.rs:8:9 @@ -19,12 +18,11 @@ LL | #![deny(const_err)] error: any use of this value will cause an error --> $DIR/const-eval-overflow2b.rs:21:6 | -LL | / const VALS_I16: (i16,) = -LL | | ( -LL | | i16::MAX + 1, - | | ^^^^^^^^^^^^ attempt to compute `i16::MAX + 1_i16`, which would overflow -LL | | ); - | |_______- +LL | const VALS_I16: (i16,) = + | ---------------------- +LL | ( +LL | i16::MAX + 1, + | ^^^^^^^^^^^^ attempt to compute `i16::MAX + 1_i16`, which would overflow | = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release! = note: for more information, see issue #71800 <https://github.com/rust-lang/rust/issues/71800> @@ -32,12 +30,11 @@ LL | | ); error: any use of this value will cause an error --> $DIR/const-eval-overflow2b.rs:28:6 | -LL | / const VALS_I32: (i32,) = -LL | | ( -LL | | i32::MAX + 1, - | | ^^^^^^^^^^^^ attempt to compute `i32::MAX + 1_i32`, which would overflow -LL | | ); - | |_______- +LL | const VALS_I32: (i32,) = + | ---------------------- +LL | ( +LL | i32::MAX + 1, + | ^^^^^^^^^^^^ attempt to compute `i32::MAX + 1_i32`, which would overflow | = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release! = note: for more information, see issue #71800 <https://github.com/rust-lang/rust/issues/71800> @@ -45,12 +42,11 @@ LL | | ); error: any use of this value will cause an error --> $DIR/const-eval-overflow2b.rs:35:6 | -LL | / const VALS_I64: (i64,) = -LL | | ( -LL | | i64::MAX + 1, - | | ^^^^^^^^^^^^ attempt to compute `i64::MAX + 1_i64`, which would overflow -LL | | ); - | |_______- +LL | const VALS_I64: (i64,) = + | ---------------------- +LL | ( +LL | i64::MAX + 1, + | ^^^^^^^^^^^^ attempt to compute `i64::MAX + 1_i64`, which would overflow | = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release! = note: for more information, see issue #71800 <https://github.com/rust-lang/rust/issues/71800> @@ -58,12 +54,11 @@ LL | | ); error: any use of this value will cause an error --> $DIR/const-eval-overflow2b.rs:42:6 | -LL | / const VALS_U8: (u8,) = -LL | | ( -LL | | u8::MAX + 1, - | | ^^^^^^^^^^^ attempt to compute `u8::MAX + 1_u8`, which would overflow -LL | | ); - | |_______- +LL | const VALS_U8: (u8,) = + | -------------------- +LL | ( +LL | u8::MAX + 1, + | ^^^^^^^^^^^ attempt to compute `u8::MAX + 1_u8`, which would overflow | = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release! = note: for more information, see issue #71800 <https://github.com/rust-lang/rust/issues/71800> @@ -71,11 +66,10 @@ LL | | ); error: any use of this value will cause an error --> $DIR/const-eval-overflow2b.rs:48:6 | -LL | / const VALS_U16: (u16,) = ( -LL | | u16::MAX + 1, - | | ^^^^^^^^^^^^ attempt to compute `u16::MAX + 1_u16`, which would overflow -LL | | ); - | |_______- +LL | const VALS_U16: (u16,) = ( + | ---------------------- +LL | u16::MAX + 1, + | ^^^^^^^^^^^^ attempt to compute `u16::MAX + 1_u16`, which would overflow | = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release! = note: for more information, see issue #71800 <https://github.com/rust-lang/rust/issues/71800> @@ -83,11 +77,10 @@ LL | | ); error: any use of this value will cause an error --> $DIR/const-eval-overflow2b.rs:54:6 | -LL | / const VALS_U32: (u32,) = ( -LL | | u32::MAX + 1, - | | ^^^^^^^^^^^^ attempt to compute `u32::MAX + 1_u32`, which would overflow -LL | | ); - | |_______- +LL | const VALS_U32: (u32,) = ( + | ---------------------- +LL | u32::MAX + 1, + | ^^^^^^^^^^^^ attempt to compute `u32::MAX + 1_u32`, which would overflow | = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release! = note: for more information, see issue #71800 <https://github.com/rust-lang/rust/issues/71800> @@ -95,12 +88,11 @@ LL | | ); error: any use of this value will cause an error --> $DIR/const-eval-overflow2b.rs:61:6 | -LL | / const VALS_U64: (u64,) = -LL | | ( -LL | | u64::MAX + 1, - | | ^^^^^^^^^^^^ attempt to compute `u64::MAX + 1_u64`, which would overflow -LL | | ); - | |_______- +LL | const VALS_U64: (u64,) = + | ---------------------- +LL | ( +LL | u64::MAX + 1, + | ^^^^^^^^^^^^ attempt to compute `u64::MAX + 1_u64`, which would overflow | = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release! = note: for more information, see issue #71800 <https://github.com/rust-lang/rust/issues/71800> @@ -111,12 +103,11 @@ Future incompatibility report: Future breakage diagnostic: error: any use of this value will cause an error --> $DIR/const-eval-overflow2b.rs:14:6 | -LL | / const VALS_I8: (i8,) = -LL | | ( -LL | | i8::MAX + 1, - | | ^^^^^^^^^^^ attempt to compute `i8::MAX + 1_i8`, which would overflow -LL | | ); - | |_______- +LL | const VALS_I8: (i8,) = + | -------------------- +LL | ( +LL | i8::MAX + 1, + | ^^^^^^^^^^^ attempt to compute `i8::MAX + 1_i8`, which would overflow | note: the lint level is defined here --> $DIR/const-eval-overflow2b.rs:8:9 @@ -130,12 +121,11 @@ Future breakage diagnostic: error: any use of this value will cause an error --> $DIR/const-eval-overflow2b.rs:21:6 | -LL | / const VALS_I16: (i16,) = -LL | | ( -LL | | i16::MAX + 1, - | | ^^^^^^^^^^^^ attempt to compute `i16::MAX + 1_i16`, which would overflow -LL | | ); - | |_______- +LL | const VALS_I16: (i16,) = + | ---------------------- +LL | ( +LL | i16::MAX + 1, + | ^^^^^^^^^^^^ attempt to compute `i16::MAX + 1_i16`, which would overflow | note: the lint level is defined here --> $DIR/const-eval-overflow2b.rs:8:9 @@ -149,12 +139,11 @@ Future breakage diagnostic: error: any use of this value will cause an error --> $DIR/const-eval-overflow2b.rs:28:6 | -LL | / const VALS_I32: (i32,) = -LL | | ( -LL | | i32::MAX + 1, - | | ^^^^^^^^^^^^ attempt to compute `i32::MAX + 1_i32`, which would overflow -LL | | ); - | |_______- +LL | const VALS_I32: (i32,) = + | ---------------------- +LL | ( +LL | i32::MAX + 1, + | ^^^^^^^^^^^^ attempt to compute `i32::MAX + 1_i32`, which would overflow | note: the lint level is defined here --> $DIR/const-eval-overflow2b.rs:8:9 @@ -168,12 +157,11 @@ Future breakage diagnostic: error: any use of this value will cause an error --> $DIR/const-eval-overflow2b.rs:35:6 | -LL | / const VALS_I64: (i64,) = -LL | | ( -LL | | i64::MAX + 1, - | | ^^^^^^^^^^^^ attempt to compute `i64::MAX + 1_i64`, which would overflow -LL | | ); - | |_______- +LL | const VALS_I64: (i64,) = + | ---------------------- +LL | ( +LL | i64::MAX + 1, + | ^^^^^^^^^^^^ attempt to compute `i64::MAX + 1_i64`, which would overflow | note: the lint level is defined here --> $DIR/const-eval-overflow2b.rs:8:9 @@ -187,12 +175,11 @@ Future breakage diagnostic: error: any use of this value will cause an error --> $DIR/const-eval-overflow2b.rs:42:6 | -LL | / const VALS_U8: (u8,) = -LL | | ( -LL | | u8::MAX + 1, - | | ^^^^^^^^^^^ attempt to compute `u8::MAX + 1_u8`, which would overflow -LL | | ); - | |_______- +LL | const VALS_U8: (u8,) = + | -------------------- +LL | ( +LL | u8::MAX + 1, + | ^^^^^^^^^^^ attempt to compute `u8::MAX + 1_u8`, which would overflow | note: the lint level is defined here --> $DIR/const-eval-overflow2b.rs:8:9 @@ -206,11 +193,10 @@ Future breakage diagnostic: error: any use of this value will cause an error --> $DIR/const-eval-overflow2b.rs:48:6 | -LL | / const VALS_U16: (u16,) = ( -LL | | u16::MAX + 1, - | | ^^^^^^^^^^^^ attempt to compute `u16::MAX + 1_u16`, which would overflow -LL | | ); - | |_______- +LL | const VALS_U16: (u16,) = ( + | ---------------------- +LL | u16::MAX + 1, + | ^^^^^^^^^^^^ attempt to compute `u16::MAX + 1_u16`, which would overflow | note: the lint level is defined here --> $DIR/const-eval-overflow2b.rs:8:9 @@ -224,11 +210,10 @@ Future breakage diagnostic: error: any use of this value will cause an error --> $DIR/const-eval-overflow2b.rs:54:6 | -LL | / const VALS_U32: (u32,) = ( -LL | | u32::MAX + 1, - | | ^^^^^^^^^^^^ attempt to compute `u32::MAX + 1_u32`, which would overflow -LL | | ); - | |_______- +LL | const VALS_U32: (u32,) = ( + | ---------------------- +LL | u32::MAX + 1, + | ^^^^^^^^^^^^ attempt to compute `u32::MAX + 1_u32`, which would overflow | note: the lint level is defined here --> $DIR/const-eval-overflow2b.rs:8:9 @@ -242,12 +227,11 @@ Future breakage diagnostic: error: any use of this value will cause an error --> $DIR/const-eval-overflow2b.rs:61:6 | -LL | / const VALS_U64: (u64,) = -LL | | ( -LL | | u64::MAX + 1, - | | ^^^^^^^^^^^^ attempt to compute `u64::MAX + 1_u64`, which would overflow -LL | | ); - | |_______- +LL | const VALS_U64: (u64,) = + | ---------------------- +LL | ( +LL | u64::MAX + 1, + | ^^^^^^^^^^^^ attempt to compute `u64::MAX + 1_u64`, which would overflow | note: the lint level is defined here --> $DIR/const-eval-overflow2b.rs:8:9 diff --git a/src/test/ui/consts/const-eval/const-eval-overflow2c.stderr b/src/test/ui/consts/const-eval/const-eval-overflow2c.stderr index ec3f3c11059..d5f3a0fb1c3 100644 --- a/src/test/ui/consts/const-eval/const-eval-overflow2c.stderr +++ b/src/test/ui/consts/const-eval/const-eval-overflow2c.stderr @@ -1,12 +1,11 @@ error: any use of this value will cause an error --> $DIR/const-eval-overflow2c.rs:14:6 | -LL | / const VALS_I8: (i8,) = -LL | | ( -LL | | i8::MIN * 2, - | | ^^^^^^^^^^^ attempt to compute `i8::MIN * 2_i8`, which would overflow -LL | | ); - | |_______- +LL | const VALS_I8: (i8,) = + | -------------------- +LL | ( +LL | i8::MIN * 2, + | ^^^^^^^^^^^ attempt to compute `i8::MIN * 2_i8`, which would overflow | note: the lint level is defined here --> $DIR/const-eval-overflow2c.rs:8:9 @@ -19,12 +18,11 @@ LL | #![deny(const_err)] error: any use of this value will cause an error --> $DIR/const-eval-overflow2c.rs:21:6 | -LL | / const VALS_I16: (i16,) = -LL | | ( -LL | | i16::MIN * 2, - | | ^^^^^^^^^^^^ attempt to compute `i16::MIN * 2_i16`, which would overflow -LL | | ); - | |_______- +LL | const VALS_I16: (i16,) = + | ---------------------- +LL | ( +LL | i16::MIN * 2, + | ^^^^^^^^^^^^ attempt to compute `i16::MIN * 2_i16`, which would overflow | = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release! = note: for more information, see issue #71800 <https://github.com/rust-lang/rust/issues/71800> @@ -32,12 +30,11 @@ LL | | ); error: any use of this value will cause an error --> $DIR/const-eval-overflow2c.rs:28:6 | -LL | / const VALS_I32: (i32,) = -LL | | ( -LL | | i32::MIN * 2, - | | ^^^^^^^^^^^^ attempt to compute `i32::MIN * 2_i32`, which would overflow -LL | | ); - | |_______- +LL | const VALS_I32: (i32,) = + | ---------------------- +LL | ( +LL | i32::MIN * 2, + | ^^^^^^^^^^^^ attempt to compute `i32::MIN * 2_i32`, which would overflow | = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release! = note: for more information, see issue #71800 <https://github.com/rust-lang/rust/issues/71800> @@ -45,12 +42,11 @@ LL | | ); error: any use of this value will cause an error --> $DIR/const-eval-overflow2c.rs:35:6 | -LL | / const VALS_I64: (i64,) = -LL | | ( -LL | | i64::MIN * 2, - | | ^^^^^^^^^^^^ attempt to compute `i64::MIN * 2_i64`, which would overflow -LL | | ); - | |_______- +LL | const VALS_I64: (i64,) = + | ---------------------- +LL | ( +LL | i64::MIN * 2, + | ^^^^^^^^^^^^ attempt to compute `i64::MIN * 2_i64`, which would overflow | = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release! = note: for more information, see issue #71800 <https://github.com/rust-lang/rust/issues/71800> @@ -58,12 +54,11 @@ LL | | ); error: any use of this value will cause an error --> $DIR/const-eval-overflow2c.rs:42:6 | -LL | / const VALS_U8: (u8,) = -LL | | ( -LL | | u8::MAX * 2, - | | ^^^^^^^^^^^ attempt to compute `u8::MAX * 2_u8`, which would overflow -LL | | ); - | |_______- +LL | const VALS_U8: (u8,) = + | -------------------- +LL | ( +LL | u8::MAX * 2, + | ^^^^^^^^^^^ attempt to compute `u8::MAX * 2_u8`, which would overflow | = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release! = note: for more information, see issue #71800 <https://github.com/rust-lang/rust/issues/71800> @@ -71,11 +66,10 @@ LL | | ); error: any use of this value will cause an error --> $DIR/const-eval-overflow2c.rs:48:6 | -LL | / const VALS_U16: (u16,) = ( -LL | | u16::MAX * 2, - | | ^^^^^^^^^^^^ attempt to compute `u16::MAX * 2_u16`, which would overflow -LL | | ); - | |_______- +LL | const VALS_U16: (u16,) = ( + | ---------------------- +LL | u16::MAX * 2, + | ^^^^^^^^^^^^ attempt to compute `u16::MAX * 2_u16`, which would overflow | = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release! = note: for more information, see issue #71800 <https://github.com/rust-lang/rust/issues/71800> @@ -83,11 +77,10 @@ LL | | ); error: any use of this value will cause an error --> $DIR/const-eval-overflow2c.rs:54:6 | -LL | / const VALS_U32: (u32,) = ( -LL | | u32::MAX * 2, - | | ^^^^^^^^^^^^ attempt to compute `u32::MAX * 2_u32`, which would overflow -LL | | ); - | |_______- +LL | const VALS_U32: (u32,) = ( + | ---------------------- +LL | u32::MAX * 2, + | ^^^^^^^^^^^^ attempt to compute `u32::MAX * 2_u32`, which would overflow | = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release! = note: for more information, see issue #71800 <https://github.com/rust-lang/rust/issues/71800> @@ -95,12 +88,11 @@ LL | | ); error: any use of this value will cause an error --> $DIR/const-eval-overflow2c.rs:61:6 | -LL | / const VALS_U64: (u64,) = -LL | | ( -LL | | u64::MAX * 2, - | | ^^^^^^^^^^^^ attempt to compute `u64::MAX * 2_u64`, which would overflow -LL | | ); - | |_______- +LL | const VALS_U64: (u64,) = + | ---------------------- +LL | ( +LL | u64::MAX * 2, + | ^^^^^^^^^^^^ attempt to compute `u64::MAX * 2_u64`, which would overflow | = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release! = note: for more information, see issue #71800 <https://github.com/rust-lang/rust/issues/71800> @@ -111,12 +103,11 @@ Future incompatibility report: Future breakage diagnostic: error: any use of this value will cause an error --> $DIR/const-eval-overflow2c.rs:14:6 | -LL | / const VALS_I8: (i8,) = -LL | | ( -LL | | i8::MIN * 2, - | | ^^^^^^^^^^^ attempt to compute `i8::MIN * 2_i8`, which would overflow -LL | | ); - | |_______- +LL | const VALS_I8: (i8,) = + | -------------------- +LL | ( +LL | i8::MIN * 2, + | ^^^^^^^^^^^ attempt to compute `i8::MIN * 2_i8`, which would overflow | note: the lint level is defined here --> $DIR/const-eval-overflow2c.rs:8:9 @@ -130,12 +121,11 @@ Future breakage diagnostic: error: any use of this value will cause an error --> $DIR/const-eval-overflow2c.rs:21:6 | -LL | / const VALS_I16: (i16,) = -LL | | ( -LL | | i16::MIN * 2, - | | ^^^^^^^^^^^^ attempt to compute `i16::MIN * 2_i16`, which would overflow -LL | | ); - | |_______- +LL | const VALS_I16: (i16,) = + | ---------------------- +LL | ( +LL | i16::MIN * 2, + | ^^^^^^^^^^^^ attempt to compute `i16::MIN * 2_i16`, which would overflow | note: the lint level is defined here --> $DIR/const-eval-overflow2c.rs:8:9 @@ -149,12 +139,11 @@ Future breakage diagnostic: error: any use of this value will cause an error --> $DIR/const-eval-overflow2c.rs:28:6 | -LL | / const VALS_I32: (i32,) = -LL | | ( -LL | | i32::MIN * 2, - | | ^^^^^^^^^^^^ attempt to compute `i32::MIN * 2_i32`, which would overflow -LL | | ); - | |_______- +LL | const VALS_I32: (i32,) = + | ---------------------- +LL | ( +LL | i32::MIN * 2, + | ^^^^^^^^^^^^ attempt to compute `i32::MIN * 2_i32`, which would overflow | note: the lint level is defined here --> $DIR/const-eval-overflow2c.rs:8:9 @@ -168,12 +157,11 @@ Future breakage diagnostic: error: any use of this value will cause an error --> $DIR/const-eval-overflow2c.rs:35:6 | -LL | / const VALS_I64: (i64,) = -LL | | ( -LL | | i64::MIN * 2, - | | ^^^^^^^^^^^^ attempt to compute `i64::MIN * 2_i64`, which would overflow -LL | | ); - | |_______- +LL | const VALS_I64: (i64,) = + | ---------------------- +LL | ( +LL | i64::MIN * 2, + | ^^^^^^^^^^^^ attempt to compute `i64::MIN * 2_i64`, which would overflow | note: the lint level is defined here --> $DIR/const-eval-overflow2c.rs:8:9 @@ -187,12 +175,11 @@ Future breakage diagnostic: error: any use of this value will cause an error --> $DIR/const-eval-overflow2c.rs:42:6 | -LL | / const VALS_U8: (u8,) = -LL | | ( -LL | | u8::MAX * 2, - | | ^^^^^^^^^^^ attempt to compute `u8::MAX * 2_u8`, which would overflow -LL | | ); - | |_______- +LL | const VALS_U8: (u8,) = + | -------------------- +LL | ( +LL | u8::MAX * 2, + | ^^^^^^^^^^^ attempt to compute `u8::MAX * 2_u8`, which would overflow | note: the lint level is defined here --> $DIR/const-eval-overflow2c.rs:8:9 @@ -206,11 +193,10 @@ Future breakage diagnostic: error: any use of this value will cause an error --> $DIR/const-eval-overflow2c.rs:48:6 | -LL | / const VALS_U16: (u16,) = ( -LL | | u16::MAX * 2, - | | ^^^^^^^^^^^^ attempt to compute `u16::MAX * 2_u16`, which would overflow -LL | | ); - | |_______- +LL | const VALS_U16: (u16,) = ( + | ---------------------- +LL | u16::MAX * 2, + | ^^^^^^^^^^^^ attempt to compute `u16::MAX * 2_u16`, which would overflow | note: the lint level is defined here --> $DIR/const-eval-overflow2c.rs:8:9 @@ -224,11 +210,10 @@ Future breakage diagnostic: error: any use of this value will cause an error --> $DIR/const-eval-overflow2c.rs:54:6 | -LL | / const VALS_U32: (u32,) = ( -LL | | u32::MAX * 2, - | | ^^^^^^^^^^^^ attempt to compute `u32::MAX * 2_u32`, which would overflow -LL | | ); - | |_______- +LL | const VALS_U32: (u32,) = ( + | ---------------------- +LL | u32::MAX * 2, + | ^^^^^^^^^^^^ attempt to compute `u32::MAX * 2_u32`, which would overflow | note: the lint level is defined here --> $DIR/const-eval-overflow2c.rs:8:9 @@ -242,12 +227,11 @@ Future breakage diagnostic: error: any use of this value will cause an error --> $DIR/const-eval-overflow2c.rs:61:6 | -LL | / const VALS_U64: (u64,) = -LL | | ( -LL | | u64::MAX * 2, - | | ^^^^^^^^^^^^ attempt to compute `u64::MAX * 2_u64`, which would overflow -LL | | ); - | |_______- +LL | const VALS_U64: (u64,) = + | ---------------------- +LL | ( +LL | u64::MAX * 2, + | ^^^^^^^^^^^^ attempt to compute `u64::MAX * 2_u64`, which would overflow | note: the lint level is defined here --> $DIR/const-eval-overflow2c.rs:8:9 diff --git a/src/test/ui/consts/const-eval/const-eval-query-stack.stderr b/src/test/ui/consts/const-eval/const-eval-query-stack.stderr index bbec2a830e6..0ae7bfa86bc 100644 --- a/src/test/ui/consts/const-eval/const-eval-query-stack.stderr +++ b/src/test/ui/consts/const-eval/const-eval-query-stack.stderr @@ -2,9 +2,7 @@ warning: any use of this value will cause an error --> $DIR/const-eval-query-stack.rs:19:16 | LL | const X: i32 = 1 / 0; - | ---------------^^^^^- - | | - | attempt to divide `1_i32` by zero + | ------------ ^^^^^ attempt to divide `1_i32` by zero | note: the lint level is defined here --> $DIR/const-eval-query-stack.rs:18:8 @@ -40,9 +38,7 @@ warning: any use of this value will cause an error --> $DIR/const-eval-query-stack.rs:19:16 | LL | const X: i32 = 1 / 0; - | ---------------^^^^^- - | | - | attempt to divide `1_i32` by zero + | ------------ ^^^^^ attempt to divide `1_i32` by zero | note: the lint level is defined here --> $DIR/const-eval-query-stack.rs:18:8 diff --git a/src/test/ui/consts/const-eval/const-pointer-values-in-various-types.64bit.stderr b/src/test/ui/consts/const-eval/const-pointer-values-in-various-types.64bit.stderr index 8cbc6a399af..655a7d52054 100644 --- a/src/test/ui/consts/const-eval/const-pointer-values-in-various-types.64bit.stderr +++ b/src/test/ui/consts/const-eval/const-pointer-values-in-various-types.64bit.stderr @@ -2,9 +2,7 @@ error: any use of this value will cause an error --> $DIR/const-pointer-values-in-various-types.rs:26:49 | LL | const I32_REF_USIZE_UNION: usize = unsafe { Nonsense { int_32_ref: &3 }.u }; - | --------------------------------------------^^^^^^^^^^^^^^^^^^^^^^^^^^^^^--- - | | - | unable to turn pointer into raw bytes + | -------------------------------- ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ unable to turn pointer into raw bytes | = note: `#[deny(const_err)]` on by default = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release! @@ -14,9 +12,7 @@ error: any use of this value will cause an error --> $DIR/const-pointer-values-in-various-types.rs:30:43 | LL | const I32_REF_U8_UNION: u8 = unsafe { Nonsense { int_32_ref: &3 }.uint_8 }; - | --------------------------------------^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^--- - | | - | unable to turn pointer into raw bytes + | -------------------------- ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ unable to turn pointer into raw bytes | = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release! = note: for more information, see issue #71800 <https://github.com/rust-lang/rust/issues/71800> @@ -25,9 +21,7 @@ error: any use of this value will cause an error --> $DIR/const-pointer-values-in-various-types.rs:34:45 | LL | const I32_REF_U16_UNION: u16 = unsafe { Nonsense { int_32_ref: &3 }.uint_16 }; - | ----------------------------------------^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^--- - | | - | unable to turn pointer into raw bytes + | ---------------------------- ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ unable to turn pointer into raw bytes | = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release! = note: for more information, see issue #71800 <https://github.com/rust-lang/rust/issues/71800> @@ -36,9 +30,7 @@ error: any use of this value will cause an error --> $DIR/const-pointer-values-in-various-types.rs:38:45 | LL | const I32_REF_U32_UNION: u32 = unsafe { Nonsense { int_32_ref: &3 }.uint_32 }; - | ----------------------------------------^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^--- - | | - | unable to turn pointer into raw bytes + | ---------------------------- ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ unable to turn pointer into raw bytes | = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release! = note: for more information, see issue #71800 <https://github.com/rust-lang/rust/issues/71800> @@ -47,9 +39,7 @@ error: any use of this value will cause an error --> $DIR/const-pointer-values-in-various-types.rs:42:45 | LL | const I32_REF_U64_UNION: u64 = unsafe { Nonsense { int_32_ref: &3 }.uint_64 }; - | ----------------------------------------^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^--- - | | - | unable to turn pointer into raw bytes + | ---------------------------- ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ unable to turn pointer into raw bytes | = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release! = note: for more information, see issue #71800 <https://github.com/rust-lang/rust/issues/71800> @@ -58,7 +48,7 @@ error[E0080]: it is undefined behavior to use this value --> $DIR/const-pointer-values-in-various-types.rs:46:5 | LL | const I32_REF_U128_UNION: u128 = unsafe { Nonsense { int_32_ref: &3 }.uint_128 }; - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ constructing invalid value: encountered uninitialized bytes, but expected initialized bytes + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ constructing invalid value: encountered uninitialized bytes, but expected initialized bytes | = note: The rules on what exactly is undefined behavior aren't clear, so this check might be overzealous. Please open an issue on the rustc repository if you believe it should not be considered undefined behavior. = note: the raw bytes of the constant (size: 16, align: 8) { @@ -69,9 +59,7 @@ error: any use of this value will cause an error --> $DIR/const-pointer-values-in-various-types.rs:49:43 | LL | const I32_REF_I8_UNION: i8 = unsafe { Nonsense { int_32_ref: &3 }.int_8 }; - | --------------------------------------^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^--- - | | - | unable to turn pointer into raw bytes + | -------------------------- ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ unable to turn pointer into raw bytes | = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release! = note: for more information, see issue #71800 <https://github.com/rust-lang/rust/issues/71800> @@ -80,9 +68,7 @@ error: any use of this value will cause an error --> $DIR/const-pointer-values-in-various-types.rs:53:45 | LL | const I32_REF_I16_UNION: i16 = unsafe { Nonsense { int_32_ref: &3 }.int_16 }; - | ----------------------------------------^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^--- - | | - | unable to turn pointer into raw bytes + | ---------------------------- ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ unable to turn pointer into raw bytes | = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release! = note: for more information, see issue #71800 <https://github.com/rust-lang/rust/issues/71800> @@ -91,9 +77,7 @@ error: any use of this value will cause an error --> $DIR/const-pointer-values-in-various-types.rs:57:45 | LL | const I32_REF_I32_UNION: i32 = unsafe { Nonsense { int_32_ref: &3 }.int_32 }; - | ----------------------------------------^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^--- - | | - | unable to turn pointer into raw bytes + | ---------------------------- ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ unable to turn pointer into raw bytes | = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release! = note: for more information, see issue #71800 <https://github.com/rust-lang/rust/issues/71800> @@ -102,9 +86,7 @@ error: any use of this value will cause an error --> $DIR/const-pointer-values-in-various-types.rs:61:45 | LL | const I32_REF_I64_UNION: i64 = unsafe { Nonsense { int_32_ref: &3 }.int_64 }; - | ----------------------------------------^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^--- - | | - | unable to turn pointer into raw bytes + | ---------------------------- ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ unable to turn pointer into raw bytes | = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release! = note: for more information, see issue #71800 <https://github.com/rust-lang/rust/issues/71800> @@ -113,7 +95,7 @@ error[E0080]: it is undefined behavior to use this value --> $DIR/const-pointer-values-in-various-types.rs:65:5 | LL | const I32_REF_I128_UNION: i128 = unsafe { Nonsense { int_32_ref: &3 }.int_128 }; - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ constructing invalid value: encountered uninitialized bytes, but expected initialized bytes + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ constructing invalid value: encountered uninitialized bytes, but expected initialized bytes | = note: The rules on what exactly is undefined behavior aren't clear, so this check might be overzealous. Please open an issue on the rustc repository if you believe it should not be considered undefined behavior. = note: the raw bytes of the constant (size: 16, align: 8) { @@ -124,9 +106,7 @@ error: any use of this value will cause an error --> $DIR/const-pointer-values-in-various-types.rs:68:45 | LL | const I32_REF_F32_UNION: f32 = unsafe { Nonsense { int_32_ref: &3 }.float_32 }; - | ----------------------------------------^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^--- - | | - | unable to turn pointer into raw bytes + | ---------------------------- ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ unable to turn pointer into raw bytes | = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release! = note: for more information, see issue #71800 <https://github.com/rust-lang/rust/issues/71800> @@ -135,9 +115,7 @@ error: any use of this value will cause an error --> $DIR/const-pointer-values-in-various-types.rs:72:45 | LL | const I32_REF_F64_UNION: f64 = unsafe { Nonsense { int_32_ref: &3 }.float_64 }; - | ----------------------------------------^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^--- - | | - | unable to turn pointer into raw bytes + | ---------------------------- ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ unable to turn pointer into raw bytes | = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release! = note: for more information, see issue #71800 <https://github.com/rust-lang/rust/issues/71800> @@ -146,9 +124,7 @@ error: any use of this value will cause an error --> $DIR/const-pointer-values-in-various-types.rs:76:47 | LL | const I32_REF_BOOL_UNION: bool = unsafe { Nonsense { int_32_ref: &3 }.truthy_falsey }; - | ------------------------------------------^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^--- - | | - | unable to turn pointer into raw bytes + | ------------------------------ ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ unable to turn pointer into raw bytes | = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release! = note: for more information, see issue #71800 <https://github.com/rust-lang/rust/issues/71800> @@ -157,9 +133,7 @@ error: any use of this value will cause an error --> $DIR/const-pointer-values-in-various-types.rs:80:47 | LL | const I32_REF_CHAR_UNION: char = unsafe { Nonsense { int_32_ref: &3 }.character }; - | ------------------------------------------^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^--- - | | - | unable to turn pointer into raw bytes + | ------------------------------ ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ unable to turn pointer into raw bytes | = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release! = note: for more information, see issue #71800 <https://github.com/rust-lang/rust/issues/71800> @@ -168,9 +142,7 @@ error: any use of this value will cause an error --> $DIR/const-pointer-values-in-various-types.rs:84:39 | LL | const STR_U8_UNION: u8 = unsafe { Nonsense { stringy: "3" }.uint_8 }; - | ----------------------------------^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^--- - | | - | unable to turn pointer into raw bytes + | ---------------------- ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ unable to turn pointer into raw bytes | = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release! = note: for more information, see issue #71800 <https://github.com/rust-lang/rust/issues/71800> @@ -179,9 +151,7 @@ error: any use of this value will cause an error --> $DIR/const-pointer-values-in-various-types.rs:88:41 | LL | const STR_U16_UNION: u16 = unsafe { Nonsense { stringy: "3" }.uint_16 }; - | ------------------------------------^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^--- - | | - | unable to turn pointer into raw bytes + | ------------------------ ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ unable to turn pointer into raw bytes | = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release! = note: for more information, see issue #71800 <https://github.com/rust-lang/rust/issues/71800> @@ -190,9 +160,7 @@ error: any use of this value will cause an error --> $DIR/const-pointer-values-in-various-types.rs:92:41 | LL | const STR_U32_UNION: u32 = unsafe { Nonsense { stringy: "3" }.uint_32 }; - | ------------------------------------^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^--- - | | - | unable to turn pointer into raw bytes + | ------------------------ ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ unable to turn pointer into raw bytes | = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release! = note: for more information, see issue #71800 <https://github.com/rust-lang/rust/issues/71800> @@ -201,9 +169,7 @@ error: any use of this value will cause an error --> $DIR/const-pointer-values-in-various-types.rs:96:41 | LL | const STR_U64_UNION: u64 = unsafe { Nonsense { stringy: "3" }.uint_64 }; - | ------------------------------------^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^--- - | | - | unable to turn pointer into raw bytes + | ------------------------ ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ unable to turn pointer into raw bytes | = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release! = note: for more information, see issue #71800 <https://github.com/rust-lang/rust/issues/71800> @@ -212,9 +178,7 @@ error: any use of this value will cause an error --> $DIR/const-pointer-values-in-various-types.rs:100:43 | LL | const STR_U128_UNION: u128 = unsafe { Nonsense { stringy: "3" }.uint_128 }; - | --------------------------------------^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^--- - | | - | unable to turn pointer into raw bytes + | -------------------------- ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ unable to turn pointer into raw bytes | = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release! = note: for more information, see issue #71800 <https://github.com/rust-lang/rust/issues/71800> @@ -223,9 +187,7 @@ error: any use of this value will cause an error --> $DIR/const-pointer-values-in-various-types.rs:104:39 | LL | const STR_I8_UNION: i8 = unsafe { Nonsense { stringy: "3" }.int_8 }; - | ----------------------------------^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^--- - | | - | unable to turn pointer into raw bytes + | ---------------------- ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ unable to turn pointer into raw bytes | = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release! = note: for more information, see issue #71800 <https://github.com/rust-lang/rust/issues/71800> @@ -234,9 +196,7 @@ error: any use of this value will cause an error --> $DIR/const-pointer-values-in-various-types.rs:108:41 | LL | const STR_I16_UNION: i16 = unsafe { Nonsense { stringy: "3" }.int_16 }; - | ------------------------------------^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^--- - | | - | unable to turn pointer into raw bytes + | ------------------------ ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ unable to turn pointer into raw bytes | = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release! = note: for more information, see issue #71800 <https://github.com/rust-lang/rust/issues/71800> @@ -245,9 +205,7 @@ error: any use of this value will cause an error --> $DIR/const-pointer-values-in-various-types.rs:112:41 | LL | const STR_I32_UNION: i32 = unsafe { Nonsense { stringy: "3" }.int_32 }; - | ------------------------------------^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^--- - | | - | unable to turn pointer into raw bytes + | ------------------------ ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ unable to turn pointer into raw bytes | = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release! = note: for more information, see issue #71800 <https://github.com/rust-lang/rust/issues/71800> @@ -256,9 +214,7 @@ error: any use of this value will cause an error --> $DIR/const-pointer-values-in-various-types.rs:116:41 | LL | const STR_I64_UNION: i64 = unsafe { Nonsense { stringy: "3" }.int_64 }; - | ------------------------------------^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^--- - | | - | unable to turn pointer into raw bytes + | ------------------------ ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ unable to turn pointer into raw bytes | = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release! = note: for more information, see issue #71800 <https://github.com/rust-lang/rust/issues/71800> @@ -267,9 +223,7 @@ error: any use of this value will cause an error --> $DIR/const-pointer-values-in-various-types.rs:120:43 | LL | const STR_I128_UNION: i128 = unsafe { Nonsense { stringy: "3" }.int_128 }; - | --------------------------------------^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^--- - | | - | unable to turn pointer into raw bytes + | -------------------------- ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ unable to turn pointer into raw bytes | = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release! = note: for more information, see issue #71800 <https://github.com/rust-lang/rust/issues/71800> @@ -278,9 +232,7 @@ error: any use of this value will cause an error --> $DIR/const-pointer-values-in-various-types.rs:124:41 | LL | const STR_F32_UNION: f32 = unsafe { Nonsense { stringy: "3" }.float_32 }; - | ------------------------------------^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^--- - | | - | unable to turn pointer into raw bytes + | ------------------------ ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ unable to turn pointer into raw bytes | = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release! = note: for more information, see issue #71800 <https://github.com/rust-lang/rust/issues/71800> @@ -289,9 +241,7 @@ error: any use of this value will cause an error --> $DIR/const-pointer-values-in-various-types.rs:128:41 | LL | const STR_F64_UNION: f64 = unsafe { Nonsense { stringy: "3" }.float_64 }; - | ------------------------------------^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^--- - | | - | unable to turn pointer into raw bytes + | ------------------------ ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ unable to turn pointer into raw bytes | = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release! = note: for more information, see issue #71800 <https://github.com/rust-lang/rust/issues/71800> @@ -300,9 +250,7 @@ error: any use of this value will cause an error --> $DIR/const-pointer-values-in-various-types.rs:132:43 | LL | const STR_BOOL_UNION: bool = unsafe { Nonsense { stringy: "3" }.truthy_falsey }; - | --------------------------------------^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^--- - | | - | unable to turn pointer into raw bytes + | -------------------------- ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ unable to turn pointer into raw bytes | = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release! = note: for more information, see issue #71800 <https://github.com/rust-lang/rust/issues/71800> @@ -311,9 +259,7 @@ error: any use of this value will cause an error --> $DIR/const-pointer-values-in-various-types.rs:136:43 | LL | const STR_CHAR_UNION: char = unsafe { Nonsense { stringy: "3" }.character }; - | --------------------------------------^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^--- - | | - | unable to turn pointer into raw bytes + | -------------------------- ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ unable to turn pointer into raw bytes | = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release! = note: for more information, see issue #71800 <https://github.com/rust-lang/rust/issues/71800> @@ -326,9 +272,7 @@ error: any use of this value will cause an error --> $DIR/const-pointer-values-in-various-types.rs:26:49 | LL | const I32_REF_USIZE_UNION: usize = unsafe { Nonsense { int_32_ref: &3 }.u }; - | --------------------------------------------^^^^^^^^^^^^^^^^^^^^^^^^^^^^^--- - | | - | unable to turn pointer into raw bytes + | -------------------------------- ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ unable to turn pointer into raw bytes | = note: `#[deny(const_err)]` on by default = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release! @@ -339,9 +283,7 @@ error: any use of this value will cause an error --> $DIR/const-pointer-values-in-various-types.rs:30:43 | LL | const I32_REF_U8_UNION: u8 = unsafe { Nonsense { int_32_ref: &3 }.uint_8 }; - | --------------------------------------^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^--- - | | - | unable to turn pointer into raw bytes + | -------------------------- ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ unable to turn pointer into raw bytes | = note: `#[deny(const_err)]` on by default = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release! @@ -352,9 +294,7 @@ error: any use of this value will cause an error --> $DIR/const-pointer-values-in-various-types.rs:34:45 | LL | const I32_REF_U16_UNION: u16 = unsafe { Nonsense { int_32_ref: &3 }.uint_16 }; - | ----------------------------------------^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^--- - | | - | unable to turn pointer into raw bytes + | ---------------------------- ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ unable to turn pointer into raw bytes | = note: `#[deny(const_err)]` on by default = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release! @@ -365,9 +305,7 @@ error: any use of this value will cause an error --> $DIR/const-pointer-values-in-various-types.rs:38:45 | LL | const I32_REF_U32_UNION: u32 = unsafe { Nonsense { int_32_ref: &3 }.uint_32 }; - | ----------------------------------------^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^--- - | | - | unable to turn pointer into raw bytes + | ---------------------------- ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ unable to turn pointer into raw bytes | = note: `#[deny(const_err)]` on by default = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release! @@ -378,9 +316,7 @@ error: any use of this value will cause an error --> $DIR/const-pointer-values-in-various-types.rs:42:45 | LL | const I32_REF_U64_UNION: u64 = unsafe { Nonsense { int_32_ref: &3 }.uint_64 }; - | ----------------------------------------^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^--- - | | - | unable to turn pointer into raw bytes + | ---------------------------- ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ unable to turn pointer into raw bytes | = note: `#[deny(const_err)]` on by default = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release! @@ -391,9 +327,7 @@ error: any use of this value will cause an error --> $DIR/const-pointer-values-in-various-types.rs:49:43 | LL | const I32_REF_I8_UNION: i8 = unsafe { Nonsense { int_32_ref: &3 }.int_8 }; - | --------------------------------------^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^--- - | | - | unable to turn pointer into raw bytes + | -------------------------- ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ unable to turn pointer into raw bytes | = note: `#[deny(const_err)]` on by default = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release! @@ -404,9 +338,7 @@ error: any use of this value will cause an error --> $DIR/const-pointer-values-in-various-types.rs:53:45 | LL | const I32_REF_I16_UNION: i16 = unsafe { Nonsense { int_32_ref: &3 }.int_16 }; - | ----------------------------------------^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^--- - | | - | unable to turn pointer into raw bytes + | ---------------------------- ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ unable to turn pointer into raw bytes | = note: `#[deny(const_err)]` on by default = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release! @@ -417,9 +349,7 @@ error: any use of this value will cause an error --> $DIR/const-pointer-values-in-various-types.rs:57:45 | LL | const I32_REF_I32_UNION: i32 = unsafe { Nonsense { int_32_ref: &3 }.int_32 }; - | ----------------------------------------^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^--- - | | - | unable to turn pointer into raw bytes + | ---------------------------- ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ unable to turn pointer into raw bytes | = note: `#[deny(const_err)]` on by default = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release! @@ -430,9 +360,7 @@ error: any use of this value will cause an error --> $DIR/const-pointer-values-in-various-types.rs:61:45 | LL | const I32_REF_I64_UNION: i64 = unsafe { Nonsense { int_32_ref: &3 }.int_64 }; - | ----------------------------------------^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^--- - | | - | unable to turn pointer into raw bytes + | ---------------------------- ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ unable to turn pointer into raw bytes | = note: `#[deny(const_err)]` on by default = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release! @@ -443,9 +371,7 @@ error: any use of this value will cause an error --> $DIR/const-pointer-values-in-various-types.rs:68:45 | LL | const I32_REF_F32_UNION: f32 = unsafe { Nonsense { int_32_ref: &3 }.float_32 }; - | ----------------------------------------^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^--- - | | - | unable to turn pointer into raw bytes + | ---------------------------- ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ unable to turn pointer into raw bytes | = note: `#[deny(const_err)]` on by default = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release! @@ -456,9 +382,7 @@ error: any use of this value will cause an error --> $DIR/const-pointer-values-in-various-types.rs:72:45 | LL | const I32_REF_F64_UNION: f64 = unsafe { Nonsense { int_32_ref: &3 }.float_64 }; - | ----------------------------------------^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^--- - | | - | unable to turn pointer into raw bytes + | ---------------------------- ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ unable to turn pointer into raw bytes | = note: `#[deny(const_err)]` on by default = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release! @@ -469,9 +393,7 @@ error: any use of this value will cause an error --> $DIR/const-pointer-values-in-various-types.rs:76:47 | LL | const I32_REF_BOOL_UNION: bool = unsafe { Nonsense { int_32_ref: &3 }.truthy_falsey }; - | ------------------------------------------^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^--- - | | - | unable to turn pointer into raw bytes + | ------------------------------ ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ unable to turn pointer into raw bytes | = note: `#[deny(const_err)]` on by default = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release! @@ -482,9 +404,7 @@ error: any use of this value will cause an error --> $DIR/const-pointer-values-in-various-types.rs:80:47 | LL | const I32_REF_CHAR_UNION: char = unsafe { Nonsense { int_32_ref: &3 }.character }; - | ------------------------------------------^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^--- - | | - | unable to turn pointer into raw bytes + | ------------------------------ ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ unable to turn pointer into raw bytes | = note: `#[deny(const_err)]` on by default = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release! @@ -495,9 +415,7 @@ error: any use of this value will cause an error --> $DIR/const-pointer-values-in-various-types.rs:84:39 | LL | const STR_U8_UNION: u8 = unsafe { Nonsense { stringy: "3" }.uint_8 }; - | ----------------------------------^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^--- - | | - | unable to turn pointer into raw bytes + | ---------------------- ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ unable to turn pointer into raw bytes | = note: `#[deny(const_err)]` on by default = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release! @@ -508,9 +426,7 @@ error: any use of this value will cause an error --> $DIR/const-pointer-values-in-various-types.rs:88:41 | LL | const STR_U16_UNION: u16 = unsafe { Nonsense { stringy: "3" }.uint_16 }; - | ------------------------------------^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^--- - | | - | unable to turn pointer into raw bytes + | ------------------------ ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ unable to turn pointer into raw bytes | = note: `#[deny(const_err)]` on by default = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release! @@ -521,9 +437,7 @@ error: any use of this value will cause an error --> $DIR/const-pointer-values-in-various-types.rs:92:41 | LL | const STR_U32_UNION: u32 = unsafe { Nonsense { stringy: "3" }.uint_32 }; - | ------------------------------------^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^--- - | | - | unable to turn pointer into raw bytes + | ------------------------ ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ unable to turn pointer into raw bytes | = note: `#[deny(const_err)]` on by default = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release! @@ -534,9 +448,7 @@ error: any use of this value will cause an error --> $DIR/const-pointer-values-in-various-types.rs:96:41 | LL | const STR_U64_UNION: u64 = unsafe { Nonsense { stringy: "3" }.uint_64 }; - | ------------------------------------^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^--- - | | - | unable to turn pointer into raw bytes + | ------------------------ ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ unable to turn pointer into raw bytes | = note: `#[deny(const_err)]` on by default = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release! @@ -547,9 +459,7 @@ error: any use of this value will cause an error --> $DIR/const-pointer-values-in-various-types.rs:100:43 | LL | const STR_U128_UNION: u128 = unsafe { Nonsense { stringy: "3" }.uint_128 }; - | --------------------------------------^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^--- - | | - | unable to turn pointer into raw bytes + | -------------------------- ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ unable to turn pointer into raw bytes | = note: `#[deny(const_err)]` on by default = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release! @@ -560,9 +470,7 @@ error: any use of this value will cause an error --> $DIR/const-pointer-values-in-various-types.rs:104:39 | LL | const STR_I8_UNION: i8 = unsafe { Nonsense { stringy: "3" }.int_8 }; - | ----------------------------------^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^--- - | | - | unable to turn pointer into raw bytes + | ---------------------- ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ unable to turn pointer into raw bytes | = note: `#[deny(const_err)]` on by default = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release! @@ -573,9 +481,7 @@ error: any use of this value will cause an error --> $DIR/const-pointer-values-in-various-types.rs:108:41 | LL | const STR_I16_UNION: i16 = unsafe { Nonsense { stringy: "3" }.int_16 }; - | ------------------------------------^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^--- - | | - | unable to turn pointer into raw bytes + | ------------------------ ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ unable to turn pointer into raw bytes | = note: `#[deny(const_err)]` on by default = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release! @@ -586,9 +492,7 @@ error: any use of this value will cause an error --> $DIR/const-pointer-values-in-various-types.rs:112:41 | LL | const STR_I32_UNION: i32 = unsafe { Nonsense { stringy: "3" }.int_32 }; - | ------------------------------------^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^--- - | | - | unable to turn pointer into raw bytes + | ------------------------ ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ unable to turn pointer into raw bytes | = note: `#[deny(const_err)]` on by default = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release! @@ -599,9 +503,7 @@ error: any use of this value will cause an error --> $DIR/const-pointer-values-in-various-types.rs:116:41 | LL | const STR_I64_UNION: i64 = unsafe { Nonsense { stringy: "3" }.int_64 }; - | ------------------------------------^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^--- - | | - | unable to turn pointer into raw bytes + | ------------------------ ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ unable to turn pointer into raw bytes | = note: `#[deny(const_err)]` on by default = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release! @@ -612,9 +514,7 @@ error: any use of this value will cause an error --> $DIR/const-pointer-values-in-various-types.rs:120:43 | LL | const STR_I128_UNION: i128 = unsafe { Nonsense { stringy: "3" }.int_128 }; - | --------------------------------------^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^--- - | | - | unable to turn pointer into raw bytes + | -------------------------- ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ unable to turn pointer into raw bytes | = note: `#[deny(const_err)]` on by default = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release! @@ -625,9 +525,7 @@ error: any use of this value will cause an error --> $DIR/const-pointer-values-in-various-types.rs:124:41 | LL | const STR_F32_UNION: f32 = unsafe { Nonsense { stringy: "3" }.float_32 }; - | ------------------------------------^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^--- - | | - | unable to turn pointer into raw bytes + | ------------------------ ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ unable to turn pointer into raw bytes | = note: `#[deny(const_err)]` on by default = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release! @@ -638,9 +536,7 @@ error: any use of this value will cause an error --> $DIR/const-pointer-values-in-various-types.rs:128:41 | LL | const STR_F64_UNION: f64 = unsafe { Nonsense { stringy: "3" }.float_64 }; - | ------------------------------------^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^--- - | | - | unable to turn pointer into raw bytes + | ------------------------ ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ unable to turn pointer into raw bytes | = note: `#[deny(const_err)]` on by default = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release! @@ -651,9 +547,7 @@ error: any use of this value will cause an error --> $DIR/const-pointer-values-in-various-types.rs:132:43 | LL | const STR_BOOL_UNION: bool = unsafe { Nonsense { stringy: "3" }.truthy_falsey }; - | --------------------------------------^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^--- - | | - | unable to turn pointer into raw bytes + | -------------------------- ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ unable to turn pointer into raw bytes | = note: `#[deny(const_err)]` on by default = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release! @@ -664,9 +558,7 @@ error: any use of this value will cause an error --> $DIR/const-pointer-values-in-various-types.rs:136:43 | LL | const STR_CHAR_UNION: char = unsafe { Nonsense { stringy: "3" }.character }; - | --------------------------------------^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^--- - | | - | unable to turn pointer into raw bytes + | -------------------------- ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ unable to turn pointer into raw bytes | = note: `#[deny(const_err)]` on by default = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release! diff --git a/src/test/ui/consts/const-eval/const_fn_ptr_fail2.stderr b/src/test/ui/consts/const-eval/const_fn_ptr_fail2.stderr index daf3d8927c1..f6ffa1ef296 100644 --- a/src/test/ui/consts/const-eval/const_fn_ptr_fail2.stderr +++ b/src/test/ui/consts/const-eval/const_fn_ptr_fail2.stderr @@ -33,7 +33,7 @@ LL | x(y) | inside `Y` at $DIR/const_fn_ptr_fail2.rs:15:18 ... LL | const Y: usize = bar(X, 2); // FIXME: should fail to typeck someday - | --------------------------- + | -------------- | note: the lint level is defined here --> $DIR/const_fn_ptr_fail2.rs:4:10 @@ -55,7 +55,7 @@ LL | x(y) | inside `Z` at $DIR/const_fn_ptr_fail2.rs:16:18 ... LL | const Z: usize = bar(double, 2); // FIXME: should fail to typeck someday - | -------------------------------- + | -------------- | note: the lint level is defined here --> $DIR/const_fn_ptr_fail2.rs:4:10 diff --git a/src/test/ui/consts/const-eval/const_panic_stability.e2018.stderr b/src/test/ui/consts/const-eval/const_panic_stability.e2018.stderr index 94cf64fff19..f06dedc2298 100644 --- a/src/test/ui/consts/const-eval/const_panic_stability.e2018.stderr +++ b/src/test/ui/consts/const-eval/const_panic_stability.e2018.stderr @@ -5,9 +5,9 @@ LL | panic!({ "foo" }); | ^^^^^^^^^ | = note: `#[warn(non_fmt_panics)]` on by default - = note: this usage of panic!() is deprecated; it will be a hard error in Rust 2021 + = note: this usage of `panic!()` is deprecated; it will be a hard error in Rust 2021 = note: for more information, see <https://doc.rust-lang.org/nightly/edition-guide/rust-2021/panic-macro-consistency.html> -help: add a "{}" format string to Display the message +help: add a "{}" format string to `Display` the message | LL | panic!("{}", { "foo" }); | +++++ diff --git a/src/test/ui/consts/const-eval/const_raw_ptr_ops2.rs b/src/test/ui/consts/const-eval/const_raw_ptr_ops2.rs index c3f8b9f31ea..ec5508a1e90 100644 --- a/src/test/ui/consts/const-eval/const_raw_ptr_ops2.rs +++ b/src/test/ui/consts/const-eval/const_raw_ptr_ops2.rs @@ -5,6 +5,6 @@ const Z: i32 = unsafe { *(&1 as *const i32) }; // bad, will thus error in miri const Z2: i32 = unsafe { *(42 as *const i32) }; //~ ERROR evaluation of constant value failed -//~| is not a valid pointer +//~| is a dangling pointer const Z3: i32 = unsafe { *(44 as *const i32) }; //~ ERROR evaluation of constant value failed -//~| is not a valid pointer +//~| is a dangling pointer diff --git a/src/test/ui/consts/const-eval/const_raw_ptr_ops2.stderr b/src/test/ui/consts/const-eval/const_raw_ptr_ops2.stderr index df8a80be72c..e41dea873ac 100644 --- a/src/test/ui/consts/const-eval/const_raw_ptr_ops2.stderr +++ b/src/test/ui/consts/const-eval/const_raw_ptr_ops2.stderr @@ -2,13 +2,13 @@ error[E0080]: evaluation of constant value failed --> $DIR/const_raw_ptr_ops2.rs:7:26 | LL | const Z2: i32 = unsafe { *(42 as *const i32) }; - | ^^^^^^^^^^^^^^^^^^^ dereferencing pointer failed: 0x2a is not a valid pointer + | ^^^^^^^^^^^^^^^^^^^ dereferencing pointer failed: 0x2a[noalloc] is a dangling pointer (it has no provenance) error[E0080]: evaluation of constant value failed --> $DIR/const_raw_ptr_ops2.rs:9:26 | LL | const Z3: i32 = unsafe { *(44 as *const i32) }; - | ^^^^^^^^^^^^^^^^^^^ dereferencing pointer failed: 0x2c is not a valid pointer + | ^^^^^^^^^^^^^^^^^^^ dereferencing pointer failed: 0x2c[noalloc] is a dangling pointer (it has no provenance) error: aborting due to 2 previous errors diff --git a/src/test/ui/consts/const-eval/erroneous-const.stderr b/src/test/ui/consts/const-eval/erroneous-const.stderr index 9057b58ded9..adfb4cc61cc 100644 --- a/src/test/ui/consts/const-eval/erroneous-const.stderr +++ b/src/test/ui/consts/const-eval/erroneous-const.stderr @@ -14,9 +14,7 @@ warning: any use of this value will cause an error --> $DIR/erroneous-const.rs:6:22 | LL | const VOID: () = [()][2]; - | -----------------^^^^^^^- - | | - | index out of bounds: the length is 1 but the index is 2 + | -------------- ^^^^^^^ index out of bounds: the length is 1 but the index is 2 | note: the lint level is defined here --> $DIR/erroneous-const.rs:2:9 @@ -46,9 +44,7 @@ warning: any use of this value will cause an error --> $DIR/erroneous-const.rs:6:22 | LL | const VOID: () = [()][2]; - | -----------------^^^^^^^- - | | - | index out of bounds: the length is 1 but the index is 2 + | -------------- ^^^^^^^ index out of bounds: the length is 1 but the index is 2 | note: the lint level is defined here --> $DIR/erroneous-const.rs:2:9 diff --git a/src/test/ui/consts/const-eval/erroneous-const2.stderr b/src/test/ui/consts/const-eval/erroneous-const2.stderr index bf6cc8410a7..e947d93e405 100644 --- a/src/test/ui/consts/const-eval/erroneous-const2.stderr +++ b/src/test/ui/consts/const-eval/erroneous-const2.stderr @@ -14,9 +14,7 @@ warning: any use of this value will cause an error --> $DIR/erroneous-const2.rs:6:22 | LL | const VOID: () = [()][2]; - | -----------------^^^^^^^- - | | - | index out of bounds: the length is 1 but the index is 2 + | -------------- ^^^^^^^ index out of bounds: the length is 1 but the index is 2 | note: the lint level is defined here --> $DIR/erroneous-const2.rs:2:9 @@ -40,9 +38,7 @@ warning: any use of this value will cause an error --> $DIR/erroneous-const2.rs:6:22 | LL | const VOID: () = [()][2]; - | -----------------^^^^^^^- - | | - | index out of bounds: the length is 1 but the index is 2 + | -------------- ^^^^^^^ index out of bounds: the length is 1 but the index is 2 | note: the lint level is defined here --> $DIR/erroneous-const2.rs:2:9 diff --git a/src/test/ui/consts/const-eval/heap/alloc_intrinsic_nontransient_fail.stderr b/src/test/ui/consts/const-eval/heap/alloc_intrinsic_nontransient_fail.stderr index adaa4716f15..00ab0dfc557 100644 --- a/src/test/ui/consts/const-eval/heap/alloc_intrinsic_nontransient_fail.stderr +++ b/src/test/ui/consts/const-eval/heap/alloc_intrinsic_nontransient_fail.stderr @@ -2,7 +2,7 @@ error: untyped pointers are not allowed in constant --> $DIR/alloc_intrinsic_nontransient_fail.rs:6:1 | LL | const FOO: *const i32 = foo(); - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | ^^^^^^^^^^^^^^^^^^^^^ error: aborting due to previous error diff --git a/src/test/ui/consts/const-eval/heap/alloc_intrinsic_uninit.32bit.stderr b/src/test/ui/consts/const-eval/heap/alloc_intrinsic_uninit.32bit.stderr index 8ce92f72261..f1a780926e7 100644 --- a/src/test/ui/consts/const-eval/heap/alloc_intrinsic_uninit.32bit.stderr +++ b/src/test/ui/consts/const-eval/heap/alloc_intrinsic_uninit.32bit.stderr @@ -2,7 +2,7 @@ error[E0080]: it is undefined behavior to use this value --> $DIR/alloc_intrinsic_uninit.rs:8:1 | LL | const BAR: &i32 = unsafe { &*(intrinsics::const_allocate(4, 4) as *mut i32) }; - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ constructing invalid value at .<deref>: encountered uninitialized bytes, but expected initialized bytes + | ^^^^^^^^^^^^^^^ constructing invalid value at .<deref>: encountered uninitialized bytes, but expected initialized bytes | = note: The rules on what exactly is undefined behavior aren't clear, so this check might be overzealous. Please open an issue on the rustc repository if you believe it should not be considered undefined behavior. = note: the raw bytes of the constant (size: 4, align: 4) { diff --git a/src/test/ui/consts/const-eval/heap/alloc_intrinsic_uninit.64bit.stderr b/src/test/ui/consts/const-eval/heap/alloc_intrinsic_uninit.64bit.stderr index cf95842530b..2eb401226f8 100644 --- a/src/test/ui/consts/const-eval/heap/alloc_intrinsic_uninit.64bit.stderr +++ b/src/test/ui/consts/const-eval/heap/alloc_intrinsic_uninit.64bit.stderr @@ -2,7 +2,7 @@ error[E0080]: it is undefined behavior to use this value --> $DIR/alloc_intrinsic_uninit.rs:8:1 | LL | const BAR: &i32 = unsafe { &*(intrinsics::const_allocate(4, 4) as *mut i32) }; - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ constructing invalid value at .<deref>: encountered uninitialized bytes, but expected initialized bytes + | ^^^^^^^^^^^^^^^ constructing invalid value at .<deref>: encountered uninitialized bytes, but expected initialized bytes | = note: The rules on what exactly is undefined behavior aren't clear, so this check might be overzealous. Please open an issue on the rustc repository if you believe it should not be considered undefined behavior. = note: the raw bytes of the constant (size: 8, align: 8) { diff --git a/src/test/ui/consts/const-eval/heap/alloc_intrinsic_untyped.stderr b/src/test/ui/consts/const-eval/heap/alloc_intrinsic_untyped.stderr index 8f4fea96c59..36002b850b7 100644 --- a/src/test/ui/consts/const-eval/heap/alloc_intrinsic_untyped.stderr +++ b/src/test/ui/consts/const-eval/heap/alloc_intrinsic_untyped.stderr @@ -2,7 +2,7 @@ error: untyped pointers are not allowed in constant --> $DIR/alloc_intrinsic_untyped.rs:6:1 | LL | const BAR: *mut i32 = unsafe { intrinsics::const_allocate(4, 4) as *mut i32}; - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | ^^^^^^^^^^^^^^^^^^^ error: aborting due to previous error diff --git a/src/test/ui/consts/const-eval/index-out-of-bounds-never-type.stderr b/src/test/ui/consts/const-eval/index-out-of-bounds-never-type.stderr index 7b3e46fccca..da4a21e08ab 100644 --- a/src/test/ui/consts/const-eval/index-out-of-bounds-never-type.stderr +++ b/src/test/ui/consts/const-eval/index-out-of-bounds-never-type.stderr @@ -2,9 +2,7 @@ warning: any use of this value will cause an error --> $DIR/index-out-of-bounds-never-type.rs:10:61 | LL | const VOID: ! = { let x = 0 * std::mem::size_of::<T>(); [][x] }; - | --------------------------------------------------------^^^^^--- - | | - | index out of bounds: the length is 0 but the index is 0 + | ------------- ^^^^^ index out of bounds: the length is 0 but the index is 0 | note: the lint level is defined here --> $DIR/index-out-of-bounds-never-type.rs:4:9 @@ -27,9 +25,7 @@ warning: any use of this value will cause an error --> $DIR/index-out-of-bounds-never-type.rs:10:61 | LL | const VOID: ! = { let x = 0 * std::mem::size_of::<T>(); [][x] }; - | --------------------------------------------------------^^^^^--- - | | - | index out of bounds: the length is 0 but the index is 0 + | ------------- ^^^^^ index out of bounds: the length is 0 but the index is 0 | note: the lint level is defined here --> $DIR/index-out-of-bounds-never-type.rs:4:9 diff --git a/src/test/ui/consts/const-eval/issue-43197.stderr b/src/test/ui/consts/const-eval/issue-43197.stderr index 53ed32638ce..91065f41682 100644 --- a/src/test/ui/consts/const-eval/issue-43197.stderr +++ b/src/test/ui/consts/const-eval/issue-43197.stderr @@ -2,9 +2,7 @@ warning: any use of this value will cause an error --> $DIR/issue-43197.rs:10:20 | LL | const X: u32 = 0 - 1; - | ---------------^^^^^- - | | - | attempt to compute `0_u32 - 1_u32`, which would overflow + | ------------ ^^^^^ attempt to compute `0_u32 - 1_u32`, which would overflow | note: the lint level is defined here --> $DIR/issue-43197.rs:3:9 @@ -18,9 +16,7 @@ warning: any use of this value will cause an error --> $DIR/issue-43197.rs:13:24 | LL | const Y: u32 = foo(0 - 1); - | -------------------^^^^^-- - | | - | attempt to compute `0_u32 - 1_u32`, which would overflow + | ------------ ^^^^^ attempt to compute `0_u32 - 1_u32`, which would overflow | = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release! = note: for more information, see issue #71800 <https://github.com/rust-lang/rust/issues/71800> @@ -65,9 +61,7 @@ warning: any use of this value will cause an error --> $DIR/issue-43197.rs:10:20 | LL | const X: u32 = 0 - 1; - | ---------------^^^^^- - | | - | attempt to compute `0_u32 - 1_u32`, which would overflow + | ------------ ^^^^^ attempt to compute `0_u32 - 1_u32`, which would overflow | note: the lint level is defined here --> $DIR/issue-43197.rs:3:9 @@ -82,9 +76,7 @@ warning: any use of this value will cause an error --> $DIR/issue-43197.rs:13:24 | LL | const Y: u32 = foo(0 - 1); - | -------------------^^^^^-- - | | - | attempt to compute `0_u32 - 1_u32`, which would overflow + | ------------ ^^^^^ attempt to compute `0_u32 - 1_u32`, which would overflow | note: the lint level is defined here --> $DIR/issue-43197.rs:3:9 diff --git a/src/test/ui/consts/const-eval/issue-44578.stderr b/src/test/ui/consts/const-eval/issue-44578.stderr index 5ecdb7ef556..81e563b4f54 100644 --- a/src/test/ui/consts/const-eval/issue-44578.stderr +++ b/src/test/ui/consts/const-eval/issue-44578.stderr @@ -12,9 +12,7 @@ warning: any use of this value will cause an error --> $DIR/issue-44578.rs:15:24 | LL | const AMT: usize = [A::AMT][(A::AMT > B::AMT) as usize]; - | -------------------^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^- - | | - | index out of bounds: the length is 1 but the index is 1 + | ---------------- ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ index out of bounds: the length is 1 but the index is 1 | note: the lint level is defined here --> $DIR/issue-44578.rs:3:10 diff --git a/src/test/ui/consts/const-eval/issue-50814-2.stderr b/src/test/ui/consts/const-eval/issue-50814-2.stderr index 67af3b2b1d3..cc19caca724 100644 --- a/src/test/ui/consts/const-eval/issue-50814-2.stderr +++ b/src/test/ui/consts/const-eval/issue-50814-2.stderr @@ -2,9 +2,7 @@ error: any use of this value will cause an error --> $DIR/issue-50814-2.rs:14:24 | LL | const BAR: usize = [5, 6, 7][T::BOO]; - | -------------------^^^^^^^^^^^^^^^^^- - | | - | index out of bounds: the length is 3 but the index is 42 + | ---------------- ^^^^^^^^^^^^^^^^^ index out of bounds: the length is 3 but the index is 42 | = note: `#[deny(const_err)]` on by default = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release! @@ -30,9 +28,7 @@ error: any use of this value will cause an error --> $DIR/issue-50814-2.rs:14:24 | LL | const BAR: usize = [5, 6, 7][T::BOO]; - | -------------------^^^^^^^^^^^^^^^^^- - | | - | index out of bounds: the length is 3 but the index is 42 + | ---------------- ^^^^^^^^^^^^^^^^^ index out of bounds: the length is 3 but the index is 42 | = note: `#[deny(const_err)]` on by default = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release! diff --git a/src/test/ui/consts/const-eval/issue-50814.stderr b/src/test/ui/consts/const-eval/issue-50814.stderr index b82bc9ca2f8..6ceef91a042 100644 --- a/src/test/ui/consts/const-eval/issue-50814.stderr +++ b/src/test/ui/consts/const-eval/issue-50814.stderr @@ -2,9 +2,7 @@ error: any use of this value will cause an error --> $DIR/issue-50814.rs:15:21 | LL | const MAX: u8 = A::MAX + B::MAX; - | ----------------^^^^^^^^^^^^^^^- - | | - | attempt to compute `u8::MAX + u8::MAX`, which would overflow + | ------------- ^^^^^^^^^^^^^^^ attempt to compute `u8::MAX + u8::MAX`, which would overflow | = note: `#[deny(const_err)]` on by default = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release! @@ -30,9 +28,7 @@ error: any use of this value will cause an error --> $DIR/issue-50814.rs:15:21 | LL | const MAX: u8 = A::MAX + B::MAX; - | ----------------^^^^^^^^^^^^^^^- - | | - | attempt to compute `u8::MAX + u8::MAX`, which would overflow + | ------------- ^^^^^^^^^^^^^^^ attempt to compute `u8::MAX + u8::MAX`, which would overflow | = note: `#[deny(const_err)]` on by default = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release! diff --git a/src/test/ui/consts/const-eval/partial_ptr_overwrite.stderr b/src/test/ui/consts/const-eval/partial_ptr_overwrite.stderr index 1a7d3861420..b007dda246d 100644 --- a/src/test/ui/consts/const-eval/partial_ptr_overwrite.stderr +++ b/src/test/ui/consts/const-eval/partial_ptr_overwrite.stderr @@ -1,16 +1,11 @@ error: any use of this value will cause an error --> $DIR/partial_ptr_overwrite.rs:8:9 | -LL | / const PARTIAL_OVERWRITE: () = { -LL | | let mut p = &42; -LL | | unsafe { -LL | | let ptr: *mut _ = &mut p; -LL | | *(ptr as *mut u8) = 123; - | | ^^^^^^^^^^^^^^^^^^^^^^^ unable to overwrite parts of a pointer in memory at alloc4 -... | -LL | | let x = *p; -LL | | }; - | |__- +LL | const PARTIAL_OVERWRITE: () = { + | --------------------------- +... +LL | *(ptr as *mut u8) = 123; + | ^^^^^^^^^^^^^^^^^^^^^^^ unable to overwrite parts of a pointer in memory at alloc4 | = note: `#[deny(const_err)]` on by default = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release! @@ -22,16 +17,11 @@ Future incompatibility report: Future breakage diagnostic: error: any use of this value will cause an error --> $DIR/partial_ptr_overwrite.rs:8:9 | -LL | / const PARTIAL_OVERWRITE: () = { -LL | | let mut p = &42; -LL | | unsafe { -LL | | let ptr: *mut _ = &mut p; -LL | | *(ptr as *mut u8) = 123; - | | ^^^^^^^^^^^^^^^^^^^^^^^ unable to overwrite parts of a pointer in memory at alloc4 -... | -LL | | let x = *p; -LL | | }; - | |__- +LL | const PARTIAL_OVERWRITE: () = { + | --------------------------- +... +LL | *(ptr as *mut u8) = 123; + | ^^^^^^^^^^^^^^^^^^^^^^^ unable to overwrite parts of a pointer in memory at alloc4 | = note: `#[deny(const_err)]` on by default = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release! diff --git a/src/test/ui/consts/const-eval/promoted_errors.noopt.stderr b/src/test/ui/consts/const-eval/promoted_errors.noopt.stderr index be845339dfe..cfca8ef0746 100644 --- a/src/test/ui/consts/const-eval/promoted_errors.noopt.stderr +++ b/src/test/ui/consts/const-eval/promoted_errors.noopt.stderr @@ -43,21 +43,15 @@ LL | [1, 2, 3][4] warning: any use of this value will cause an error --> $DIR/promoted_errors.rs:15:5 | -LL | 0 - 1 - | ^^^^^ - | | - | attempt to compute `0_u32 - 1_u32`, which would overflow - | inside `overflow` at $DIR/promoted_errors.rs:15:5 - | inside `X` at $DIR/promoted_errors.rs:43:29 +LL | 0 - 1 + | ^^^^^ + | | + | attempt to compute `0_u32 - 1_u32`, which would overflow + | inside `overflow` at $DIR/promoted_errors.rs:15:5 + | inside `X` at $DIR/promoted_errors.rs:43:29 ... -LL | / const X: () = { -LL | | let _x: &'static u32 = &overflow(); -LL | | -LL | | -... | -LL | | let _x: &'static i32 = &oob(); -LL | | }; - | |__- +LL | const X: () = { + | ----------- | note: the lint level is defined here --> $DIR/promoted_errors.rs:11:9 @@ -70,15 +64,10 @@ LL | #![warn(const_err, arithmetic_overflow, unconditional_panic)] warning: any use of this value will cause an error --> $DIR/promoted_errors.rs:43:28 | -LL | / const X: () = { -LL | | let _x: &'static u32 = &overflow(); - | | ^^^^^^^^^^^ referenced constant has errors -LL | | -LL | | -... | -LL | | let _x: &'static i32 = &oob(); -LL | | }; - | |__- +LL | const X: () = { + | ----------- +LL | let _x: &'static u32 = &overflow(); + | ^^^^^^^^^^^ referenced constant has errors | = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release! = note: for more information, see issue #71800 <https://github.com/rust-lang/rust/issues/71800> @@ -89,21 +78,15 @@ Future incompatibility report: Future breakage diagnostic: warning: any use of this value will cause an error --> $DIR/promoted_errors.rs:15:5 | -LL | 0 - 1 - | ^^^^^ - | | - | attempt to compute `0_u32 - 1_u32`, which would overflow - | inside `overflow` at $DIR/promoted_errors.rs:15:5 - | inside `X` at $DIR/promoted_errors.rs:43:29 +LL | 0 - 1 + | ^^^^^ + | | + | attempt to compute `0_u32 - 1_u32`, which would overflow + | inside `overflow` at $DIR/promoted_errors.rs:15:5 + | inside `X` at $DIR/promoted_errors.rs:43:29 ... -LL | / const X: () = { -LL | | let _x: &'static u32 = &overflow(); -LL | | -LL | | -... | -LL | | let _x: &'static i32 = &oob(); -LL | | }; - | |__- +LL | const X: () = { + | ----------- | note: the lint level is defined here --> $DIR/promoted_errors.rs:11:9 @@ -117,15 +100,10 @@ Future breakage diagnostic: warning: any use of this value will cause an error --> $DIR/promoted_errors.rs:43:28 | -LL | / const X: () = { -LL | | let _x: &'static u32 = &overflow(); - | | ^^^^^^^^^^^ referenced constant has errors -LL | | -LL | | -... | -LL | | let _x: &'static i32 = &oob(); -LL | | }; - | |__- +LL | const X: () = { + | ----------- +LL | let _x: &'static u32 = &overflow(); + | ^^^^^^^^^^^ referenced constant has errors | note: the lint level is defined here --> $DIR/promoted_errors.rs:11:9 diff --git a/src/test/ui/consts/const-eval/promoted_errors.opt.stderr b/src/test/ui/consts/const-eval/promoted_errors.opt.stderr index c91d52336c3..984484a850f 100644 --- a/src/test/ui/consts/const-eval/promoted_errors.opt.stderr +++ b/src/test/ui/consts/const-eval/promoted_errors.opt.stderr @@ -43,21 +43,15 @@ LL | [1, 2, 3][4] warning: any use of this value will cause an error --> $DIR/promoted_errors.rs:21:5 | -LL | 1 / 0 - | ^^^^^ - | | - | attempt to divide `1_i32` by zero - | inside `div_by_zero1` at $DIR/promoted_errors.rs:21:5 - | inside `X` at $DIR/promoted_errors.rs:46:29 +LL | 1 / 0 + | ^^^^^ + | | + | attempt to divide `1_i32` by zero + | inside `div_by_zero1` at $DIR/promoted_errors.rs:21:5 + | inside `X` at $DIR/promoted_errors.rs:46:29 ... -LL | / const X: () = { -LL | | let _x: &'static u32 = &overflow(); -LL | | -LL | | -... | -LL | | let _x: &'static i32 = &oob(); -LL | | }; - | |__- +LL | const X: () = { + | ----------- | note: the lint level is defined here --> $DIR/promoted_errors.rs:11:9 @@ -70,16 +64,11 @@ LL | #![warn(const_err, arithmetic_overflow, unconditional_panic)] warning: any use of this value will cause an error --> $DIR/promoted_errors.rs:46:28 | -LL | / const X: () = { -LL | | let _x: &'static u32 = &overflow(); -LL | | -LL | | -LL | | let _x: &'static i32 = &div_by_zero1(); - | | ^^^^^^^^^^^^^^^ referenced constant has errors -... | -LL | | let _x: &'static i32 = &oob(); -LL | | }; - | |__- +LL | const X: () = { + | ----------- +... +LL | let _x: &'static i32 = &div_by_zero1(); + | ^^^^^^^^^^^^^^^ referenced constant has errors | = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release! = note: for more information, see issue #71800 <https://github.com/rust-lang/rust/issues/71800> @@ -90,21 +79,15 @@ Future incompatibility report: Future breakage diagnostic: warning: any use of this value will cause an error --> $DIR/promoted_errors.rs:21:5 | -LL | 1 / 0 - | ^^^^^ - | | - | attempt to divide `1_i32` by zero - | inside `div_by_zero1` at $DIR/promoted_errors.rs:21:5 - | inside `X` at $DIR/promoted_errors.rs:46:29 +LL | 1 / 0 + | ^^^^^ + | | + | attempt to divide `1_i32` by zero + | inside `div_by_zero1` at $DIR/promoted_errors.rs:21:5 + | inside `X` at $DIR/promoted_errors.rs:46:29 ... -LL | / const X: () = { -LL | | let _x: &'static u32 = &overflow(); -LL | | -LL | | -... | -LL | | let _x: &'static i32 = &oob(); -LL | | }; - | |__- +LL | const X: () = { + | ----------- | note: the lint level is defined here --> $DIR/promoted_errors.rs:11:9 @@ -118,16 +101,11 @@ Future breakage diagnostic: warning: any use of this value will cause an error --> $DIR/promoted_errors.rs:46:28 | -LL | / const X: () = { -LL | | let _x: &'static u32 = &overflow(); -LL | | -LL | | -LL | | let _x: &'static i32 = &div_by_zero1(); - | | ^^^^^^^^^^^^^^^ referenced constant has errors -... | -LL | | let _x: &'static i32 = &oob(); -LL | | }; - | |__- +LL | const X: () = { + | ----------- +... +LL | let _x: &'static i32 = &div_by_zero1(); + | ^^^^^^^^^^^^^^^ referenced constant has errors | note: the lint level is defined here --> $DIR/promoted_errors.rs:11:9 diff --git a/src/test/ui/consts/const-eval/promoted_errors.opt_with_overflow_checks.stderr b/src/test/ui/consts/const-eval/promoted_errors.opt_with_overflow_checks.stderr index be845339dfe..cfca8ef0746 100644 --- a/src/test/ui/consts/const-eval/promoted_errors.opt_with_overflow_checks.stderr +++ b/src/test/ui/consts/const-eval/promoted_errors.opt_with_overflow_checks.stderr @@ -43,21 +43,15 @@ LL | [1, 2, 3][4] warning: any use of this value will cause an error --> $DIR/promoted_errors.rs:15:5 | -LL | 0 - 1 - | ^^^^^ - | | - | attempt to compute `0_u32 - 1_u32`, which would overflow - | inside `overflow` at $DIR/promoted_errors.rs:15:5 - | inside `X` at $DIR/promoted_errors.rs:43:29 +LL | 0 - 1 + | ^^^^^ + | | + | attempt to compute `0_u32 - 1_u32`, which would overflow + | inside `overflow` at $DIR/promoted_errors.rs:15:5 + | inside `X` at $DIR/promoted_errors.rs:43:29 ... -LL | / const X: () = { -LL | | let _x: &'static u32 = &overflow(); -LL | | -LL | | -... | -LL | | let _x: &'static i32 = &oob(); -LL | | }; - | |__- +LL | const X: () = { + | ----------- | note: the lint level is defined here --> $DIR/promoted_errors.rs:11:9 @@ -70,15 +64,10 @@ LL | #![warn(const_err, arithmetic_overflow, unconditional_panic)] warning: any use of this value will cause an error --> $DIR/promoted_errors.rs:43:28 | -LL | / const X: () = { -LL | | let _x: &'static u32 = &overflow(); - | | ^^^^^^^^^^^ referenced constant has errors -LL | | -LL | | -... | -LL | | let _x: &'static i32 = &oob(); -LL | | }; - | |__- +LL | const X: () = { + | ----------- +LL | let _x: &'static u32 = &overflow(); + | ^^^^^^^^^^^ referenced constant has errors | = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release! = note: for more information, see issue #71800 <https://github.com/rust-lang/rust/issues/71800> @@ -89,21 +78,15 @@ Future incompatibility report: Future breakage diagnostic: warning: any use of this value will cause an error --> $DIR/promoted_errors.rs:15:5 | -LL | 0 - 1 - | ^^^^^ - | | - | attempt to compute `0_u32 - 1_u32`, which would overflow - | inside `overflow` at $DIR/promoted_errors.rs:15:5 - | inside `X` at $DIR/promoted_errors.rs:43:29 +LL | 0 - 1 + | ^^^^^ + | | + | attempt to compute `0_u32 - 1_u32`, which would overflow + | inside `overflow` at $DIR/promoted_errors.rs:15:5 + | inside `X` at $DIR/promoted_errors.rs:43:29 ... -LL | / const X: () = { -LL | | let _x: &'static u32 = &overflow(); -LL | | -LL | | -... | -LL | | let _x: &'static i32 = &oob(); -LL | | }; - | |__- +LL | const X: () = { + | ----------- | note: the lint level is defined here --> $DIR/promoted_errors.rs:11:9 @@ -117,15 +100,10 @@ Future breakage diagnostic: warning: any use of this value will cause an error --> $DIR/promoted_errors.rs:43:28 | -LL | / const X: () = { -LL | | let _x: &'static u32 = &overflow(); - | | ^^^^^^^^^^^ referenced constant has errors -LL | | -LL | | -... | -LL | | let _x: &'static i32 = &oob(); -LL | | }; - | |__- +LL | const X: () = { + | ----------- +LL | let _x: &'static u32 = &overflow(); + | ^^^^^^^^^^^ referenced constant has errors | note: the lint level is defined here --> $DIR/promoted_errors.rs:11:9 diff --git a/src/test/ui/consts/const-eval/pub_const_err.stderr b/src/test/ui/consts/const-eval/pub_const_err.stderr index 56d66827626..36197a7ab59 100644 --- a/src/test/ui/consts/const-eval/pub_const_err.stderr +++ b/src/test/ui/consts/const-eval/pub_const_err.stderr @@ -2,9 +2,7 @@ warning: any use of this value will cause an error --> $DIR/pub_const_err.rs:6:20 | LL | pub const Z: u32 = 0 - 1; - | -------------------^^^^^- - | | - | attempt to compute `0_u32 - 1_u32`, which would overflow + | ---------------- ^^^^^ attempt to compute `0_u32 - 1_u32`, which would overflow | note: the lint level is defined here --> $DIR/pub_const_err.rs:2:9 @@ -21,9 +19,7 @@ warning: any use of this value will cause an error --> $DIR/pub_const_err.rs:6:20 | LL | pub const Z: u32 = 0 - 1; - | -------------------^^^^^- - | | - | attempt to compute `0_u32 - 1_u32`, which would overflow + | ---------------- ^^^^^ attempt to compute `0_u32 - 1_u32`, which would overflow | note: the lint level is defined here --> $DIR/pub_const_err.rs:2:9 diff --git a/src/test/ui/consts/const-eval/pub_const_err_bin.stderr b/src/test/ui/consts/const-eval/pub_const_err_bin.stderr index 202ea781e97..2eef3b8f5c4 100644 --- a/src/test/ui/consts/const-eval/pub_const_err_bin.stderr +++ b/src/test/ui/consts/const-eval/pub_const_err_bin.stderr @@ -2,9 +2,7 @@ warning: any use of this value will cause an error --> $DIR/pub_const_err_bin.rs:4:20 | LL | pub const Z: u32 = 0 - 1; - | -------------------^^^^^- - | | - | attempt to compute `0_u32 - 1_u32`, which would overflow + | ---------------- ^^^^^ attempt to compute `0_u32 - 1_u32`, which would overflow | note: the lint level is defined here --> $DIR/pub_const_err_bin.rs:2:9 @@ -21,9 +19,7 @@ warning: any use of this value will cause an error --> $DIR/pub_const_err_bin.rs:4:20 | LL | pub const Z: u32 = 0 - 1; - | -------------------^^^^^- - | | - | attempt to compute `0_u32 - 1_u32`, which would overflow + | ---------------- ^^^^^ attempt to compute `0_u32 - 1_u32`, which would overflow | note: the lint level is defined here --> $DIR/pub_const_err_bin.rs:2:9 diff --git a/src/test/ui/consts/const-eval/ref_to_int_match.32bit.stderr b/src/test/ui/consts/const-eval/ref_to_int_match.32bit.stderr index a55fd8c156e..0e374358810 100644 --- a/src/test/ui/consts/const-eval/ref_to_int_match.32bit.stderr +++ b/src/test/ui/consts/const-eval/ref_to_int_match.32bit.stderr @@ -2,9 +2,7 @@ error: any use of this value will cause an error --> $DIR/ref_to_int_match.rs:25:27 | LL | const BAR: Int = unsafe { Foo { r: &42 }.f }; - | --------------------------^^^^^^^^^^^^^^^^--- - | | - | unable to turn pointer into raw bytes + | -------------- ^^^^^^^^^^^^^^^^ unable to turn pointer into raw bytes | = note: `#[deny(const_err)]` on by default = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release! @@ -29,9 +27,7 @@ error: any use of this value will cause an error --> $DIR/ref_to_int_match.rs:25:27 | LL | const BAR: Int = unsafe { Foo { r: &42 }.f }; - | --------------------------^^^^^^^^^^^^^^^^--- - | | - | unable to turn pointer into raw bytes + | -------------- ^^^^^^^^^^^^^^^^ unable to turn pointer into raw bytes | = note: `#[deny(const_err)]` on by default = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release! diff --git a/src/test/ui/consts/const-eval/ref_to_int_match.64bit.stderr b/src/test/ui/consts/const-eval/ref_to_int_match.64bit.stderr index a55fd8c156e..0e374358810 100644 --- a/src/test/ui/consts/const-eval/ref_to_int_match.64bit.stderr +++ b/src/test/ui/consts/const-eval/ref_to_int_match.64bit.stderr @@ -2,9 +2,7 @@ error: any use of this value will cause an error --> $DIR/ref_to_int_match.rs:25:27 | LL | const BAR: Int = unsafe { Foo { r: &42 }.f }; - | --------------------------^^^^^^^^^^^^^^^^--- - | | - | unable to turn pointer into raw bytes + | -------------- ^^^^^^^^^^^^^^^^ unable to turn pointer into raw bytes | = note: `#[deny(const_err)]` on by default = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release! @@ -29,9 +27,7 @@ error: any use of this value will cause an error --> $DIR/ref_to_int_match.rs:25:27 | LL | const BAR: Int = unsafe { Foo { r: &42 }.f }; - | --------------------------^^^^^^^^^^^^^^^^--- - | | - | unable to turn pointer into raw bytes + | -------------- ^^^^^^^^^^^^^^^^ unable to turn pointer into raw bytes | = note: `#[deny(const_err)]` on by default = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release! diff --git a/src/test/ui/consts/const-eval/transmute-const.32bit.stderr b/src/test/ui/consts/const-eval/transmute-const.32bit.stderr index ba4c3799158..09fd7998695 100644 --- a/src/test/ui/consts/const-eval/transmute-const.32bit.stderr +++ b/src/test/ui/consts/const-eval/transmute-const.32bit.stderr @@ -2,7 +2,7 @@ error[E0080]: it is undefined behavior to use this value --> $DIR/transmute-const.rs:4:1 | LL | static FOO: bool = unsafe { mem::transmute(3u8) }; - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ constructing invalid value: encountered 0x03, but expected a boolean + | ^^^^^^^^^^^^^^^^ constructing invalid value: encountered 0x03, but expected a boolean | = note: The rules on what exactly is undefined behavior aren't clear, so this check might be overzealous. Please open an issue on the rustc repository if you believe it should not be considered undefined behavior. = note: the raw bytes of the constant (size: 1, align: 1) { diff --git a/src/test/ui/consts/const-eval/transmute-const.64bit.stderr b/src/test/ui/consts/const-eval/transmute-const.64bit.stderr index ba4c3799158..09fd7998695 100644 --- a/src/test/ui/consts/const-eval/transmute-const.64bit.stderr +++ b/src/test/ui/consts/const-eval/transmute-const.64bit.stderr @@ -2,7 +2,7 @@ error[E0080]: it is undefined behavior to use this value --> $DIR/transmute-const.rs:4:1 | LL | static FOO: bool = unsafe { mem::transmute(3u8) }; - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ constructing invalid value: encountered 0x03, but expected a boolean + | ^^^^^^^^^^^^^^^^ constructing invalid value: encountered 0x03, but expected a boolean | = note: The rules on what exactly is undefined behavior aren't clear, so this check might be overzealous. Please open an issue on the rustc repository if you believe it should not be considered undefined behavior. = note: the raw bytes of the constant (size: 1, align: 1) { diff --git a/src/test/ui/consts/const-eval/ub-enum-overwrite.stderr b/src/test/ui/consts/const-eval/ub-enum-overwrite.stderr index 7c4ae1c56f6..8560112ae3b 100644 --- a/src/test/ui/consts/const-eval/ub-enum-overwrite.stderr +++ b/src/test/ui/consts/const-eval/ub-enum-overwrite.stderr @@ -1,14 +1,8 @@ error[E0080]: it is undefined behavior to use this value --> $DIR/ub-enum-overwrite.rs:8:1 | -LL | / const _: u8 = { -LL | | -LL | | let mut e = E::A(1); -LL | | let p = if let E::A(x) = &mut e { x as *mut u8 } else { unreachable!() }; -... | -LL | | unsafe { *p } -LL | | }; - | |__^ constructing invalid value: encountered uninitialized bytes, but expected initialized bytes +LL | const _: u8 = { + | ^^^^^^^^^^^ constructing invalid value: encountered uninitialized bytes, but expected initialized bytes | = note: The rules on what exactly is undefined behavior aren't clear, so this check might be overzealous. Please open an issue on the rustc repository if you believe it should not be considered undefined behavior. = note: the raw bytes of the constant (size: 1, align: 1) { diff --git a/src/test/ui/consts/const-eval/ub-enum.32bit.stderr b/src/test/ui/consts/const-eval/ub-enum.32bit.stderr index c1cf22c8839..2f8b44da0fc 100644 --- a/src/test/ui/consts/const-eval/ub-enum.32bit.stderr +++ b/src/test/ui/consts/const-eval/ub-enum.32bit.stderr @@ -2,7 +2,7 @@ error[E0080]: it is undefined behavior to use this value --> $DIR/ub-enum.rs:23:1 | LL | const BAD_ENUM: Enum = unsafe { mem::transmute(1usize) }; - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ constructing invalid value at .<enum-tag>: encountered 0x00000001, but expected a valid enum tag + | ^^^^^^^^^^^^^^^^^^^^ constructing invalid value at .<enum-tag>: encountered 0x00000001, but expected a valid enum tag | = note: The rules on what exactly is undefined behavior aren't clear, so this check might be overzealous. Please open an issue on the rustc repository if you believe it should not be considered undefined behavior. = note: the raw bytes of the constant (size: 4, align: 4) { @@ -13,7 +13,7 @@ error: any use of this value will cause an error --> $DIR/ub-enum.rs:26:1 | LL | const BAD_ENUM_PTR: Enum = unsafe { mem::transmute(&1) }; - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ unable to turn pointer into raw bytes + | ^^^^^^^^^^^^^^^^^^^^^^^^ unable to turn pointer into raw bytes | = note: `#[deny(const_err)]` on by default = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release! @@ -23,7 +23,7 @@ error: any use of this value will cause an error --> $DIR/ub-enum.rs:30:1 | LL | const BAD_ENUM_WRAPPED: Wrap<Enum> = unsafe { mem::transmute(&1) }; - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ unable to turn pointer into raw bytes + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ unable to turn pointer into raw bytes | = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release! = note: for more information, see issue #71800 <https://github.com/rust-lang/rust/issues/71800> @@ -32,7 +32,7 @@ error[E0080]: it is undefined behavior to use this value --> $DIR/ub-enum.rs:43:1 | LL | const BAD_ENUM2: Enum2 = unsafe { mem::transmute(0usize) }; - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ constructing invalid value at .<enum-tag>: encountered 0x00000000, but expected a valid enum tag + | ^^^^^^^^^^^^^^^^^^^^^^ constructing invalid value at .<enum-tag>: encountered 0x00000000, but expected a valid enum tag | = note: The rules on what exactly is undefined behavior aren't clear, so this check might be overzealous. Please open an issue on the rustc repository if you believe it should not be considered undefined behavior. = note: the raw bytes of the constant (size: 4, align: 4) { @@ -43,7 +43,7 @@ error: any use of this value will cause an error --> $DIR/ub-enum.rs:45:1 | LL | const BAD_ENUM2_PTR: Enum2 = unsafe { mem::transmute(&0) }; - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ unable to turn pointer into raw bytes + | ^^^^^^^^^^^^^^^^^^^^^^^^^^ unable to turn pointer into raw bytes | = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release! = note: for more information, see issue #71800 <https://github.com/rust-lang/rust/issues/71800> @@ -52,7 +52,7 @@ error: any use of this value will cause an error --> $DIR/ub-enum.rs:49:1 | LL | const BAD_ENUM2_WRAPPED: Wrap<Enum2> = unsafe { mem::transmute(&0) }; - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ unable to turn pointer into raw bytes + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ unable to turn pointer into raw bytes | = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release! = note: for more information, see issue #71800 <https://github.com/rust-lang/rust/issues/71800> @@ -61,7 +61,7 @@ error[E0080]: it is undefined behavior to use this value --> $DIR/ub-enum.rs:59:1 | LL | const BAD_ENUM2_UNDEF : Enum2 = unsafe { MaybeUninit { uninit: () }.init }; - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ constructing invalid value at .<enum-tag>: encountered uninitialized bytes, but expected initialized bytes + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ constructing invalid value at .<enum-tag>: encountered uninitialized bytes, but expected initialized bytes | = note: The rules on what exactly is undefined behavior aren't clear, so this check might be overzealous. Please open an issue on the rustc repository if you believe it should not be considered undefined behavior. = note: the raw bytes of the constant (size: 4, align: 4) { @@ -72,7 +72,7 @@ error: any use of this value will cause an error --> $DIR/ub-enum.rs:63:1 | LL | const BAD_ENUM2_OPTION_PTR: Option<Enum2> = unsafe { mem::transmute(&0) }; - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ unable to turn pointer into raw bytes + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ unable to turn pointer into raw bytes | = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release! = note: for more information, see issue #71800 <https://github.com/rust-lang/rust/issues/71800> @@ -81,7 +81,7 @@ error[E0080]: it is undefined behavior to use this value --> $DIR/ub-enum.rs:81:1 | LL | const BAD_UNINHABITED_VARIANT1: UninhDiscriminant = unsafe { mem::transmute(1u8) }; - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ constructing invalid value at .<enum-variant(B)>.0: encountered a value of the never type `!` + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ constructing invalid value at .<enum-variant(B)>.0: encountered a value of the never type `!` | = note: The rules on what exactly is undefined behavior aren't clear, so this check might be overzealous. Please open an issue on the rustc repository if you believe it should not be considered undefined behavior. = note: the raw bytes of the constant (size: 1, align: 1) { @@ -92,7 +92,7 @@ error[E0080]: it is undefined behavior to use this value --> $DIR/ub-enum.rs:83:1 | LL | const BAD_UNINHABITED_VARIANT2: UninhDiscriminant = unsafe { mem::transmute(3u8) }; - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ constructing invalid value at .<enum-variant(D)>.0: encountered a value of uninhabited type Never + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ constructing invalid value at .<enum-variant(D)>.0: encountered a value of uninhabited type Never | = note: The rules on what exactly is undefined behavior aren't clear, so this check might be overzealous. Please open an issue on the rustc repository if you believe it should not be considered undefined behavior. = note: the raw bytes of the constant (size: 1, align: 1) { @@ -103,7 +103,7 @@ error[E0080]: it is undefined behavior to use this value --> $DIR/ub-enum.rs:91:1 | LL | const BAD_OPTION_CHAR: Option<(char, char)> = Some(('x', unsafe { mem::transmute(!0u32) })); - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ constructing invalid value at .<enum-variant(Some)>.0.1: encountered 0xffffffff, but expected a valid unicode scalar value (in `0..=0x10FFFF` but not in `0xD800..=0xDFFF`) + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ constructing invalid value at .<enum-variant(Some)>.0.1: encountered 0xffffffff, but expected a valid unicode scalar value (in `0..=0x10FFFF` but not in `0xD800..=0xDFFF`) | = note: The rules on what exactly is undefined behavior aren't clear, so this check might be overzealous. Please open an issue on the rustc repository if you believe it should not be considered undefined behavior. = note: the raw bytes of the constant (size: 8, align: 4) { @@ -130,7 +130,7 @@ error: any use of this value will cause an error --> $DIR/ub-enum.rs:26:1 | LL | const BAD_ENUM_PTR: Enum = unsafe { mem::transmute(&1) }; - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ unable to turn pointer into raw bytes + | ^^^^^^^^^^^^^^^^^^^^^^^^ unable to turn pointer into raw bytes | = note: `#[deny(const_err)]` on by default = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release! @@ -141,7 +141,7 @@ error: any use of this value will cause an error --> $DIR/ub-enum.rs:30:1 | LL | const BAD_ENUM_WRAPPED: Wrap<Enum> = unsafe { mem::transmute(&1) }; - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ unable to turn pointer into raw bytes + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ unable to turn pointer into raw bytes | = note: `#[deny(const_err)]` on by default = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release! @@ -152,7 +152,7 @@ error: any use of this value will cause an error --> $DIR/ub-enum.rs:45:1 | LL | const BAD_ENUM2_PTR: Enum2 = unsafe { mem::transmute(&0) }; - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ unable to turn pointer into raw bytes + | ^^^^^^^^^^^^^^^^^^^^^^^^^^ unable to turn pointer into raw bytes | = note: `#[deny(const_err)]` on by default = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release! @@ -163,7 +163,7 @@ error: any use of this value will cause an error --> $DIR/ub-enum.rs:49:1 | LL | const BAD_ENUM2_WRAPPED: Wrap<Enum2> = unsafe { mem::transmute(&0) }; - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ unable to turn pointer into raw bytes + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ unable to turn pointer into raw bytes | = note: `#[deny(const_err)]` on by default = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release! @@ -174,7 +174,7 @@ error: any use of this value will cause an error --> $DIR/ub-enum.rs:63:1 | LL | const BAD_ENUM2_OPTION_PTR: Option<Enum2> = unsafe { mem::transmute(&0) }; - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ unable to turn pointer into raw bytes + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ unable to turn pointer into raw bytes | = note: `#[deny(const_err)]` on by default = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release! diff --git a/src/test/ui/consts/const-eval/ub-enum.64bit.stderr b/src/test/ui/consts/const-eval/ub-enum.64bit.stderr index 5e749a6e735..3a05a5150f1 100644 --- a/src/test/ui/consts/const-eval/ub-enum.64bit.stderr +++ b/src/test/ui/consts/const-eval/ub-enum.64bit.stderr @@ -2,7 +2,7 @@ error[E0080]: it is undefined behavior to use this value --> $DIR/ub-enum.rs:23:1 | LL | const BAD_ENUM: Enum = unsafe { mem::transmute(1usize) }; - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ constructing invalid value at .<enum-tag>: encountered 0x0000000000000001, but expected a valid enum tag + | ^^^^^^^^^^^^^^^^^^^^ constructing invalid value at .<enum-tag>: encountered 0x0000000000000001, but expected a valid enum tag | = note: The rules on what exactly is undefined behavior aren't clear, so this check might be overzealous. Please open an issue on the rustc repository if you believe it should not be considered undefined behavior. = note: the raw bytes of the constant (size: 8, align: 8) { @@ -13,7 +13,7 @@ error: any use of this value will cause an error --> $DIR/ub-enum.rs:26:1 | LL | const BAD_ENUM_PTR: Enum = unsafe { mem::transmute(&1) }; - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ unable to turn pointer into raw bytes + | ^^^^^^^^^^^^^^^^^^^^^^^^ unable to turn pointer into raw bytes | = note: `#[deny(const_err)]` on by default = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release! @@ -23,7 +23,7 @@ error: any use of this value will cause an error --> $DIR/ub-enum.rs:30:1 | LL | const BAD_ENUM_WRAPPED: Wrap<Enum> = unsafe { mem::transmute(&1) }; - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ unable to turn pointer into raw bytes + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ unable to turn pointer into raw bytes | = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release! = note: for more information, see issue #71800 <https://github.com/rust-lang/rust/issues/71800> @@ -32,7 +32,7 @@ error[E0080]: it is undefined behavior to use this value --> $DIR/ub-enum.rs:43:1 | LL | const BAD_ENUM2: Enum2 = unsafe { mem::transmute(0usize) }; - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ constructing invalid value at .<enum-tag>: encountered 0x0000000000000000, but expected a valid enum tag + | ^^^^^^^^^^^^^^^^^^^^^^ constructing invalid value at .<enum-tag>: encountered 0x0000000000000000, but expected a valid enum tag | = note: The rules on what exactly is undefined behavior aren't clear, so this check might be overzealous. Please open an issue on the rustc repository if you believe it should not be considered undefined behavior. = note: the raw bytes of the constant (size: 8, align: 8) { @@ -43,7 +43,7 @@ error: any use of this value will cause an error --> $DIR/ub-enum.rs:45:1 | LL | const BAD_ENUM2_PTR: Enum2 = unsafe { mem::transmute(&0) }; - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ unable to turn pointer into raw bytes + | ^^^^^^^^^^^^^^^^^^^^^^^^^^ unable to turn pointer into raw bytes | = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release! = note: for more information, see issue #71800 <https://github.com/rust-lang/rust/issues/71800> @@ -52,7 +52,7 @@ error: any use of this value will cause an error --> $DIR/ub-enum.rs:49:1 | LL | const BAD_ENUM2_WRAPPED: Wrap<Enum2> = unsafe { mem::transmute(&0) }; - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ unable to turn pointer into raw bytes + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ unable to turn pointer into raw bytes | = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release! = note: for more information, see issue #71800 <https://github.com/rust-lang/rust/issues/71800> @@ -61,7 +61,7 @@ error[E0080]: it is undefined behavior to use this value --> $DIR/ub-enum.rs:59:1 | LL | const BAD_ENUM2_UNDEF : Enum2 = unsafe { MaybeUninit { uninit: () }.init }; - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ constructing invalid value at .<enum-tag>: encountered uninitialized bytes, but expected initialized bytes + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ constructing invalid value at .<enum-tag>: encountered uninitialized bytes, but expected initialized bytes | = note: The rules on what exactly is undefined behavior aren't clear, so this check might be overzealous. Please open an issue on the rustc repository if you believe it should not be considered undefined behavior. = note: the raw bytes of the constant (size: 8, align: 8) { @@ -72,7 +72,7 @@ error: any use of this value will cause an error --> $DIR/ub-enum.rs:63:1 | LL | const BAD_ENUM2_OPTION_PTR: Option<Enum2> = unsafe { mem::transmute(&0) }; - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ unable to turn pointer into raw bytes + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ unable to turn pointer into raw bytes | = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release! = note: for more information, see issue #71800 <https://github.com/rust-lang/rust/issues/71800> @@ -81,7 +81,7 @@ error[E0080]: it is undefined behavior to use this value --> $DIR/ub-enum.rs:81:1 | LL | const BAD_UNINHABITED_VARIANT1: UninhDiscriminant = unsafe { mem::transmute(1u8) }; - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ constructing invalid value at .<enum-variant(B)>.0: encountered a value of the never type `!` + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ constructing invalid value at .<enum-variant(B)>.0: encountered a value of the never type `!` | = note: The rules on what exactly is undefined behavior aren't clear, so this check might be overzealous. Please open an issue on the rustc repository if you believe it should not be considered undefined behavior. = note: the raw bytes of the constant (size: 1, align: 1) { @@ -92,7 +92,7 @@ error[E0080]: it is undefined behavior to use this value --> $DIR/ub-enum.rs:83:1 | LL | const BAD_UNINHABITED_VARIANT2: UninhDiscriminant = unsafe { mem::transmute(3u8) }; - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ constructing invalid value at .<enum-variant(D)>.0: encountered a value of uninhabited type Never + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ constructing invalid value at .<enum-variant(D)>.0: encountered a value of uninhabited type Never | = note: The rules on what exactly is undefined behavior aren't clear, so this check might be overzealous. Please open an issue on the rustc repository if you believe it should not be considered undefined behavior. = note: the raw bytes of the constant (size: 1, align: 1) { @@ -103,7 +103,7 @@ error[E0080]: it is undefined behavior to use this value --> $DIR/ub-enum.rs:91:1 | LL | const BAD_OPTION_CHAR: Option<(char, char)> = Some(('x', unsafe { mem::transmute(!0u32) })); - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ constructing invalid value at .<enum-variant(Some)>.0.1: encountered 0xffffffff, but expected a valid unicode scalar value (in `0..=0x10FFFF` but not in `0xD800..=0xDFFF`) + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ constructing invalid value at .<enum-variant(Some)>.0.1: encountered 0xffffffff, but expected a valid unicode scalar value (in `0..=0x10FFFF` but not in `0xD800..=0xDFFF`) | = note: The rules on what exactly is undefined behavior aren't clear, so this check might be overzealous. Please open an issue on the rustc repository if you believe it should not be considered undefined behavior. = note: the raw bytes of the constant (size: 8, align: 4) { @@ -130,7 +130,7 @@ error: any use of this value will cause an error --> $DIR/ub-enum.rs:26:1 | LL | const BAD_ENUM_PTR: Enum = unsafe { mem::transmute(&1) }; - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ unable to turn pointer into raw bytes + | ^^^^^^^^^^^^^^^^^^^^^^^^ unable to turn pointer into raw bytes | = note: `#[deny(const_err)]` on by default = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release! @@ -141,7 +141,7 @@ error: any use of this value will cause an error --> $DIR/ub-enum.rs:30:1 | LL | const BAD_ENUM_WRAPPED: Wrap<Enum> = unsafe { mem::transmute(&1) }; - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ unable to turn pointer into raw bytes + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ unable to turn pointer into raw bytes | = note: `#[deny(const_err)]` on by default = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release! @@ -152,7 +152,7 @@ error: any use of this value will cause an error --> $DIR/ub-enum.rs:45:1 | LL | const BAD_ENUM2_PTR: Enum2 = unsafe { mem::transmute(&0) }; - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ unable to turn pointer into raw bytes + | ^^^^^^^^^^^^^^^^^^^^^^^^^^ unable to turn pointer into raw bytes | = note: `#[deny(const_err)]` on by default = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release! @@ -163,7 +163,7 @@ error: any use of this value will cause an error --> $DIR/ub-enum.rs:49:1 | LL | const BAD_ENUM2_WRAPPED: Wrap<Enum2> = unsafe { mem::transmute(&0) }; - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ unable to turn pointer into raw bytes + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ unable to turn pointer into raw bytes | = note: `#[deny(const_err)]` on by default = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release! @@ -174,7 +174,7 @@ error: any use of this value will cause an error --> $DIR/ub-enum.rs:63:1 | LL | const BAD_ENUM2_OPTION_PTR: Option<Enum2> = unsafe { mem::transmute(&0) }; - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ unable to turn pointer into raw bytes + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ unable to turn pointer into raw bytes | = note: `#[deny(const_err)]` on by default = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release! diff --git a/src/test/ui/consts/const-eval/ub-incorrect-vtable.32bit.stderr b/src/test/ui/consts/const-eval/ub-incorrect-vtable.32bit.stderr index 1da829ad125..c6422447a4b 100644 --- a/src/test/ui/consts/const-eval/ub-incorrect-vtable.32bit.stderr +++ b/src/test/ui/consts/const-eval/ub-incorrect-vtable.32bit.stderr @@ -13,9 +13,8 @@ LL | unsafe { std::mem::transmute((&92u8, &[1usize, usize::MAX, 1usize])) }; error[E0080]: it is undefined behavior to use this value --> $DIR/ub-incorrect-vtable.rs:34:1 | -LL | / const INVALID_VTABLE_ALIGNMENT_UB: W<&dyn Trait> = -LL | | unsafe { std::mem::transmute((&92u8, &(drop_me as fn(*mut usize), 1usize, 1000usize))) }; - | |_____________________________________________________________________________________________^ constructing invalid value at .0: encountered invalid vtable: alignment `1000` is not a power of 2 +LL | const INVALID_VTABLE_ALIGNMENT_UB: W<&dyn Trait> = + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ constructing invalid value at .0: encountered invalid vtable: alignment `1000` is not a power of 2 | = note: The rules on what exactly is undefined behavior aren't clear, so this check might be overzealous. Please open an issue on the rustc repository if you believe it should not be considered undefined behavior. = note: the raw bytes of the constant (size: 8, align: 4) { @@ -25,9 +24,8 @@ LL | | unsafe { std::mem::transmute((&92u8, &(drop_me as fn(*mut usize), 1us error[E0080]: it is undefined behavior to use this value --> $DIR/ub-incorrect-vtable.rs:39:1 | -LL | / const INVALID_VTABLE_SIZE_UB: W<&dyn Trait> = -LL | | unsafe { std::mem::transmute((&92u8, &(drop_me as fn(*mut usize), usize::MAX, 1usize))) }; - | |______________________________________________________________________________________________^ constructing invalid value at .0: encountered invalid vtable: size is bigger than largest supported object +LL | const INVALID_VTABLE_SIZE_UB: W<&dyn Trait> = + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ constructing invalid value at .0: encountered invalid vtable: size is bigger than largest supported object | = note: The rules on what exactly is undefined behavior aren't clear, so this check might be overzealous. Please open an issue on the rustc repository if you believe it should not be considered undefined behavior. = note: the raw bytes of the constant (size: 8, align: 4) { diff --git a/src/test/ui/consts/const-eval/ub-incorrect-vtable.64bit.stderr b/src/test/ui/consts/const-eval/ub-incorrect-vtable.64bit.stderr index 1139976f390..e594ad71b5b 100644 --- a/src/test/ui/consts/const-eval/ub-incorrect-vtable.64bit.stderr +++ b/src/test/ui/consts/const-eval/ub-incorrect-vtable.64bit.stderr @@ -13,9 +13,8 @@ LL | unsafe { std::mem::transmute((&92u8, &[1usize, usize::MAX, 1usize])) }; error[E0080]: it is undefined behavior to use this value --> $DIR/ub-incorrect-vtable.rs:34:1 | -LL | / const INVALID_VTABLE_ALIGNMENT_UB: W<&dyn Trait> = -LL | | unsafe { std::mem::transmute((&92u8, &(drop_me as fn(*mut usize), 1usize, 1000usize))) }; - | |_____________________________________________________________________________________________^ constructing invalid value at .0: encountered invalid vtable: alignment `1000` is not a power of 2 +LL | const INVALID_VTABLE_ALIGNMENT_UB: W<&dyn Trait> = + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ constructing invalid value at .0: encountered invalid vtable: alignment `1000` is not a power of 2 | = note: The rules on what exactly is undefined behavior aren't clear, so this check might be overzealous. Please open an issue on the rustc repository if you believe it should not be considered undefined behavior. = note: the raw bytes of the constant (size: 16, align: 8) { @@ -25,9 +24,8 @@ LL | | unsafe { std::mem::transmute((&92u8, &(drop_me as fn(*mut usize), 1us error[E0080]: it is undefined behavior to use this value --> $DIR/ub-incorrect-vtable.rs:39:1 | -LL | / const INVALID_VTABLE_SIZE_UB: W<&dyn Trait> = -LL | | unsafe { std::mem::transmute((&92u8, &(drop_me as fn(*mut usize), usize::MAX, 1usize))) }; - | |______________________________________________________________________________________________^ constructing invalid value at .0: encountered invalid vtable: size is bigger than largest supported object +LL | const INVALID_VTABLE_SIZE_UB: W<&dyn Trait> = + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ constructing invalid value at .0: encountered invalid vtable: size is bigger than largest supported object | = note: The rules on what exactly is undefined behavior aren't clear, so this check might be overzealous. Please open an issue on the rustc repository if you believe it should not be considered undefined behavior. = note: the raw bytes of the constant (size: 16, align: 8) { diff --git a/src/test/ui/consts/const-eval/ub-int-array.32bit.stderr b/src/test/ui/consts/const-eval/ub-int-array.32bit.stderr index 5964d494a14..8eece9e30e4 100644 --- a/src/test/ui/consts/const-eval/ub-int-array.32bit.stderr +++ b/src/test/ui/consts/const-eval/ub-int-array.32bit.stderr @@ -1,14 +1,8 @@ error[E0080]: it is undefined behavior to use this value --> $DIR/ub-int-array.rs:14:1 | -LL | / const UNINIT_INT_0: [u32; 3] = unsafe { -LL | | -LL | | -LL | | [ -... | -LL | | ] -LL | | }; - | |__^ constructing invalid value at [0]: encountered uninitialized bytes +LL | const UNINIT_INT_0: [u32; 3] = unsafe { + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ constructing invalid value at [0]: encountered uninitialized bytes | = note: The rules on what exactly is undefined behavior aren't clear, so this check might be overzealous. Please open an issue on the rustc repository if you believe it should not be considered undefined behavior. = note: the raw bytes of the constant (size: 12, align: 4) { @@ -18,14 +12,8 @@ LL | | }; error[E0080]: it is undefined behavior to use this value --> $DIR/ub-int-array.rs:23:1 | -LL | / const UNINIT_INT_1: [u32; 3] = unsafe { -LL | | -LL | | -LL | | mem::transmute( -... | -LL | | ) -LL | | }; - | |__^ constructing invalid value at [1]: encountered uninitialized bytes +LL | const UNINIT_INT_1: [u32; 3] = unsafe { + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ constructing invalid value at [1]: encountered uninitialized bytes | = note: The rules on what exactly is undefined behavior aren't clear, so this check might be overzealous. Please open an issue on the rustc repository if you believe it should not be considered undefined behavior. = note: the raw bytes of the constant (size: 12, align: 4) { @@ -35,14 +23,8 @@ LL | | }; error[E0080]: it is undefined behavior to use this value --> $DIR/ub-int-array.rs:43:1 | -LL | / const UNINIT_INT_2: [u32; 3] = unsafe { -LL | | -LL | | -LL | | mem::transmute( -... | -LL | | ) -LL | | }; - | |__^ constructing invalid value at [2]: encountered uninitialized bytes +LL | const UNINIT_INT_2: [u32; 3] = unsafe { + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ constructing invalid value at [2]: encountered uninitialized bytes | = note: The rules on what exactly is undefined behavior aren't clear, so this check might be overzealous. Please open an issue on the rustc repository if you believe it should not be considered undefined behavior. = note: the raw bytes of the constant (size: 12, align: 4) { diff --git a/src/test/ui/consts/const-eval/ub-int-array.64bit.stderr b/src/test/ui/consts/const-eval/ub-int-array.64bit.stderr index 5964d494a14..8eece9e30e4 100644 --- a/src/test/ui/consts/const-eval/ub-int-array.64bit.stderr +++ b/src/test/ui/consts/const-eval/ub-int-array.64bit.stderr @@ -1,14 +1,8 @@ error[E0080]: it is undefined behavior to use this value --> $DIR/ub-int-array.rs:14:1 | -LL | / const UNINIT_INT_0: [u32; 3] = unsafe { -LL | | -LL | | -LL | | [ -... | -LL | | ] -LL | | }; - | |__^ constructing invalid value at [0]: encountered uninitialized bytes +LL | const UNINIT_INT_0: [u32; 3] = unsafe { + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ constructing invalid value at [0]: encountered uninitialized bytes | = note: The rules on what exactly is undefined behavior aren't clear, so this check might be overzealous. Please open an issue on the rustc repository if you believe it should not be considered undefined behavior. = note: the raw bytes of the constant (size: 12, align: 4) { @@ -18,14 +12,8 @@ LL | | }; error[E0080]: it is undefined behavior to use this value --> $DIR/ub-int-array.rs:23:1 | -LL | / const UNINIT_INT_1: [u32; 3] = unsafe { -LL | | -LL | | -LL | | mem::transmute( -... | -LL | | ) -LL | | }; - | |__^ constructing invalid value at [1]: encountered uninitialized bytes +LL | const UNINIT_INT_1: [u32; 3] = unsafe { + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ constructing invalid value at [1]: encountered uninitialized bytes | = note: The rules on what exactly is undefined behavior aren't clear, so this check might be overzealous. Please open an issue on the rustc repository if you believe it should not be considered undefined behavior. = note: the raw bytes of the constant (size: 12, align: 4) { @@ -35,14 +23,8 @@ LL | | }; error[E0080]: it is undefined behavior to use this value --> $DIR/ub-int-array.rs:43:1 | -LL | / const UNINIT_INT_2: [u32; 3] = unsafe { -LL | | -LL | | -LL | | mem::transmute( -... | -LL | | ) -LL | | }; - | |__^ constructing invalid value at [2]: encountered uninitialized bytes +LL | const UNINIT_INT_2: [u32; 3] = unsafe { + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ constructing invalid value at [2]: encountered uninitialized bytes | = note: The rules on what exactly is undefined behavior aren't clear, so this check might be overzealous. Please open an issue on the rustc repository if you believe it should not be considered undefined behavior. = note: the raw bytes of the constant (size: 12, align: 4) { diff --git a/src/test/ui/consts/const-eval/ub-nonnull.32bit.stderr b/src/test/ui/consts/const-eval/ub-nonnull.32bit.stderr index 6c1a9d25f23..d450a814cfa 100644 --- a/src/test/ui/consts/const-eval/ub-nonnull.32bit.stderr +++ b/src/test/ui/consts/const-eval/ub-nonnull.32bit.stderr @@ -2,7 +2,7 @@ error[E0080]: it is undefined behavior to use this value --> $DIR/ub-nonnull.rs:12:1 | LL | const NULL_PTR: NonNull<u8> = unsafe { mem::transmute(0usize) }; - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ constructing invalid value: encountered 0, but expected something greater or equal to 1 + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^ constructing invalid value: encountered 0, but expected something greater or equal to 1 | = note: The rules on what exactly is undefined behavior aren't clear, so this check might be overzealous. Please open an issue on the rustc repository if you believe it should not be considered undefined behavior. = note: the raw bytes of the constant (size: 4, align: 4) { @@ -19,7 +19,7 @@ error[E0080]: it is undefined behavior to use this value --> $DIR/ub-nonnull.rs:23:1 | LL | const NULL_U8: NonZeroU8 = unsafe { mem::transmute(0u8) }; - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ constructing invalid value: encountered 0, but expected something greater or equal to 1 + | ^^^^^^^^^^^^^^^^^^^^^^^^ constructing invalid value: encountered 0, but expected something greater or equal to 1 | = note: The rules on what exactly is undefined behavior aren't clear, so this check might be overzealous. Please open an issue on the rustc repository if you believe it should not be considered undefined behavior. = note: the raw bytes of the constant (size: 1, align: 1) { @@ -30,7 +30,7 @@ error[E0080]: it is undefined behavior to use this value --> $DIR/ub-nonnull.rs:25:1 | LL | const NULL_USIZE: NonZeroUsize = unsafe { mem::transmute(0usize) }; - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ constructing invalid value: encountered 0, but expected something greater or equal to 1 + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ constructing invalid value: encountered 0, but expected something greater or equal to 1 | = note: The rules on what exactly is undefined behavior aren't clear, so this check might be overzealous. Please open an issue on the rustc repository if you believe it should not be considered undefined behavior. = note: the raw bytes of the constant (size: 4, align: 4) { @@ -41,7 +41,7 @@ error[E0080]: it is undefined behavior to use this value --> $DIR/ub-nonnull.rs:33:1 | LL | const UNINIT: NonZeroU8 = unsafe { MaybeUninit { uninit: () }.init }; - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ constructing invalid value at .0: encountered uninitialized bytes, but expected initialized bytes + | ^^^^^^^^^^^^^^^^^^^^^^^ constructing invalid value at .0: encountered uninitialized bytes, but expected initialized bytes | = note: The rules on what exactly is undefined behavior aren't clear, so this check might be overzealous. Please open an issue on the rustc repository if you believe it should not be considered undefined behavior. = note: the raw bytes of the constant (size: 1, align: 1) { @@ -52,7 +52,7 @@ error[E0080]: it is undefined behavior to use this value --> $DIR/ub-nonnull.rs:41:1 | LL | const BAD_RANGE1: RestrictedRange1 = unsafe { RestrictedRange1(42) }; - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ constructing invalid value: encountered 42, but expected something in the range 10..=30 + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ constructing invalid value: encountered 42, but expected something in the range 10..=30 | = note: The rules on what exactly is undefined behavior aren't clear, so this check might be overzealous. Please open an issue on the rustc repository if you believe it should not be considered undefined behavior. = note: the raw bytes of the constant (size: 4, align: 4) { @@ -63,7 +63,7 @@ error[E0080]: it is undefined behavior to use this value --> $DIR/ub-nonnull.rs:47:1 | LL | const BAD_RANGE2: RestrictedRange2 = unsafe { RestrictedRange2(20) }; - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ constructing invalid value: encountered 20, but expected something less or equal to 10, or greater or equal to 30 + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ constructing invalid value: encountered 20, but expected something less or equal to 10, or greater or equal to 30 | = note: The rules on what exactly is undefined behavior aren't clear, so this check might be overzealous. Please open an issue on the rustc repository if you believe it should not be considered undefined behavior. = note: the raw bytes of the constant (size: 4, align: 4) { diff --git a/src/test/ui/consts/const-eval/ub-nonnull.64bit.stderr b/src/test/ui/consts/const-eval/ub-nonnull.64bit.stderr index f3827473737..ed0d91aabd3 100644 --- a/src/test/ui/consts/const-eval/ub-nonnull.64bit.stderr +++ b/src/test/ui/consts/const-eval/ub-nonnull.64bit.stderr @@ -2,7 +2,7 @@ error[E0080]: it is undefined behavior to use this value --> $DIR/ub-nonnull.rs:12:1 | LL | const NULL_PTR: NonNull<u8> = unsafe { mem::transmute(0usize) }; - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ constructing invalid value: encountered 0, but expected something greater or equal to 1 + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^ constructing invalid value: encountered 0, but expected something greater or equal to 1 | = note: The rules on what exactly is undefined behavior aren't clear, so this check might be overzealous. Please open an issue on the rustc repository if you believe it should not be considered undefined behavior. = note: the raw bytes of the constant (size: 8, align: 8) { @@ -19,7 +19,7 @@ error[E0080]: it is undefined behavior to use this value --> $DIR/ub-nonnull.rs:23:1 | LL | const NULL_U8: NonZeroU8 = unsafe { mem::transmute(0u8) }; - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ constructing invalid value: encountered 0, but expected something greater or equal to 1 + | ^^^^^^^^^^^^^^^^^^^^^^^^ constructing invalid value: encountered 0, but expected something greater or equal to 1 | = note: The rules on what exactly is undefined behavior aren't clear, so this check might be overzealous. Please open an issue on the rustc repository if you believe it should not be considered undefined behavior. = note: the raw bytes of the constant (size: 1, align: 1) { @@ -30,7 +30,7 @@ error[E0080]: it is undefined behavior to use this value --> $DIR/ub-nonnull.rs:25:1 | LL | const NULL_USIZE: NonZeroUsize = unsafe { mem::transmute(0usize) }; - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ constructing invalid value: encountered 0, but expected something greater or equal to 1 + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ constructing invalid value: encountered 0, but expected something greater or equal to 1 | = note: The rules on what exactly is undefined behavior aren't clear, so this check might be overzealous. Please open an issue on the rustc repository if you believe it should not be considered undefined behavior. = note: the raw bytes of the constant (size: 8, align: 8) { @@ -41,7 +41,7 @@ error[E0080]: it is undefined behavior to use this value --> $DIR/ub-nonnull.rs:33:1 | LL | const UNINIT: NonZeroU8 = unsafe { MaybeUninit { uninit: () }.init }; - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ constructing invalid value at .0: encountered uninitialized bytes, but expected initialized bytes + | ^^^^^^^^^^^^^^^^^^^^^^^ constructing invalid value at .0: encountered uninitialized bytes, but expected initialized bytes | = note: The rules on what exactly is undefined behavior aren't clear, so this check might be overzealous. Please open an issue on the rustc repository if you believe it should not be considered undefined behavior. = note: the raw bytes of the constant (size: 1, align: 1) { @@ -52,7 +52,7 @@ error[E0080]: it is undefined behavior to use this value --> $DIR/ub-nonnull.rs:41:1 | LL | const BAD_RANGE1: RestrictedRange1 = unsafe { RestrictedRange1(42) }; - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ constructing invalid value: encountered 42, but expected something in the range 10..=30 + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ constructing invalid value: encountered 42, but expected something in the range 10..=30 | = note: The rules on what exactly is undefined behavior aren't clear, so this check might be overzealous. Please open an issue on the rustc repository if you believe it should not be considered undefined behavior. = note: the raw bytes of the constant (size: 4, align: 4) { @@ -63,7 +63,7 @@ error[E0080]: it is undefined behavior to use this value --> $DIR/ub-nonnull.rs:47:1 | LL | const BAD_RANGE2: RestrictedRange2 = unsafe { RestrictedRange2(20) }; - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ constructing invalid value: encountered 20, but expected something less or equal to 10, or greater or equal to 30 + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ constructing invalid value: encountered 20, but expected something less or equal to 10, or greater or equal to 30 | = note: The rules on what exactly is undefined behavior aren't clear, so this check might be overzealous. Please open an issue on the rustc repository if you believe it should not be considered undefined behavior. = note: the raw bytes of the constant (size: 4, align: 4) { diff --git a/src/test/ui/consts/const-eval/ub-ref-ptr.32bit.stderr b/src/test/ui/consts/const-eval/ub-ref-ptr.32bit.stderr index c9e101cb6e4..b60e3337b44 100644 --- a/src/test/ui/consts/const-eval/ub-ref-ptr.32bit.stderr +++ b/src/test/ui/consts/const-eval/ub-ref-ptr.32bit.stderr @@ -2,7 +2,7 @@ error[E0080]: it is undefined behavior to use this value --> $DIR/ub-ref-ptr.rs:13:1 | LL | const UNALIGNED: &u16 = unsafe { mem::transmute(&[0u8; 4]) }; - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ constructing invalid value: encountered an unaligned reference (required 2 byte alignment but found 1) + | ^^^^^^^^^^^^^^^^^^^^^ constructing invalid value: encountered an unaligned reference (required 2 byte alignment but found 1) | = note: The rules on what exactly is undefined behavior aren't clear, so this check might be overzealous. Please open an issue on the rustc repository if you believe it should not be considered undefined behavior. = note: the raw bytes of the constant (size: 4, align: 4) { @@ -13,7 +13,7 @@ error[E0080]: it is undefined behavior to use this value --> $DIR/ub-ref-ptr.rs:17:1 | LL | const UNALIGNED_BOX: Box<u16> = unsafe { mem::transmute(&[0u8; 4]) }; - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ constructing invalid value: encountered an unaligned box (required 2 byte alignment but found 1) + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ constructing invalid value: encountered an unaligned box (required 2 byte alignment but found 1) | = note: The rules on what exactly is undefined behavior aren't clear, so this check might be overzealous. Please open an issue on the rustc repository if you believe it should not be considered undefined behavior. = note: the raw bytes of the constant (size: 4, align: 4) { @@ -24,7 +24,7 @@ error[E0080]: it is undefined behavior to use this value --> $DIR/ub-ref-ptr.rs:21:1 | LL | const NULL: &u16 = unsafe { mem::transmute(0usize) }; - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ constructing invalid value: encountered a null reference + | ^^^^^^^^^^^^^^^^ constructing invalid value: encountered a null reference | = note: The rules on what exactly is undefined behavior aren't clear, so this check might be overzealous. Please open an issue on the rustc repository if you believe it should not be considered undefined behavior. = note: the raw bytes of the constant (size: 4, align: 4) { @@ -35,7 +35,7 @@ error[E0080]: it is undefined behavior to use this value --> $DIR/ub-ref-ptr.rs:24:1 | LL | const NULL_BOX: Box<u16> = unsafe { mem::transmute(0usize) }; - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ constructing invalid value: encountered a null box + | ^^^^^^^^^^^^^^^^^^^^^^^^ constructing invalid value: encountered a null box | = note: The rules on what exactly is undefined behavior aren't clear, so this check might be overzealous. Please open an issue on the rustc repository if you believe it should not be considered undefined behavior. = note: the raw bytes of the constant (size: 4, align: 4) { @@ -46,7 +46,7 @@ error: any use of this value will cause an error --> $DIR/ub-ref-ptr.rs:31:1 | LL | const REF_AS_USIZE: usize = unsafe { mem::transmute(&0) }; - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ unable to turn pointer into raw bytes + | ^^^^^^^^^^^^^^^^^^^^^^^^^ unable to turn pointer into raw bytes | = note: `#[deny(const_err)]` on by default = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release! @@ -56,9 +56,7 @@ error: any use of this value will cause an error --> $DIR/ub-ref-ptr.rs:35:39 | LL | const REF_AS_USIZE_SLICE: &[usize] = &[unsafe { mem::transmute(&0) }]; - | --------------------------------------^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^- - | | - | unable to turn pointer into raw bytes + | ---------------------------------- ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ unable to turn pointer into raw bytes | = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release! = note: for more information, see issue #71800 <https://github.com/rust-lang/rust/issues/71800> @@ -67,9 +65,7 @@ error: any use of this value will cause an error --> $DIR/ub-ref-ptr.rs:35:38 | LL | const REF_AS_USIZE_SLICE: &[usize] = &[unsafe { mem::transmute(&0) }]; - | -------------------------------------^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^- - | | - | referenced constant has errors + | ---------------------------------- ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ referenced constant has errors | = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release! = note: for more information, see issue #71800 <https://github.com/rust-lang/rust/issues/71800> @@ -78,9 +74,7 @@ error: any use of this value will cause an error --> $DIR/ub-ref-ptr.rs:41:86 | LL | const REF_AS_USIZE_BOX_SLICE: Box<[usize]> = unsafe { mem::transmute::<&[usize], _>(&[mem::transmute(&0)]) }; - | -------------------------------------------------------------------------------------^^^^^^^^^^^^^^^^^^^^---- - | | - | unable to turn pointer into raw bytes + | ------------------------------------------ ^^^^^^^^^^^^^^^^^^^^ unable to turn pointer into raw bytes | = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release! = note: for more information, see issue #71800 <https://github.com/rust-lang/rust/issues/71800> @@ -89,9 +83,7 @@ error: any use of this value will cause an error --> $DIR/ub-ref-ptr.rs:41:85 | LL | const REF_AS_USIZE_BOX_SLICE: Box<[usize]> = unsafe { mem::transmute::<&[usize], _>(&[mem::transmute(&0)]) }; - | ------------------------------------------------------------------------------------^^^^^^^^^^^^^^^^^^^^^---- - | | - | referenced constant has errors + | ------------------------------------------ ^^^^^^^^^^^^^^^^^^^^^ referenced constant has errors | = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release! = note: for more information, see issue #71800 <https://github.com/rust-lang/rust/issues/71800> @@ -100,7 +92,7 @@ error[E0080]: it is undefined behavior to use this value --> $DIR/ub-ref-ptr.rs:47:1 | LL | const USIZE_AS_REF: &'static u8 = unsafe { mem::transmute(1337usize) }; - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ constructing invalid value: encountered a dangling reference (address 0x539 is unallocated) + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ constructing invalid value: encountered a dangling reference (address 0x539 is unallocated) | = note: The rules on what exactly is undefined behavior aren't clear, so this check might be overzealous. Please open an issue on the rustc repository if you believe it should not be considered undefined behavior. = note: the raw bytes of the constant (size: 4, align: 4) { @@ -111,7 +103,7 @@ error[E0080]: it is undefined behavior to use this value --> $DIR/ub-ref-ptr.rs:50:1 | LL | const USIZE_AS_BOX: Box<u8> = unsafe { mem::transmute(1337usize) }; - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ constructing invalid value: encountered a dangling box (address 0x539 is unallocated) + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^ constructing invalid value: encountered a dangling box (address 0x539 is unallocated) | = note: The rules on what exactly is undefined behavior aren't clear, so this check might be overzealous. Please open an issue on the rustc repository if you believe it should not be considered undefined behavior. = note: the raw bytes of the constant (size: 4, align: 4) { @@ -122,7 +114,7 @@ error[E0080]: it is undefined behavior to use this value --> $DIR/ub-ref-ptr.rs:53:1 | LL | const UNINIT_PTR: *const i32 = unsafe { MaybeUninit { uninit: () }.init }; - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ constructing invalid value: encountered uninitialized raw pointer + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ constructing invalid value: encountered uninitialized raw pointer | = note: The rules on what exactly is undefined behavior aren't clear, so this check might be overzealous. Please open an issue on the rustc repository if you believe it should not be considered undefined behavior. = note: the raw bytes of the constant (size: 4, align: 4) { @@ -133,7 +125,7 @@ error[E0080]: it is undefined behavior to use this value --> $DIR/ub-ref-ptr.rs:56:1 | LL | const NULL_FN_PTR: fn() = unsafe { mem::transmute(0usize) }; - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ constructing invalid value: encountered a null function pointer + | ^^^^^^^^^^^^^^^^^^^^^^^ constructing invalid value: encountered a null function pointer | = note: The rules on what exactly is undefined behavior aren't clear, so this check might be overzealous. Please open an issue on the rustc repository if you believe it should not be considered undefined behavior. = note: the raw bytes of the constant (size: 4, align: 4) { @@ -144,7 +136,7 @@ error[E0080]: it is undefined behavior to use this value --> $DIR/ub-ref-ptr.rs:58:1 | LL | const UNINIT_FN_PTR: fn() = unsafe { MaybeUninit { uninit: () }.init }; - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ constructing invalid value: encountered uninitialized bytes, but expected a proper pointer or integer value + | ^^^^^^^^^^^^^^^^^^^^^^^^^ constructing invalid value: encountered uninitialized bytes, but expected a proper pointer or integer value | = note: The rules on what exactly is undefined behavior aren't clear, so this check might be overzealous. Please open an issue on the rustc repository if you believe it should not be considered undefined behavior. = note: the raw bytes of the constant (size: 4, align: 4) { @@ -155,7 +147,7 @@ error[E0080]: it is undefined behavior to use this value --> $DIR/ub-ref-ptr.rs:60:1 | LL | const DANGLING_FN_PTR: fn() = unsafe { mem::transmute(13usize) }; - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ constructing invalid value: encountered 0x0000000d, but expected a function pointer + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^ constructing invalid value: encountered 0x0000000d, but expected a function pointer | = note: The rules on what exactly is undefined behavior aren't clear, so this check might be overzealous. Please open an issue on the rustc repository if you believe it should not be considered undefined behavior. = note: the raw bytes of the constant (size: 4, align: 4) { @@ -166,7 +158,7 @@ error[E0080]: it is undefined behavior to use this value --> $DIR/ub-ref-ptr.rs:62:1 | LL | const DATA_FN_PTR: fn() = unsafe { mem::transmute(&13) }; - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ constructing invalid value: encountered pointer to alloc43, but expected a function pointer + | ^^^^^^^^^^^^^^^^^^^^^^^ constructing invalid value: encountered pointer to alloc43, but expected a function pointer | = note: The rules on what exactly is undefined behavior aren't clear, so this check might be overzealous. Please open an issue on the rustc repository if you believe it should not be considered undefined behavior. = note: the raw bytes of the constant (size: 4, align: 4) { @@ -181,7 +173,7 @@ error: any use of this value will cause an error --> $DIR/ub-ref-ptr.rs:31:1 | LL | const REF_AS_USIZE: usize = unsafe { mem::transmute(&0) }; - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ unable to turn pointer into raw bytes + | ^^^^^^^^^^^^^^^^^^^^^^^^^ unable to turn pointer into raw bytes | = note: `#[deny(const_err)]` on by default = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release! @@ -192,9 +184,7 @@ error: any use of this value will cause an error --> $DIR/ub-ref-ptr.rs:35:39 | LL | const REF_AS_USIZE_SLICE: &[usize] = &[unsafe { mem::transmute(&0) }]; - | --------------------------------------^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^- - | | - | unable to turn pointer into raw bytes + | ---------------------------------- ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ unable to turn pointer into raw bytes | = note: `#[deny(const_err)]` on by default = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release! @@ -205,9 +195,7 @@ error: any use of this value will cause an error --> $DIR/ub-ref-ptr.rs:35:38 | LL | const REF_AS_USIZE_SLICE: &[usize] = &[unsafe { mem::transmute(&0) }]; - | -------------------------------------^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^- - | | - | referenced constant has errors + | ---------------------------------- ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ referenced constant has errors | = note: `#[deny(const_err)]` on by default = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release! @@ -218,9 +206,7 @@ error: any use of this value will cause an error --> $DIR/ub-ref-ptr.rs:41:86 | LL | const REF_AS_USIZE_BOX_SLICE: Box<[usize]> = unsafe { mem::transmute::<&[usize], _>(&[mem::transmute(&0)]) }; - | -------------------------------------------------------------------------------------^^^^^^^^^^^^^^^^^^^^---- - | | - | unable to turn pointer into raw bytes + | ------------------------------------------ ^^^^^^^^^^^^^^^^^^^^ unable to turn pointer into raw bytes | = note: `#[deny(const_err)]` on by default = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release! @@ -231,9 +217,7 @@ error: any use of this value will cause an error --> $DIR/ub-ref-ptr.rs:41:85 | LL | const REF_AS_USIZE_BOX_SLICE: Box<[usize]> = unsafe { mem::transmute::<&[usize], _>(&[mem::transmute(&0)]) }; - | ------------------------------------------------------------------------------------^^^^^^^^^^^^^^^^^^^^^---- - | | - | referenced constant has errors + | ------------------------------------------ ^^^^^^^^^^^^^^^^^^^^^ referenced constant has errors | = note: `#[deny(const_err)]` on by default = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release! diff --git a/src/test/ui/consts/const-eval/ub-ref-ptr.64bit.stderr b/src/test/ui/consts/const-eval/ub-ref-ptr.64bit.stderr index b3d9500333a..505ef2dd7d7 100644 --- a/src/test/ui/consts/const-eval/ub-ref-ptr.64bit.stderr +++ b/src/test/ui/consts/const-eval/ub-ref-ptr.64bit.stderr @@ -2,7 +2,7 @@ error[E0080]: it is undefined behavior to use this value --> $DIR/ub-ref-ptr.rs:13:1 | LL | const UNALIGNED: &u16 = unsafe { mem::transmute(&[0u8; 4]) }; - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ constructing invalid value: encountered an unaligned reference (required 2 byte alignment but found 1) + | ^^^^^^^^^^^^^^^^^^^^^ constructing invalid value: encountered an unaligned reference (required 2 byte alignment but found 1) | = note: The rules on what exactly is undefined behavior aren't clear, so this check might be overzealous. Please open an issue on the rustc repository if you believe it should not be considered undefined behavior. = note: the raw bytes of the constant (size: 8, align: 8) { @@ -13,7 +13,7 @@ error[E0080]: it is undefined behavior to use this value --> $DIR/ub-ref-ptr.rs:17:1 | LL | const UNALIGNED_BOX: Box<u16> = unsafe { mem::transmute(&[0u8; 4]) }; - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ constructing invalid value: encountered an unaligned box (required 2 byte alignment but found 1) + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ constructing invalid value: encountered an unaligned box (required 2 byte alignment but found 1) | = note: The rules on what exactly is undefined behavior aren't clear, so this check might be overzealous. Please open an issue on the rustc repository if you believe it should not be considered undefined behavior. = note: the raw bytes of the constant (size: 8, align: 8) { @@ -24,7 +24,7 @@ error[E0080]: it is undefined behavior to use this value --> $DIR/ub-ref-ptr.rs:21:1 | LL | const NULL: &u16 = unsafe { mem::transmute(0usize) }; - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ constructing invalid value: encountered a null reference + | ^^^^^^^^^^^^^^^^ constructing invalid value: encountered a null reference | = note: The rules on what exactly is undefined behavior aren't clear, so this check might be overzealous. Please open an issue on the rustc repository if you believe it should not be considered undefined behavior. = note: the raw bytes of the constant (size: 8, align: 8) { @@ -35,7 +35,7 @@ error[E0080]: it is undefined behavior to use this value --> $DIR/ub-ref-ptr.rs:24:1 | LL | const NULL_BOX: Box<u16> = unsafe { mem::transmute(0usize) }; - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ constructing invalid value: encountered a null box + | ^^^^^^^^^^^^^^^^^^^^^^^^ constructing invalid value: encountered a null box | = note: The rules on what exactly is undefined behavior aren't clear, so this check might be overzealous. Please open an issue on the rustc repository if you believe it should not be considered undefined behavior. = note: the raw bytes of the constant (size: 8, align: 8) { @@ -46,7 +46,7 @@ error: any use of this value will cause an error --> $DIR/ub-ref-ptr.rs:31:1 | LL | const REF_AS_USIZE: usize = unsafe { mem::transmute(&0) }; - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ unable to turn pointer into raw bytes + | ^^^^^^^^^^^^^^^^^^^^^^^^^ unable to turn pointer into raw bytes | = note: `#[deny(const_err)]` on by default = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release! @@ -56,9 +56,7 @@ error: any use of this value will cause an error --> $DIR/ub-ref-ptr.rs:35:39 | LL | const REF_AS_USIZE_SLICE: &[usize] = &[unsafe { mem::transmute(&0) }]; - | --------------------------------------^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^- - | | - | unable to turn pointer into raw bytes + | ---------------------------------- ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ unable to turn pointer into raw bytes | = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release! = note: for more information, see issue #71800 <https://github.com/rust-lang/rust/issues/71800> @@ -67,9 +65,7 @@ error: any use of this value will cause an error --> $DIR/ub-ref-ptr.rs:35:38 | LL | const REF_AS_USIZE_SLICE: &[usize] = &[unsafe { mem::transmute(&0) }]; - | -------------------------------------^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^- - | | - | referenced constant has errors + | ---------------------------------- ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ referenced constant has errors | = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release! = note: for more information, see issue #71800 <https://github.com/rust-lang/rust/issues/71800> @@ -78,9 +74,7 @@ error: any use of this value will cause an error --> $DIR/ub-ref-ptr.rs:41:86 | LL | const REF_AS_USIZE_BOX_SLICE: Box<[usize]> = unsafe { mem::transmute::<&[usize], _>(&[mem::transmute(&0)]) }; - | -------------------------------------------------------------------------------------^^^^^^^^^^^^^^^^^^^^---- - | | - | unable to turn pointer into raw bytes + | ------------------------------------------ ^^^^^^^^^^^^^^^^^^^^ unable to turn pointer into raw bytes | = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release! = note: for more information, see issue #71800 <https://github.com/rust-lang/rust/issues/71800> @@ -89,9 +83,7 @@ error: any use of this value will cause an error --> $DIR/ub-ref-ptr.rs:41:85 | LL | const REF_AS_USIZE_BOX_SLICE: Box<[usize]> = unsafe { mem::transmute::<&[usize], _>(&[mem::transmute(&0)]) }; - | ------------------------------------------------------------------------------------^^^^^^^^^^^^^^^^^^^^^---- - | | - | referenced constant has errors + | ------------------------------------------ ^^^^^^^^^^^^^^^^^^^^^ referenced constant has errors | = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release! = note: for more information, see issue #71800 <https://github.com/rust-lang/rust/issues/71800> @@ -100,7 +92,7 @@ error[E0080]: it is undefined behavior to use this value --> $DIR/ub-ref-ptr.rs:47:1 | LL | const USIZE_AS_REF: &'static u8 = unsafe { mem::transmute(1337usize) }; - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ constructing invalid value: encountered a dangling reference (address 0x539 is unallocated) + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ constructing invalid value: encountered a dangling reference (address 0x539 is unallocated) | = note: The rules on what exactly is undefined behavior aren't clear, so this check might be overzealous. Please open an issue on the rustc repository if you believe it should not be considered undefined behavior. = note: the raw bytes of the constant (size: 8, align: 8) { @@ -111,7 +103,7 @@ error[E0080]: it is undefined behavior to use this value --> $DIR/ub-ref-ptr.rs:50:1 | LL | const USIZE_AS_BOX: Box<u8> = unsafe { mem::transmute(1337usize) }; - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ constructing invalid value: encountered a dangling box (address 0x539 is unallocated) + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^ constructing invalid value: encountered a dangling box (address 0x539 is unallocated) | = note: The rules on what exactly is undefined behavior aren't clear, so this check might be overzealous. Please open an issue on the rustc repository if you believe it should not be considered undefined behavior. = note: the raw bytes of the constant (size: 8, align: 8) { @@ -122,7 +114,7 @@ error[E0080]: it is undefined behavior to use this value --> $DIR/ub-ref-ptr.rs:53:1 | LL | const UNINIT_PTR: *const i32 = unsafe { MaybeUninit { uninit: () }.init }; - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ constructing invalid value: encountered uninitialized raw pointer + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ constructing invalid value: encountered uninitialized raw pointer | = note: The rules on what exactly is undefined behavior aren't clear, so this check might be overzealous. Please open an issue on the rustc repository if you believe it should not be considered undefined behavior. = note: the raw bytes of the constant (size: 8, align: 8) { @@ -133,7 +125,7 @@ error[E0080]: it is undefined behavior to use this value --> $DIR/ub-ref-ptr.rs:56:1 | LL | const NULL_FN_PTR: fn() = unsafe { mem::transmute(0usize) }; - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ constructing invalid value: encountered a null function pointer + | ^^^^^^^^^^^^^^^^^^^^^^^ constructing invalid value: encountered a null function pointer | = note: The rules on what exactly is undefined behavior aren't clear, so this check might be overzealous. Please open an issue on the rustc repository if you believe it should not be considered undefined behavior. = note: the raw bytes of the constant (size: 8, align: 8) { @@ -144,7 +136,7 @@ error[E0080]: it is undefined behavior to use this value --> $DIR/ub-ref-ptr.rs:58:1 | LL | const UNINIT_FN_PTR: fn() = unsafe { MaybeUninit { uninit: () }.init }; - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ constructing invalid value: encountered uninitialized bytes, but expected a proper pointer or integer value + | ^^^^^^^^^^^^^^^^^^^^^^^^^ constructing invalid value: encountered uninitialized bytes, but expected a proper pointer or integer value | = note: The rules on what exactly is undefined behavior aren't clear, so this check might be overzealous. Please open an issue on the rustc repository if you believe it should not be considered undefined behavior. = note: the raw bytes of the constant (size: 8, align: 8) { @@ -155,7 +147,7 @@ error[E0080]: it is undefined behavior to use this value --> $DIR/ub-ref-ptr.rs:60:1 | LL | const DANGLING_FN_PTR: fn() = unsafe { mem::transmute(13usize) }; - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ constructing invalid value: encountered 0x000000000000000d, but expected a function pointer + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^ constructing invalid value: encountered 0x000000000000000d, but expected a function pointer | = note: The rules on what exactly is undefined behavior aren't clear, so this check might be overzealous. Please open an issue on the rustc repository if you believe it should not be considered undefined behavior. = note: the raw bytes of the constant (size: 8, align: 8) { @@ -166,7 +158,7 @@ error[E0080]: it is undefined behavior to use this value --> $DIR/ub-ref-ptr.rs:62:1 | LL | const DATA_FN_PTR: fn() = unsafe { mem::transmute(&13) }; - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ constructing invalid value: encountered pointer to alloc43, but expected a function pointer + | ^^^^^^^^^^^^^^^^^^^^^^^ constructing invalid value: encountered pointer to alloc43, but expected a function pointer | = note: The rules on what exactly is undefined behavior aren't clear, so this check might be overzealous. Please open an issue on the rustc repository if you believe it should not be considered undefined behavior. = note: the raw bytes of the constant (size: 8, align: 8) { @@ -181,7 +173,7 @@ error: any use of this value will cause an error --> $DIR/ub-ref-ptr.rs:31:1 | LL | const REF_AS_USIZE: usize = unsafe { mem::transmute(&0) }; - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ unable to turn pointer into raw bytes + | ^^^^^^^^^^^^^^^^^^^^^^^^^ unable to turn pointer into raw bytes | = note: `#[deny(const_err)]` on by default = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release! @@ -192,9 +184,7 @@ error: any use of this value will cause an error --> $DIR/ub-ref-ptr.rs:35:39 | LL | const REF_AS_USIZE_SLICE: &[usize] = &[unsafe { mem::transmute(&0) }]; - | --------------------------------------^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^- - | | - | unable to turn pointer into raw bytes + | ---------------------------------- ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ unable to turn pointer into raw bytes | = note: `#[deny(const_err)]` on by default = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release! @@ -205,9 +195,7 @@ error: any use of this value will cause an error --> $DIR/ub-ref-ptr.rs:35:38 | LL | const REF_AS_USIZE_SLICE: &[usize] = &[unsafe { mem::transmute(&0) }]; - | -------------------------------------^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^- - | | - | referenced constant has errors + | ---------------------------------- ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ referenced constant has errors | = note: `#[deny(const_err)]` on by default = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release! @@ -218,9 +206,7 @@ error: any use of this value will cause an error --> $DIR/ub-ref-ptr.rs:41:86 | LL | const REF_AS_USIZE_BOX_SLICE: Box<[usize]> = unsafe { mem::transmute::<&[usize], _>(&[mem::transmute(&0)]) }; - | -------------------------------------------------------------------------------------^^^^^^^^^^^^^^^^^^^^---- - | | - | unable to turn pointer into raw bytes + | ------------------------------------------ ^^^^^^^^^^^^^^^^^^^^ unable to turn pointer into raw bytes | = note: `#[deny(const_err)]` on by default = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release! @@ -231,9 +217,7 @@ error: any use of this value will cause an error --> $DIR/ub-ref-ptr.rs:41:85 | LL | const REF_AS_USIZE_BOX_SLICE: Box<[usize]> = unsafe { mem::transmute::<&[usize], _>(&[mem::transmute(&0)]) }; - | ------------------------------------------------------------------------------------^^^^^^^^^^^^^^^^^^^^^---- - | | - | referenced constant has errors + | ------------------------------------------ ^^^^^^^^^^^^^^^^^^^^^ referenced constant has errors | = note: `#[deny(const_err)]` on by default = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release! diff --git a/src/test/ui/consts/const-eval/ub-uninhabit.32bit.stderr b/src/test/ui/consts/const-eval/ub-uninhabit.32bit.stderr index 38c71c20fa5..7f0feb13004 100644 --- a/src/test/ui/consts/const-eval/ub-uninhabit.32bit.stderr +++ b/src/test/ui/consts/const-eval/ub-uninhabit.32bit.stderr @@ -2,7 +2,7 @@ error[E0080]: it is undefined behavior to use this value --> $DIR/ub-uninhabit.rs:15:1 | LL | const BAD_BAD_BAD: Bar = unsafe { MaybeUninit { uninit: () }.init }; - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ constructing invalid value: encountered a value of uninhabited type Bar + | ^^^^^^^^^^^^^^^^^^^^^^ constructing invalid value: encountered a value of uninhabited type Bar | = note: The rules on what exactly is undefined behavior aren't clear, so this check might be overzealous. Please open an issue on the rustc repository if you believe it should not be considered undefined behavior. = note: the raw bytes of the constant (size: 0, align: 1) {} @@ -11,7 +11,7 @@ error[E0080]: it is undefined behavior to use this value --> $DIR/ub-uninhabit.rs:18:1 | LL | const BAD_BAD_REF: &Bar = unsafe { mem::transmute(1usize) }; - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ constructing invalid value: encountered a reference pointing to uninhabited type Bar + | ^^^^^^^^^^^^^^^^^^^^^^^ constructing invalid value: encountered a reference pointing to uninhabited type Bar | = note: The rules on what exactly is undefined behavior aren't clear, so this check might be overzealous. Please open an issue on the rustc repository if you believe it should not be considered undefined behavior. = note: the raw bytes of the constant (size: 4, align: 4) { @@ -22,7 +22,7 @@ error[E0080]: it is undefined behavior to use this value --> $DIR/ub-uninhabit.rs:21:1 | LL | const BAD_BAD_ARRAY: [Bar; 1] = unsafe { MaybeUninit { uninit: () }.init }; - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ constructing invalid value at [0]: encountered a value of uninhabited type Bar + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ constructing invalid value at [0]: encountered a value of uninhabited type Bar | = note: The rules on what exactly is undefined behavior aren't clear, so this check might be overzealous. Please open an issue on the rustc repository if you believe it should not be considered undefined behavior. = note: the raw bytes of the constant (size: 0, align: 1) {} diff --git a/src/test/ui/consts/const-eval/ub-uninhabit.64bit.stderr b/src/test/ui/consts/const-eval/ub-uninhabit.64bit.stderr index 7cfa888b1a1..4dcbbc2f5e4 100644 --- a/src/test/ui/consts/const-eval/ub-uninhabit.64bit.stderr +++ b/src/test/ui/consts/const-eval/ub-uninhabit.64bit.stderr @@ -2,7 +2,7 @@ error[E0080]: it is undefined behavior to use this value --> $DIR/ub-uninhabit.rs:15:1 | LL | const BAD_BAD_BAD: Bar = unsafe { MaybeUninit { uninit: () }.init }; - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ constructing invalid value: encountered a value of uninhabited type Bar + | ^^^^^^^^^^^^^^^^^^^^^^ constructing invalid value: encountered a value of uninhabited type Bar | = note: The rules on what exactly is undefined behavior aren't clear, so this check might be overzealous. Please open an issue on the rustc repository if you believe it should not be considered undefined behavior. = note: the raw bytes of the constant (size: 0, align: 1) {} @@ -11,7 +11,7 @@ error[E0080]: it is undefined behavior to use this value --> $DIR/ub-uninhabit.rs:18:1 | LL | const BAD_BAD_REF: &Bar = unsafe { mem::transmute(1usize) }; - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ constructing invalid value: encountered a reference pointing to uninhabited type Bar + | ^^^^^^^^^^^^^^^^^^^^^^^ constructing invalid value: encountered a reference pointing to uninhabited type Bar | = note: The rules on what exactly is undefined behavior aren't clear, so this check might be overzealous. Please open an issue on the rustc repository if you believe it should not be considered undefined behavior. = note: the raw bytes of the constant (size: 8, align: 8) { @@ -22,7 +22,7 @@ error[E0080]: it is undefined behavior to use this value --> $DIR/ub-uninhabit.rs:21:1 | LL | const BAD_BAD_ARRAY: [Bar; 1] = unsafe { MaybeUninit { uninit: () }.init }; - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ constructing invalid value at [0]: encountered a value of uninhabited type Bar + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ constructing invalid value at [0]: encountered a value of uninhabited type Bar | = note: The rules on what exactly is undefined behavior aren't clear, so this check might be overzealous. Please open an issue on the rustc repository if you believe it should not be considered undefined behavior. = note: the raw bytes of the constant (size: 0, align: 1) {} diff --git a/src/test/ui/consts/const-eval/ub-upvars.32bit.stderr b/src/test/ui/consts/const-eval/ub-upvars.32bit.stderr index d7de743afa9..43f73f6ec7f 100644 --- a/src/test/ui/consts/const-eval/ub-upvars.32bit.stderr +++ b/src/test/ui/consts/const-eval/ub-upvars.32bit.stderr @@ -1,12 +1,8 @@ error[E0080]: it is undefined behavior to use this value --> $DIR/ub-upvars.rs:6:1 | -LL | / const BAD_UPVAR: &dyn FnOnce() = &{ -LL | | let bad_ref: &'static u16 = unsafe { mem::transmute(0usize) }; -LL | | let another_var = 13; -LL | | move || { let _ = bad_ref; let _ = another_var; } -LL | | }; - | |__^ constructing invalid value at .<deref>.<dyn-downcast>.<captured-var(bad_ref)>: encountered a null reference +LL | const BAD_UPVAR: &dyn FnOnce() = &{ + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ constructing invalid value at .<deref>.<dyn-downcast>.<captured-var(bad_ref)>: encountered a null reference | = note: The rules on what exactly is undefined behavior aren't clear, so this check might be overzealous. Please open an issue on the rustc repository if you believe it should not be considered undefined behavior. = note: the raw bytes of the constant (size: 8, align: 4) { diff --git a/src/test/ui/consts/const-eval/ub-upvars.64bit.stderr b/src/test/ui/consts/const-eval/ub-upvars.64bit.stderr index 6df58f6eaae..64185a06362 100644 --- a/src/test/ui/consts/const-eval/ub-upvars.64bit.stderr +++ b/src/test/ui/consts/const-eval/ub-upvars.64bit.stderr @@ -1,12 +1,8 @@ error[E0080]: it is undefined behavior to use this value --> $DIR/ub-upvars.rs:6:1 | -LL | / const BAD_UPVAR: &dyn FnOnce() = &{ -LL | | let bad_ref: &'static u16 = unsafe { mem::transmute(0usize) }; -LL | | let another_var = 13; -LL | | move || { let _ = bad_ref; let _ = another_var; } -LL | | }; - | |__^ constructing invalid value at .<deref>.<dyn-downcast>.<captured-var(bad_ref)>: encountered a null reference +LL | const BAD_UPVAR: &dyn FnOnce() = &{ + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ constructing invalid value at .<deref>.<dyn-downcast>.<captured-var(bad_ref)>: encountered a null reference | = note: The rules on what exactly is undefined behavior aren't clear, so this check might be overzealous. Please open an issue on the rustc repository if you believe it should not be considered undefined behavior. = note: the raw bytes of the constant (size: 16, align: 8) { diff --git a/src/test/ui/consts/const-eval/ub-wide-ptr.32bit.stderr b/src/test/ui/consts/const-eval/ub-wide-ptr.32bit.stderr index 25062a5a396..2fd98ea322b 100644 --- a/src/test/ui/consts/const-eval/ub-wide-ptr.32bit.stderr +++ b/src/test/ui/consts/const-eval/ub-wide-ptr.32bit.stderr @@ -2,7 +2,7 @@ error[E0080]: it is undefined behavior to use this value --> $DIR/ub-wide-ptr.rs:37:1 | LL | const STR_TOO_LONG: &str = unsafe { mem::transmute((&42u8, 999usize)) }; - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ constructing invalid value: encountered a dangling reference (going beyond the bounds of its allocation) + | ^^^^^^^^^^^^^^^^^^^^^^^^ constructing invalid value: encountered a dangling reference (going beyond the bounds of its allocation) | = note: The rules on what exactly is undefined behavior aren't clear, so this check might be overzealous. Please open an issue on the rustc repository if you believe it should not be considered undefined behavior. = note: the raw bytes of the constant (size: 8, align: 4) { @@ -13,7 +13,7 @@ error[E0080]: it is undefined behavior to use this value --> $DIR/ub-wide-ptr.rs:39:1 | LL | const NESTED_STR_MUCH_TOO_LONG: (&str,) = (unsafe { mem::transmute((&42, usize::MAX)) },); - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ constructing invalid value at .0: encountered invalid reference metadata: slice is bigger than largest supported object + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ constructing invalid value at .0: encountered invalid reference metadata: slice is bigger than largest supported object | = note: The rules on what exactly is undefined behavior aren't clear, so this check might be overzealous. Please open an issue on the rustc repository if you believe it should not be considered undefined behavior. = note: the raw bytes of the constant (size: 8, align: 4) { @@ -24,7 +24,7 @@ error: any use of this value will cause an error --> $DIR/ub-wide-ptr.rs:42:1 | LL | const STR_LENGTH_PTR: &str = unsafe { mem::transmute((&42u8, &3)) }; - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ unable to turn pointer into raw bytes + | ^^^^^^^^^^^^^^^^^^^^^^^^^^ unable to turn pointer into raw bytes | = note: `#[deny(const_err)]` on by default = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release! @@ -34,7 +34,7 @@ error: any use of this value will cause an error --> $DIR/ub-wide-ptr.rs:46:1 | LL | const MY_STR_LENGTH_PTR: &MyStr = unsafe { mem::transmute((&42u8, &3)) }; - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ unable to turn pointer into raw bytes + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ unable to turn pointer into raw bytes | = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release! = note: for more information, see issue #71800 <https://github.com/rust-lang/rust/issues/71800> @@ -43,7 +43,7 @@ error[E0080]: it is undefined behavior to use this value --> $DIR/ub-wide-ptr.rs:49:1 | LL | const MY_STR_MUCH_TOO_LONG: &MyStr = unsafe { mem::transmute((&42u8, usize::MAX)) }; - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ constructing invalid value: encountered invalid reference metadata: slice is bigger than largest supported object + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ constructing invalid value: encountered invalid reference metadata: slice is bigger than largest supported object | = note: The rules on what exactly is undefined behavior aren't clear, so this check might be overzealous. Please open an issue on the rustc repository if you believe it should not be considered undefined behavior. = note: the raw bytes of the constant (size: 8, align: 4) { @@ -54,7 +54,7 @@ error[E0080]: it is undefined behavior to use this value --> $DIR/ub-wide-ptr.rs:53:1 | LL | const STR_NO_INIT: &str = unsafe { mem::transmute::<&[_], _>(&[MaybeUninit::<u8> { uninit: () }]) }; - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ constructing invalid value at .<deref>: encountered uninitialized data in `str` + | ^^^^^^^^^^^^^^^^^^^^^^^ constructing invalid value at .<deref>: encountered uninitialized data in `str` | = note: The rules on what exactly is undefined behavior aren't clear, so this check might be overzealous. Please open an issue on the rustc repository if you believe it should not be considered undefined behavior. = note: the raw bytes of the constant (size: 8, align: 4) { @@ -65,7 +65,7 @@ error[E0080]: it is undefined behavior to use this value --> $DIR/ub-wide-ptr.rs:56:1 | LL | const MYSTR_NO_INIT: &MyStr = unsafe { mem::transmute::<&[_], _>(&[MaybeUninit::<u8> { uninit: () }]) }; - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ constructing invalid value at .<deref>.0: encountered uninitialized data in `str` + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^ constructing invalid value at .<deref>.0: encountered uninitialized data in `str` | = note: The rules on what exactly is undefined behavior aren't clear, so this check might be overzealous. Please open an issue on the rustc repository if you believe it should not be considered undefined behavior. = note: the raw bytes of the constant (size: 8, align: 4) { @@ -75,12 +75,8 @@ LL | const MYSTR_NO_INIT: &MyStr = unsafe { mem::transmute::<&[_], _>(&[MaybeUni error[E0080]: it is undefined behavior to use this value --> $DIR/ub-wide-ptr.rs:63:1 | -LL | / const SLICE_LENGTH_UNINIT: &[u8] = unsafe { -LL | | -LL | | let uninit_len = MaybeUninit::<usize> { uninit: () }; -LL | | mem::transmute((42, uninit_len)) -LL | | }; - | |__^ constructing invalid value: encountered uninitialized reference +LL | const SLICE_LENGTH_UNINIT: &[u8] = unsafe { + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ constructing invalid value: encountered uninitialized reference | = note: The rules on what exactly is undefined behavior aren't clear, so this check might be overzealous. Please open an issue on the rustc repository if you believe it should not be considered undefined behavior. = note: the raw bytes of the constant (size: 8, align: 4) { @@ -91,7 +87,7 @@ error[E0080]: it is undefined behavior to use this value --> $DIR/ub-wide-ptr.rs:69:1 | LL | const SLICE_TOO_LONG: &[u8] = unsafe { mem::transmute((&42u8, 999usize)) }; - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ constructing invalid value: encountered a dangling reference (going beyond the bounds of its allocation) + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^ constructing invalid value: encountered a dangling reference (going beyond the bounds of its allocation) | = note: The rules on what exactly is undefined behavior aren't clear, so this check might be overzealous. Please open an issue on the rustc repository if you believe it should not be considered undefined behavior. = note: the raw bytes of the constant (size: 8, align: 4) { @@ -102,7 +98,7 @@ error[E0080]: it is undefined behavior to use this value --> $DIR/ub-wide-ptr.rs:72:1 | LL | const SLICE_TOO_LONG_OVERFLOW: &[u32] = unsafe { mem::transmute((&42u32, isize::MAX)) }; - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ constructing invalid value: encountered invalid reference metadata: slice is bigger than largest supported object + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ constructing invalid value: encountered invalid reference metadata: slice is bigger than largest supported object | = note: The rules on what exactly is undefined behavior aren't clear, so this check might be overzealous. Please open an issue on the rustc repository if you believe it should not be considered undefined behavior. = note: the raw bytes of the constant (size: 8, align: 4) { @@ -113,7 +109,7 @@ error: any use of this value will cause an error --> $DIR/ub-wide-ptr.rs:75:1 | LL | const SLICE_LENGTH_PTR: &[u8] = unsafe { mem::transmute((&42u8, &3)) }; - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ unable to turn pointer into raw bytes + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ unable to turn pointer into raw bytes | = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release! = note: for more information, see issue #71800 <https://github.com/rust-lang/rust/issues/71800> @@ -122,7 +118,7 @@ error[E0080]: it is undefined behavior to use this value --> $DIR/ub-wide-ptr.rs:79:1 | LL | const SLICE_TOO_LONG_BOX: Box<[u8]> = unsafe { mem::transmute((&42u8, 999usize)) }; - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ constructing invalid value: encountered a dangling box (going beyond the bounds of its allocation) + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ constructing invalid value: encountered a dangling box (going beyond the bounds of its allocation) | = note: The rules on what exactly is undefined behavior aren't clear, so this check might be overzealous. Please open an issue on the rustc repository if you believe it should not be considered undefined behavior. = note: the raw bytes of the constant (size: 8, align: 4) { @@ -133,7 +129,7 @@ error: any use of this value will cause an error --> $DIR/ub-wide-ptr.rs:82:1 | LL | const SLICE_LENGTH_PTR_BOX: Box<[u8]> = unsafe { mem::transmute((&42u8, &3)) }; - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ unable to turn pointer into raw bytes + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ unable to turn pointer into raw bytes | = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release! = note: for more information, see issue #71800 <https://github.com/rust-lang/rust/issues/71800> @@ -142,7 +138,7 @@ error[E0080]: it is undefined behavior to use this value --> $DIR/ub-wide-ptr.rs:87:1 | LL | const SLICE_CONTENT_INVALID: &[bool] = &[unsafe { mem::transmute(3u8) }]; - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ constructing invalid value at .<deref>[0]: encountered 0x03, but expected a boolean + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ constructing invalid value at .<deref>[0]: encountered 0x03, but expected a boolean | = note: The rules on what exactly is undefined behavior aren't clear, so this check might be overzealous. Please open an issue on the rustc repository if you believe it should not be considered undefined behavior. = note: the raw bytes of the constant (size: 4, align: 4) { @@ -153,9 +149,7 @@ error: any use of this value will cause an error --> $DIR/ub-wide-ptr.rs:87:40 | LL | const SLICE_CONTENT_INVALID: &[bool] = &[unsafe { mem::transmute(3u8) }]; - | ---------------------------------------^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^- - | | - | referenced constant has errors + | ------------------------------------ ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ referenced constant has errors | = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release! = note: for more information, see issue #71800 <https://github.com/rust-lang/rust/issues/71800> @@ -164,7 +158,7 @@ error[E0080]: it is undefined behavior to use this value --> $DIR/ub-wide-ptr.rs:95:1 | LL | const MYSLICE_PREFIX_BAD: &MySliceBool = &MySlice(unsafe { mem::transmute(3u8) }, [false]); - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ constructing invalid value at .<deref>.0: encountered 0x03, but expected a boolean + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ constructing invalid value at .<deref>.0: encountered 0x03, but expected a boolean | = note: The rules on what exactly is undefined behavior aren't clear, so this check might be overzealous. Please open an issue on the rustc repository if you believe it should not be considered undefined behavior. = note: the raw bytes of the constant (size: 4, align: 4) { @@ -175,9 +169,7 @@ error: any use of this value will cause an error --> $DIR/ub-wide-ptr.rs:95:42 | LL | const MYSLICE_PREFIX_BAD: &MySliceBool = &MySlice(unsafe { mem::transmute(3u8) }, [false]); - | -----------------------------------------^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^- - | | - | referenced constant has errors + | -------------------------------------- ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ referenced constant has errors | = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release! = note: for more information, see issue #71800 <https://github.com/rust-lang/rust/issues/71800> @@ -186,7 +178,7 @@ error[E0080]: it is undefined behavior to use this value --> $DIR/ub-wide-ptr.rs:100:1 | LL | const MYSLICE_SUFFIX_BAD: &MySliceBool = &MySlice(true, [unsafe { mem::transmute(3u8) }]); - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ constructing invalid value at .<deref>.1[0]: encountered 0x03, but expected a boolean + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ constructing invalid value at .<deref>.1[0]: encountered 0x03, but expected a boolean | = note: The rules on what exactly is undefined behavior aren't clear, so this check might be overzealous. Please open an issue on the rustc repository if you believe it should not be considered undefined behavior. = note: the raw bytes of the constant (size: 4, align: 4) { @@ -197,9 +189,7 @@ error: any use of this value will cause an error --> $DIR/ub-wide-ptr.rs:100:42 | LL | const MYSLICE_SUFFIX_BAD: &MySliceBool = &MySlice(true, [unsafe { mem::transmute(3u8) }]); - | -----------------------------------------^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^- - | | - | referenced constant has errors + | -------------------------------------- ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ referenced constant has errors | = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release! = note: for more information, see issue #71800 <https://github.com/rust-lang/rust/issues/71800> @@ -207,12 +197,8 @@ LL | const MYSLICE_SUFFIX_BAD: &MySliceBool = &MySlice(true, [unsafe { mem::tran error[E0080]: it is undefined behavior to use this value --> $DIR/ub-wide-ptr.rs:109:1 | -LL | / const RAW_SLICE_LENGTH_UNINIT: *const [u8] = unsafe { -LL | | -LL | | let uninit_len = MaybeUninit::<usize> { uninit: () }; -LL | | mem::transmute((42, uninit_len)) -LL | | }; - | |__^ constructing invalid value: encountered uninitialized raw pointer +LL | const RAW_SLICE_LENGTH_UNINIT: *const [u8] = unsafe { + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ constructing invalid value: encountered uninitialized raw pointer | = note: The rules on what exactly is undefined behavior aren't clear, so this check might be overzealous. Please open an issue on the rustc repository if you believe it should not be considered undefined behavior. = note: the raw bytes of the constant (size: 8, align: 4) { @@ -223,7 +209,7 @@ error[E0080]: it is undefined behavior to use this value --> $DIR/ub-wide-ptr.rs:117:1 | LL | const TRAIT_OBJ_SHORT_VTABLE_1: W<&dyn Trait> = unsafe { mem::transmute(W((&92u8, &3u8))) }; - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ constructing invalid value at .0: encountered too small vtable + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ constructing invalid value at .0: encountered too small vtable | = note: The rules on what exactly is undefined behavior aren't clear, so this check might be overzealous. Please open an issue on the rustc repository if you believe it should not be considered undefined behavior. = note: the raw bytes of the constant (size: 8, align: 4) { @@ -234,7 +220,7 @@ error[E0080]: it is undefined behavior to use this value --> $DIR/ub-wide-ptr.rs:120:1 | LL | const TRAIT_OBJ_SHORT_VTABLE_2: W<&dyn Trait> = unsafe { mem::transmute(W((&92u8, &3u64))) }; - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ constructing invalid value at .0: encountered too small vtable + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ constructing invalid value at .0: encountered too small vtable | = note: The rules on what exactly is undefined behavior aren't clear, so this check might be overzealous. Please open an issue on the rustc repository if you believe it should not be considered undefined behavior. = note: the raw bytes of the constant (size: 8, align: 4) { @@ -245,7 +231,7 @@ error[E0080]: it is undefined behavior to use this value --> $DIR/ub-wide-ptr.rs:123:1 | LL | const TRAIT_OBJ_INT_VTABLE: W<&dyn Trait> = unsafe { mem::transmute(W((&92u8, 4usize))) }; - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ constructing invalid value at .0: encountered dangling vtable pointer in wide pointer + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ constructing invalid value at .0: encountered dangling vtable pointer in wide pointer | = note: The rules on what exactly is undefined behavior aren't clear, so this check might be overzealous. Please open an issue on the rustc repository if you believe it should not be considered undefined behavior. = note: the raw bytes of the constant (size: 8, align: 4) { @@ -256,7 +242,7 @@ error[E0080]: it is undefined behavior to use this value --> $DIR/ub-wide-ptr.rs:125:1 | LL | const TRAIT_OBJ_UNALIGNED_VTABLE: &dyn Trait = unsafe { mem::transmute((&92u8, &[0u8; 128])) }; - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ constructing invalid value: encountered unaligned vtable pointer in wide pointer + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ constructing invalid value: encountered unaligned vtable pointer in wide pointer | = note: The rules on what exactly is undefined behavior aren't clear, so this check might be overzealous. Please open an issue on the rustc repository if you believe it should not be considered undefined behavior. = note: the raw bytes of the constant (size: 8, align: 4) { @@ -267,7 +253,7 @@ error[E0080]: it is undefined behavior to use this value --> $DIR/ub-wide-ptr.rs:127:1 | LL | const TRAIT_OBJ_BAD_DROP_FN_NULL: &dyn Trait = unsafe { mem::transmute((&92u8, &[0usize; 8])) }; - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ constructing invalid value: encountered invalid drop function pointer in vtable (not pointing to a function) + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ constructing invalid value: encountered invalid drop function pointer in vtable (not pointing to a function) | = note: The rules on what exactly is undefined behavior aren't clear, so this check might be overzealous. Please open an issue on the rustc repository if you believe it should not be considered undefined behavior. = note: the raw bytes of the constant (size: 8, align: 4) { @@ -278,7 +264,7 @@ error[E0080]: it is undefined behavior to use this value --> $DIR/ub-wide-ptr.rs:129:1 | LL | const TRAIT_OBJ_BAD_DROP_FN_INT: &dyn Trait = unsafe { mem::transmute((&92u8, &[1usize; 8])) }; - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ constructing invalid value: encountered invalid drop function pointer in vtable (not pointing to a function) + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ constructing invalid value: encountered invalid drop function pointer in vtable (not pointing to a function) | = note: The rules on what exactly is undefined behavior aren't clear, so this check might be overzealous. Please open an issue on the rustc repository if you believe it should not be considered undefined behavior. = note: the raw bytes of the constant (size: 8, align: 4) { @@ -289,7 +275,7 @@ error[E0080]: it is undefined behavior to use this value --> $DIR/ub-wide-ptr.rs:131:1 | LL | const TRAIT_OBJ_BAD_DROP_FN_NOT_FN_PTR: W<&dyn Trait> = unsafe { mem::transmute(W((&92u8, &[&42u8; 8]))) }; - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ constructing invalid value at .0: encountered invalid drop function pointer in vtable (not pointing to a function) + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ constructing invalid value at .0: encountered invalid drop function pointer in vtable (not pointing to a function) | = note: The rules on what exactly is undefined behavior aren't clear, so this check might be overzealous. Please open an issue on the rustc repository if you believe it should not be considered undefined behavior. = note: the raw bytes of the constant (size: 8, align: 4) { @@ -300,7 +286,7 @@ error[E0080]: it is undefined behavior to use this value --> $DIR/ub-wide-ptr.rs:135:1 | LL | const TRAIT_OBJ_CONTENT_INVALID: &dyn Trait = unsafe { mem::transmute::<_, &bool>(&3u8) }; - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ constructing invalid value at .<deref>.<dyn-downcast>: encountered 0x03, but expected a boolean + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ constructing invalid value at .<deref>.<dyn-downcast>: encountered 0x03, but expected a boolean | = note: The rules on what exactly is undefined behavior aren't clear, so this check might be overzealous. Please open an issue on the rustc repository if you believe it should not be considered undefined behavior. = note: the raw bytes of the constant (size: 8, align: 4) { @@ -311,7 +297,7 @@ error[E0080]: it is undefined behavior to use this value --> $DIR/ub-wide-ptr.rs:139:1 | LL | const RAW_TRAIT_OBJ_VTABLE_NULL: *const dyn Trait = unsafe { mem::transmute((&92u8, 0usize)) }; - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ constructing invalid value: encountered dangling vtable pointer in wide pointer + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ constructing invalid value: encountered dangling vtable pointer in wide pointer | = note: The rules on what exactly is undefined behavior aren't clear, so this check might be overzealous. Please open an issue on the rustc repository if you believe it should not be considered undefined behavior. = note: the raw bytes of the constant (size: 8, align: 4) { @@ -322,7 +308,7 @@ error[E0080]: it is undefined behavior to use this value --> $DIR/ub-wide-ptr.rs:141:1 | LL | const RAW_TRAIT_OBJ_VTABLE_INVALID: *const dyn Trait = unsafe { mem::transmute((&92u8, &3u64)) }; - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ constructing invalid value: encountered too small vtable + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ constructing invalid value: encountered too small vtable | = note: The rules on what exactly is undefined behavior aren't clear, so this check might be overzealous. Please open an issue on the rustc repository if you believe it should not be considered undefined behavior. = note: the raw bytes of the constant (size: 8, align: 4) { @@ -333,7 +319,7 @@ error[E0080]: could not evaluate static initializer --> $DIR/ub-wide-ptr.rs:147:5 | LL | mem::transmute::<_, &dyn Trait>((&92u8, 0usize)) - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ memory access failed: null pointer is not a valid pointer + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ memory access failed: null pointer is a dangling pointer (it has no provenance) error[E0080]: could not evaluate static initializer --> $DIR/ub-wide-ptr.rs:151:5 @@ -349,7 +335,7 @@ error: any use of this value will cause an error --> $DIR/ub-wide-ptr.rs:42:1 | LL | const STR_LENGTH_PTR: &str = unsafe { mem::transmute((&42u8, &3)) }; - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ unable to turn pointer into raw bytes + | ^^^^^^^^^^^^^^^^^^^^^^^^^^ unable to turn pointer into raw bytes | = note: `#[deny(const_err)]` on by default = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release! @@ -360,7 +346,7 @@ error: any use of this value will cause an error --> $DIR/ub-wide-ptr.rs:46:1 | LL | const MY_STR_LENGTH_PTR: &MyStr = unsafe { mem::transmute((&42u8, &3)) }; - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ unable to turn pointer into raw bytes + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ unable to turn pointer into raw bytes | = note: `#[deny(const_err)]` on by default = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release! @@ -371,7 +357,7 @@ error: any use of this value will cause an error --> $DIR/ub-wide-ptr.rs:75:1 | LL | const SLICE_LENGTH_PTR: &[u8] = unsafe { mem::transmute((&42u8, &3)) }; - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ unable to turn pointer into raw bytes + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ unable to turn pointer into raw bytes | = note: `#[deny(const_err)]` on by default = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release! @@ -382,7 +368,7 @@ error: any use of this value will cause an error --> $DIR/ub-wide-ptr.rs:82:1 | LL | const SLICE_LENGTH_PTR_BOX: Box<[u8]> = unsafe { mem::transmute((&42u8, &3)) }; - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ unable to turn pointer into raw bytes + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ unable to turn pointer into raw bytes | = note: `#[deny(const_err)]` on by default = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release! @@ -393,9 +379,7 @@ error: any use of this value will cause an error --> $DIR/ub-wide-ptr.rs:87:40 | LL | const SLICE_CONTENT_INVALID: &[bool] = &[unsafe { mem::transmute(3u8) }]; - | ---------------------------------------^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^- - | | - | referenced constant has errors + | ------------------------------------ ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ referenced constant has errors | = note: `#[deny(const_err)]` on by default = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release! @@ -406,9 +390,7 @@ error: any use of this value will cause an error --> $DIR/ub-wide-ptr.rs:95:42 | LL | const MYSLICE_PREFIX_BAD: &MySliceBool = &MySlice(unsafe { mem::transmute(3u8) }, [false]); - | -----------------------------------------^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^- - | | - | referenced constant has errors + | -------------------------------------- ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ referenced constant has errors | = note: `#[deny(const_err)]` on by default = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release! @@ -419,9 +401,7 @@ error: any use of this value will cause an error --> $DIR/ub-wide-ptr.rs:100:42 | LL | const MYSLICE_SUFFIX_BAD: &MySliceBool = &MySlice(true, [unsafe { mem::transmute(3u8) }]); - | -----------------------------------------^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^- - | | - | referenced constant has errors + | -------------------------------------- ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ referenced constant has errors | = note: `#[deny(const_err)]` on by default = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release! diff --git a/src/test/ui/consts/const-eval/ub-wide-ptr.64bit.stderr b/src/test/ui/consts/const-eval/ub-wide-ptr.64bit.stderr index e3a9214b1a5..bae24907659 100644 --- a/src/test/ui/consts/const-eval/ub-wide-ptr.64bit.stderr +++ b/src/test/ui/consts/const-eval/ub-wide-ptr.64bit.stderr @@ -2,7 +2,7 @@ error[E0080]: it is undefined behavior to use this value --> $DIR/ub-wide-ptr.rs:37:1 | LL | const STR_TOO_LONG: &str = unsafe { mem::transmute((&42u8, 999usize)) }; - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ constructing invalid value: encountered a dangling reference (going beyond the bounds of its allocation) + | ^^^^^^^^^^^^^^^^^^^^^^^^ constructing invalid value: encountered a dangling reference (going beyond the bounds of its allocation) | = note: The rules on what exactly is undefined behavior aren't clear, so this check might be overzealous. Please open an issue on the rustc repository if you believe it should not be considered undefined behavior. = note: the raw bytes of the constant (size: 16, align: 8) { @@ -13,7 +13,7 @@ error[E0080]: it is undefined behavior to use this value --> $DIR/ub-wide-ptr.rs:39:1 | LL | const NESTED_STR_MUCH_TOO_LONG: (&str,) = (unsafe { mem::transmute((&42, usize::MAX)) },); - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ constructing invalid value at .0: encountered invalid reference metadata: slice is bigger than largest supported object + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ constructing invalid value at .0: encountered invalid reference metadata: slice is bigger than largest supported object | = note: The rules on what exactly is undefined behavior aren't clear, so this check might be overzealous. Please open an issue on the rustc repository if you believe it should not be considered undefined behavior. = note: the raw bytes of the constant (size: 16, align: 8) { @@ -24,7 +24,7 @@ error: any use of this value will cause an error --> $DIR/ub-wide-ptr.rs:42:1 | LL | const STR_LENGTH_PTR: &str = unsafe { mem::transmute((&42u8, &3)) }; - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ unable to turn pointer into raw bytes + | ^^^^^^^^^^^^^^^^^^^^^^^^^^ unable to turn pointer into raw bytes | = note: `#[deny(const_err)]` on by default = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release! @@ -34,7 +34,7 @@ error: any use of this value will cause an error --> $DIR/ub-wide-ptr.rs:46:1 | LL | const MY_STR_LENGTH_PTR: &MyStr = unsafe { mem::transmute((&42u8, &3)) }; - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ unable to turn pointer into raw bytes + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ unable to turn pointer into raw bytes | = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release! = note: for more information, see issue #71800 <https://github.com/rust-lang/rust/issues/71800> @@ -43,7 +43,7 @@ error[E0080]: it is undefined behavior to use this value --> $DIR/ub-wide-ptr.rs:49:1 | LL | const MY_STR_MUCH_TOO_LONG: &MyStr = unsafe { mem::transmute((&42u8, usize::MAX)) }; - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ constructing invalid value: encountered invalid reference metadata: slice is bigger than largest supported object + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ constructing invalid value: encountered invalid reference metadata: slice is bigger than largest supported object | = note: The rules on what exactly is undefined behavior aren't clear, so this check might be overzealous. Please open an issue on the rustc repository if you believe it should not be considered undefined behavior. = note: the raw bytes of the constant (size: 16, align: 8) { @@ -54,7 +54,7 @@ error[E0080]: it is undefined behavior to use this value --> $DIR/ub-wide-ptr.rs:53:1 | LL | const STR_NO_INIT: &str = unsafe { mem::transmute::<&[_], _>(&[MaybeUninit::<u8> { uninit: () }]) }; - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ constructing invalid value at .<deref>: encountered uninitialized data in `str` + | ^^^^^^^^^^^^^^^^^^^^^^^ constructing invalid value at .<deref>: encountered uninitialized data in `str` | = note: The rules on what exactly is undefined behavior aren't clear, so this check might be overzealous. Please open an issue on the rustc repository if you believe it should not be considered undefined behavior. = note: the raw bytes of the constant (size: 16, align: 8) { @@ -65,7 +65,7 @@ error[E0080]: it is undefined behavior to use this value --> $DIR/ub-wide-ptr.rs:56:1 | LL | const MYSTR_NO_INIT: &MyStr = unsafe { mem::transmute::<&[_], _>(&[MaybeUninit::<u8> { uninit: () }]) }; - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ constructing invalid value at .<deref>.0: encountered uninitialized data in `str` + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^ constructing invalid value at .<deref>.0: encountered uninitialized data in `str` | = note: The rules on what exactly is undefined behavior aren't clear, so this check might be overzealous. Please open an issue on the rustc repository if you believe it should not be considered undefined behavior. = note: the raw bytes of the constant (size: 16, align: 8) { @@ -75,12 +75,8 @@ LL | const MYSTR_NO_INIT: &MyStr = unsafe { mem::transmute::<&[_], _>(&[MaybeUni error[E0080]: it is undefined behavior to use this value --> $DIR/ub-wide-ptr.rs:63:1 | -LL | / const SLICE_LENGTH_UNINIT: &[u8] = unsafe { -LL | | -LL | | let uninit_len = MaybeUninit::<usize> { uninit: () }; -LL | | mem::transmute((42, uninit_len)) -LL | | }; - | |__^ constructing invalid value: encountered uninitialized reference +LL | const SLICE_LENGTH_UNINIT: &[u8] = unsafe { + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ constructing invalid value: encountered uninitialized reference | = note: The rules on what exactly is undefined behavior aren't clear, so this check might be overzealous. Please open an issue on the rustc repository if you believe it should not be considered undefined behavior. = note: the raw bytes of the constant (size: 16, align: 8) { @@ -91,7 +87,7 @@ error[E0080]: it is undefined behavior to use this value --> $DIR/ub-wide-ptr.rs:69:1 | LL | const SLICE_TOO_LONG: &[u8] = unsafe { mem::transmute((&42u8, 999usize)) }; - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ constructing invalid value: encountered a dangling reference (going beyond the bounds of its allocation) + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^ constructing invalid value: encountered a dangling reference (going beyond the bounds of its allocation) | = note: The rules on what exactly is undefined behavior aren't clear, so this check might be overzealous. Please open an issue on the rustc repository if you believe it should not be considered undefined behavior. = note: the raw bytes of the constant (size: 16, align: 8) { @@ -102,7 +98,7 @@ error[E0080]: it is undefined behavior to use this value --> $DIR/ub-wide-ptr.rs:72:1 | LL | const SLICE_TOO_LONG_OVERFLOW: &[u32] = unsafe { mem::transmute((&42u32, isize::MAX)) }; - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ constructing invalid value: encountered invalid reference metadata: slice is bigger than largest supported object + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ constructing invalid value: encountered invalid reference metadata: slice is bigger than largest supported object | = note: The rules on what exactly is undefined behavior aren't clear, so this check might be overzealous. Please open an issue on the rustc repository if you believe it should not be considered undefined behavior. = note: the raw bytes of the constant (size: 16, align: 8) { @@ -113,7 +109,7 @@ error: any use of this value will cause an error --> $DIR/ub-wide-ptr.rs:75:1 | LL | const SLICE_LENGTH_PTR: &[u8] = unsafe { mem::transmute((&42u8, &3)) }; - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ unable to turn pointer into raw bytes + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ unable to turn pointer into raw bytes | = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release! = note: for more information, see issue #71800 <https://github.com/rust-lang/rust/issues/71800> @@ -122,7 +118,7 @@ error[E0080]: it is undefined behavior to use this value --> $DIR/ub-wide-ptr.rs:79:1 | LL | const SLICE_TOO_LONG_BOX: Box<[u8]> = unsafe { mem::transmute((&42u8, 999usize)) }; - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ constructing invalid value: encountered a dangling box (going beyond the bounds of its allocation) + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ constructing invalid value: encountered a dangling box (going beyond the bounds of its allocation) | = note: The rules on what exactly is undefined behavior aren't clear, so this check might be overzealous. Please open an issue on the rustc repository if you believe it should not be considered undefined behavior. = note: the raw bytes of the constant (size: 16, align: 8) { @@ -133,7 +129,7 @@ error: any use of this value will cause an error --> $DIR/ub-wide-ptr.rs:82:1 | LL | const SLICE_LENGTH_PTR_BOX: Box<[u8]> = unsafe { mem::transmute((&42u8, &3)) }; - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ unable to turn pointer into raw bytes + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ unable to turn pointer into raw bytes | = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release! = note: for more information, see issue #71800 <https://github.com/rust-lang/rust/issues/71800> @@ -142,7 +138,7 @@ error[E0080]: it is undefined behavior to use this value --> $DIR/ub-wide-ptr.rs:87:1 | LL | const SLICE_CONTENT_INVALID: &[bool] = &[unsafe { mem::transmute(3u8) }]; - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ constructing invalid value at .<deref>[0]: encountered 0x03, but expected a boolean + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ constructing invalid value at .<deref>[0]: encountered 0x03, but expected a boolean | = note: The rules on what exactly is undefined behavior aren't clear, so this check might be overzealous. Please open an issue on the rustc repository if you believe it should not be considered undefined behavior. = note: the raw bytes of the constant (size: 8, align: 8) { @@ -153,9 +149,7 @@ error: any use of this value will cause an error --> $DIR/ub-wide-ptr.rs:87:40 | LL | const SLICE_CONTENT_INVALID: &[bool] = &[unsafe { mem::transmute(3u8) }]; - | ---------------------------------------^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^- - | | - | referenced constant has errors + | ------------------------------------ ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ referenced constant has errors | = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release! = note: for more information, see issue #71800 <https://github.com/rust-lang/rust/issues/71800> @@ -164,7 +158,7 @@ error[E0080]: it is undefined behavior to use this value --> $DIR/ub-wide-ptr.rs:95:1 | LL | const MYSLICE_PREFIX_BAD: &MySliceBool = &MySlice(unsafe { mem::transmute(3u8) }, [false]); - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ constructing invalid value at .<deref>.0: encountered 0x03, but expected a boolean + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ constructing invalid value at .<deref>.0: encountered 0x03, but expected a boolean | = note: The rules on what exactly is undefined behavior aren't clear, so this check might be overzealous. Please open an issue on the rustc repository if you believe it should not be considered undefined behavior. = note: the raw bytes of the constant (size: 8, align: 8) { @@ -175,9 +169,7 @@ error: any use of this value will cause an error --> $DIR/ub-wide-ptr.rs:95:42 | LL | const MYSLICE_PREFIX_BAD: &MySliceBool = &MySlice(unsafe { mem::transmute(3u8) }, [false]); - | -----------------------------------------^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^- - | | - | referenced constant has errors + | -------------------------------------- ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ referenced constant has errors | = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release! = note: for more information, see issue #71800 <https://github.com/rust-lang/rust/issues/71800> @@ -186,7 +178,7 @@ error[E0080]: it is undefined behavior to use this value --> $DIR/ub-wide-ptr.rs:100:1 | LL | const MYSLICE_SUFFIX_BAD: &MySliceBool = &MySlice(true, [unsafe { mem::transmute(3u8) }]); - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ constructing invalid value at .<deref>.1[0]: encountered 0x03, but expected a boolean + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ constructing invalid value at .<deref>.1[0]: encountered 0x03, but expected a boolean | = note: The rules on what exactly is undefined behavior aren't clear, so this check might be overzealous. Please open an issue on the rustc repository if you believe it should not be considered undefined behavior. = note: the raw bytes of the constant (size: 8, align: 8) { @@ -197,9 +189,7 @@ error: any use of this value will cause an error --> $DIR/ub-wide-ptr.rs:100:42 | LL | const MYSLICE_SUFFIX_BAD: &MySliceBool = &MySlice(true, [unsafe { mem::transmute(3u8) }]); - | -----------------------------------------^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^- - | | - | referenced constant has errors + | -------------------------------------- ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ referenced constant has errors | = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release! = note: for more information, see issue #71800 <https://github.com/rust-lang/rust/issues/71800> @@ -207,12 +197,8 @@ LL | const MYSLICE_SUFFIX_BAD: &MySliceBool = &MySlice(true, [unsafe { mem::tran error[E0080]: it is undefined behavior to use this value --> $DIR/ub-wide-ptr.rs:109:1 | -LL | / const RAW_SLICE_LENGTH_UNINIT: *const [u8] = unsafe { -LL | | -LL | | let uninit_len = MaybeUninit::<usize> { uninit: () }; -LL | | mem::transmute((42, uninit_len)) -LL | | }; - | |__^ constructing invalid value: encountered uninitialized raw pointer +LL | const RAW_SLICE_LENGTH_UNINIT: *const [u8] = unsafe { + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ constructing invalid value: encountered uninitialized raw pointer | = note: The rules on what exactly is undefined behavior aren't clear, so this check might be overzealous. Please open an issue on the rustc repository if you believe it should not be considered undefined behavior. = note: the raw bytes of the constant (size: 16, align: 8) { @@ -223,7 +209,7 @@ error[E0080]: it is undefined behavior to use this value --> $DIR/ub-wide-ptr.rs:117:1 | LL | const TRAIT_OBJ_SHORT_VTABLE_1: W<&dyn Trait> = unsafe { mem::transmute(W((&92u8, &3u8))) }; - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ constructing invalid value at .0: encountered too small vtable + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ constructing invalid value at .0: encountered too small vtable | = note: The rules on what exactly is undefined behavior aren't clear, so this check might be overzealous. Please open an issue on the rustc repository if you believe it should not be considered undefined behavior. = note: the raw bytes of the constant (size: 16, align: 8) { @@ -234,7 +220,7 @@ error[E0080]: it is undefined behavior to use this value --> $DIR/ub-wide-ptr.rs:120:1 | LL | const TRAIT_OBJ_SHORT_VTABLE_2: W<&dyn Trait> = unsafe { mem::transmute(W((&92u8, &3u64))) }; - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ constructing invalid value at .0: encountered too small vtable + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ constructing invalid value at .0: encountered too small vtable | = note: The rules on what exactly is undefined behavior aren't clear, so this check might be overzealous. Please open an issue on the rustc repository if you believe it should not be considered undefined behavior. = note: the raw bytes of the constant (size: 16, align: 8) { @@ -245,7 +231,7 @@ error[E0080]: it is undefined behavior to use this value --> $DIR/ub-wide-ptr.rs:123:1 | LL | const TRAIT_OBJ_INT_VTABLE: W<&dyn Trait> = unsafe { mem::transmute(W((&92u8, 4usize))) }; - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ constructing invalid value at .0: encountered dangling vtable pointer in wide pointer + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ constructing invalid value at .0: encountered dangling vtable pointer in wide pointer | = note: The rules on what exactly is undefined behavior aren't clear, so this check might be overzealous. Please open an issue on the rustc repository if you believe it should not be considered undefined behavior. = note: the raw bytes of the constant (size: 16, align: 8) { @@ -256,7 +242,7 @@ error[E0080]: it is undefined behavior to use this value --> $DIR/ub-wide-ptr.rs:125:1 | LL | const TRAIT_OBJ_UNALIGNED_VTABLE: &dyn Trait = unsafe { mem::transmute((&92u8, &[0u8; 128])) }; - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ constructing invalid value: encountered unaligned vtable pointer in wide pointer + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ constructing invalid value: encountered unaligned vtable pointer in wide pointer | = note: The rules on what exactly is undefined behavior aren't clear, so this check might be overzealous. Please open an issue on the rustc repository if you believe it should not be considered undefined behavior. = note: the raw bytes of the constant (size: 16, align: 8) { @@ -267,7 +253,7 @@ error[E0080]: it is undefined behavior to use this value --> $DIR/ub-wide-ptr.rs:127:1 | LL | const TRAIT_OBJ_BAD_DROP_FN_NULL: &dyn Trait = unsafe { mem::transmute((&92u8, &[0usize; 8])) }; - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ constructing invalid value: encountered invalid drop function pointer in vtable (not pointing to a function) + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ constructing invalid value: encountered invalid drop function pointer in vtable (not pointing to a function) | = note: The rules on what exactly is undefined behavior aren't clear, so this check might be overzealous. Please open an issue on the rustc repository if you believe it should not be considered undefined behavior. = note: the raw bytes of the constant (size: 16, align: 8) { @@ -278,7 +264,7 @@ error[E0080]: it is undefined behavior to use this value --> $DIR/ub-wide-ptr.rs:129:1 | LL | const TRAIT_OBJ_BAD_DROP_FN_INT: &dyn Trait = unsafe { mem::transmute((&92u8, &[1usize; 8])) }; - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ constructing invalid value: encountered invalid drop function pointer in vtable (not pointing to a function) + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ constructing invalid value: encountered invalid drop function pointer in vtable (not pointing to a function) | = note: The rules on what exactly is undefined behavior aren't clear, so this check might be overzealous. Please open an issue on the rustc repository if you believe it should not be considered undefined behavior. = note: the raw bytes of the constant (size: 16, align: 8) { @@ -289,7 +275,7 @@ error[E0080]: it is undefined behavior to use this value --> $DIR/ub-wide-ptr.rs:131:1 | LL | const TRAIT_OBJ_BAD_DROP_FN_NOT_FN_PTR: W<&dyn Trait> = unsafe { mem::transmute(W((&92u8, &[&42u8; 8]))) }; - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ constructing invalid value at .0: encountered invalid drop function pointer in vtable (not pointing to a function) + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ constructing invalid value at .0: encountered invalid drop function pointer in vtable (not pointing to a function) | = note: The rules on what exactly is undefined behavior aren't clear, so this check might be overzealous. Please open an issue on the rustc repository if you believe it should not be considered undefined behavior. = note: the raw bytes of the constant (size: 16, align: 8) { @@ -300,7 +286,7 @@ error[E0080]: it is undefined behavior to use this value --> $DIR/ub-wide-ptr.rs:135:1 | LL | const TRAIT_OBJ_CONTENT_INVALID: &dyn Trait = unsafe { mem::transmute::<_, &bool>(&3u8) }; - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ constructing invalid value at .<deref>.<dyn-downcast>: encountered 0x03, but expected a boolean + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ constructing invalid value at .<deref>.<dyn-downcast>: encountered 0x03, but expected a boolean | = note: The rules on what exactly is undefined behavior aren't clear, so this check might be overzealous. Please open an issue on the rustc repository if you believe it should not be considered undefined behavior. = note: the raw bytes of the constant (size: 16, align: 8) { @@ -311,7 +297,7 @@ error[E0080]: it is undefined behavior to use this value --> $DIR/ub-wide-ptr.rs:139:1 | LL | const RAW_TRAIT_OBJ_VTABLE_NULL: *const dyn Trait = unsafe { mem::transmute((&92u8, 0usize)) }; - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ constructing invalid value: encountered dangling vtable pointer in wide pointer + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ constructing invalid value: encountered dangling vtable pointer in wide pointer | = note: The rules on what exactly is undefined behavior aren't clear, so this check might be overzealous. Please open an issue on the rustc repository if you believe it should not be considered undefined behavior. = note: the raw bytes of the constant (size: 16, align: 8) { @@ -322,7 +308,7 @@ error[E0080]: it is undefined behavior to use this value --> $DIR/ub-wide-ptr.rs:141:1 | LL | const RAW_TRAIT_OBJ_VTABLE_INVALID: *const dyn Trait = unsafe { mem::transmute((&92u8, &3u64)) }; - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ constructing invalid value: encountered too small vtable + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ constructing invalid value: encountered too small vtable | = note: The rules on what exactly is undefined behavior aren't clear, so this check might be overzealous. Please open an issue on the rustc repository if you believe it should not be considered undefined behavior. = note: the raw bytes of the constant (size: 16, align: 8) { @@ -333,7 +319,7 @@ error[E0080]: could not evaluate static initializer --> $DIR/ub-wide-ptr.rs:147:5 | LL | mem::transmute::<_, &dyn Trait>((&92u8, 0usize)) - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ memory access failed: null pointer is not a valid pointer + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ memory access failed: null pointer is a dangling pointer (it has no provenance) error[E0080]: could not evaluate static initializer --> $DIR/ub-wide-ptr.rs:151:5 @@ -349,7 +335,7 @@ error: any use of this value will cause an error --> $DIR/ub-wide-ptr.rs:42:1 | LL | const STR_LENGTH_PTR: &str = unsafe { mem::transmute((&42u8, &3)) }; - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ unable to turn pointer into raw bytes + | ^^^^^^^^^^^^^^^^^^^^^^^^^^ unable to turn pointer into raw bytes | = note: `#[deny(const_err)]` on by default = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release! @@ -360,7 +346,7 @@ error: any use of this value will cause an error --> $DIR/ub-wide-ptr.rs:46:1 | LL | const MY_STR_LENGTH_PTR: &MyStr = unsafe { mem::transmute((&42u8, &3)) }; - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ unable to turn pointer into raw bytes + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ unable to turn pointer into raw bytes | = note: `#[deny(const_err)]` on by default = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release! @@ -371,7 +357,7 @@ error: any use of this value will cause an error --> $DIR/ub-wide-ptr.rs:75:1 | LL | const SLICE_LENGTH_PTR: &[u8] = unsafe { mem::transmute((&42u8, &3)) }; - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ unable to turn pointer into raw bytes + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ unable to turn pointer into raw bytes | = note: `#[deny(const_err)]` on by default = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release! @@ -382,7 +368,7 @@ error: any use of this value will cause an error --> $DIR/ub-wide-ptr.rs:82:1 | LL | const SLICE_LENGTH_PTR_BOX: Box<[u8]> = unsafe { mem::transmute((&42u8, &3)) }; - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ unable to turn pointer into raw bytes + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ unable to turn pointer into raw bytes | = note: `#[deny(const_err)]` on by default = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release! @@ -393,9 +379,7 @@ error: any use of this value will cause an error --> $DIR/ub-wide-ptr.rs:87:40 | LL | const SLICE_CONTENT_INVALID: &[bool] = &[unsafe { mem::transmute(3u8) }]; - | ---------------------------------------^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^- - | | - | referenced constant has errors + | ------------------------------------ ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ referenced constant has errors | = note: `#[deny(const_err)]` on by default = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release! @@ -406,9 +390,7 @@ error: any use of this value will cause an error --> $DIR/ub-wide-ptr.rs:95:42 | LL | const MYSLICE_PREFIX_BAD: &MySliceBool = &MySlice(unsafe { mem::transmute(3u8) }, [false]); - | -----------------------------------------^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^- - | | - | referenced constant has errors + | -------------------------------------- ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ referenced constant has errors | = note: `#[deny(const_err)]` on by default = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release! @@ -419,9 +401,7 @@ error: any use of this value will cause an error --> $DIR/ub-wide-ptr.rs:100:42 | LL | const MYSLICE_SUFFIX_BAD: &MySliceBool = &MySlice(true, [unsafe { mem::transmute(3u8) }]); - | -----------------------------------------^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^- - | | - | referenced constant has errors + | -------------------------------------- ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ referenced constant has errors | = note: `#[deny(const_err)]` on by default = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release! diff --git a/src/test/ui/consts/const-eval/union-const-eval-field.stderr b/src/test/ui/consts/const-eval/union-const-eval-field.stderr index f962afadffb..c512e682504 100644 --- a/src/test/ui/consts/const-eval/union-const-eval-field.stderr +++ b/src/test/ui/consts/const-eval/union-const-eval-field.stderr @@ -2,7 +2,7 @@ error[E0080]: it is undefined behavior to use this value --> $DIR/union-const-eval-field.rs:28:5 | LL | const FIELD3: Field3 = unsafe { UNION.field3 }; - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ constructing invalid value: encountered uninitialized bytes, but expected initialized bytes + | ^^^^^^^^^^^^^^^^^^^^ constructing invalid value: encountered uninitialized bytes, but expected initialized bytes | = note: The rules on what exactly is undefined behavior aren't clear, so this check might be overzealous. Please open an issue on the rustc repository if you believe it should not be considered undefined behavior. = note: the raw bytes of the constant (size: 8, align: 8) { diff --git a/src/test/ui/consts/const-eval/union-ice.stderr b/src/test/ui/consts/const-eval/union-ice.stderr index 6f1fce3f980..21a54550900 100644 --- a/src/test/ui/consts/const-eval/union-ice.stderr +++ b/src/test/ui/consts/const-eval/union-ice.stderr @@ -2,7 +2,7 @@ error[E0080]: it is undefined behavior to use this value --> $DIR/union-ice.rs:14:1 | LL | const FIELD3: Field3 = unsafe { UNION.field3 }; - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ constructing invalid value: encountered uninitialized bytes, but expected initialized bytes + | ^^^^^^^^^^^^^^^^^^^^ constructing invalid value: encountered uninitialized bytes, but expected initialized bytes | = note: The rules on what exactly is undefined behavior aren't clear, so this check might be overzealous. Please open an issue on the rustc repository if you believe it should not be considered undefined behavior. = note: the raw bytes of the constant (size: 8, align: 8) { @@ -12,11 +12,8 @@ LL | const FIELD3: Field3 = unsafe { UNION.field3 }; error[E0080]: it is undefined behavior to use this value --> $DIR/union-ice.rs:16:1 | -LL | / const FIELD_PATH: Struct = Struct { -LL | | a: 42, -LL | | b: unsafe { UNION.field3 }, -LL | | }; - | |__^ constructing invalid value at .b: encountered uninitialized bytes, but expected initialized bytes +LL | const FIELD_PATH: Struct = Struct { + | ^^^^^^^^^^^^^^^^^^^^^^^^ constructing invalid value at .b: encountered uninitialized bytes, but expected initialized bytes | = note: The rules on what exactly is undefined behavior aren't clear, so this check might be overzealous. Please open an issue on the rustc repository if you believe it should not be considered undefined behavior. = note: the raw bytes of the constant (size: 16, align: 8) { @@ -26,14 +23,8 @@ LL | | }; error[E0080]: it is undefined behavior to use this value --> $DIR/union-ice.rs:26:1 | -LL | / const FIELD_PATH2: Struct2 = Struct2 { -LL | | b: [ -LL | | 21, -LL | | unsafe { UNION.field3 }, -... | -LL | | a: 42, -LL | | }; - | |__^ constructing invalid value at .b[1]: encountered uninitialized bytes +LL | const FIELD_PATH2: Struct2 = Struct2 { + | ^^^^^^^^^^^^^^^^^^^^^^^^^^ constructing invalid value at .b[1]: encountered uninitialized bytes | = note: The rules on what exactly is undefined behavior aren't clear, so this check might be overzealous. Please open an issue on the rustc repository if you believe it should not be considered undefined behavior. = note: the raw bytes of the constant (size: 40, align: 8) { diff --git a/src/test/ui/consts/const-eval/union-ub.32bit.stderr b/src/test/ui/consts/const-eval/union-ub.32bit.stderr index c1b84ef330e..baf68259660 100644 --- a/src/test/ui/consts/const-eval/union-ub.32bit.stderr +++ b/src/test/ui/consts/const-eval/union-ub.32bit.stderr @@ -2,7 +2,7 @@ error[E0080]: it is undefined behavior to use this value --> $DIR/union-ub.rs:33:1 | LL | const BAD_BOOL: bool = unsafe { DummyUnion { u8: 42 }.bool}; - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ constructing invalid value: encountered 0x2a, but expected a boolean + | ^^^^^^^^^^^^^^^^^^^^ constructing invalid value: encountered 0x2a, but expected a boolean | = note: The rules on what exactly is undefined behavior aren't clear, so this check might be overzealous. Please open an issue on the rustc repository if you believe it should not be considered undefined behavior. = note: the raw bytes of the constant (size: 1, align: 1) { @@ -13,7 +13,7 @@ error[E0080]: it is undefined behavior to use this value --> $DIR/union-ub.rs:35:1 | LL | const UNINIT_BOOL: bool = unsafe { DummyUnion { unit: () }.bool}; - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ constructing invalid value: encountered uninitialized bytes, but expected a boolean + | ^^^^^^^^^^^^^^^^^^^^^^^ constructing invalid value: encountered uninitialized bytes, but expected a boolean | = note: The rules on what exactly is undefined behavior aren't clear, so this check might be overzealous. Please open an issue on the rustc repository if you believe it should not be considered undefined behavior. = note: the raw bytes of the constant (size: 1, align: 1) { diff --git a/src/test/ui/consts/const-eval/union-ub.64bit.stderr b/src/test/ui/consts/const-eval/union-ub.64bit.stderr index c1b84ef330e..baf68259660 100644 --- a/src/test/ui/consts/const-eval/union-ub.64bit.stderr +++ b/src/test/ui/consts/const-eval/union-ub.64bit.stderr @@ -2,7 +2,7 @@ error[E0080]: it is undefined behavior to use this value --> $DIR/union-ub.rs:33:1 | LL | const BAD_BOOL: bool = unsafe { DummyUnion { u8: 42 }.bool}; - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ constructing invalid value: encountered 0x2a, but expected a boolean + | ^^^^^^^^^^^^^^^^^^^^ constructing invalid value: encountered 0x2a, but expected a boolean | = note: The rules on what exactly is undefined behavior aren't clear, so this check might be overzealous. Please open an issue on the rustc repository if you believe it should not be considered undefined behavior. = note: the raw bytes of the constant (size: 1, align: 1) { @@ -13,7 +13,7 @@ error[E0080]: it is undefined behavior to use this value --> $DIR/union-ub.rs:35:1 | LL | const UNINIT_BOOL: bool = unsafe { DummyUnion { unit: () }.bool}; - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ constructing invalid value: encountered uninitialized bytes, but expected a boolean + | ^^^^^^^^^^^^^^^^^^^^^^^ constructing invalid value: encountered uninitialized bytes, but expected a boolean | = note: The rules on what exactly is undefined behavior aren't clear, so this check might be overzealous. Please open an issue on the rustc repository if you believe it should not be considered undefined behavior. = note: the raw bytes of the constant (size: 1, align: 1) { diff --git a/src/test/ui/consts/const-eval/unused-broken-const.stderr b/src/test/ui/consts/const-eval/unused-broken-const.stderr index bfc076aa5e6..df5bd524f27 100644 --- a/src/test/ui/consts/const-eval/unused-broken-const.stderr +++ b/src/test/ui/consts/const-eval/unused-broken-const.stderr @@ -2,9 +2,7 @@ error: any use of this value will cause an error --> $DIR/unused-broken-const.rs:5:18 | LL | const FOO: i32 = [][0]; - | -----------------^^^^^- - | | - | index out of bounds: the length is 0 but the index is 0 + | -------------- ^^^^^ index out of bounds: the length is 0 but the index is 0 | = note: `#[deny(const_err)]` on by default = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release! @@ -17,9 +15,7 @@ error: any use of this value will cause an error --> $DIR/unused-broken-const.rs:5:18 | LL | const FOO: i32 = [][0]; - | -----------------^^^^^- - | | - | index out of bounds: the length is 0 but the index is 0 + | -------------- ^^^^^ index out of bounds: the length is 0 but the index is 0 | = note: `#[deny(const_err)]` on by default = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release! diff --git a/src/test/ui/consts/const-eval/validate_uninhabited_zsts.32bit.stderr b/src/test/ui/consts/const-eval/validate_uninhabited_zsts.32bit.stderr index 22afc9779e8..bdaeb4a0fbe 100644 --- a/src/test/ui/consts/const-eval/validate_uninhabited_zsts.32bit.stderr +++ b/src/test/ui/consts/const-eval/validate_uninhabited_zsts.32bit.stderr @@ -26,7 +26,7 @@ error[E0080]: it is undefined behavior to use this value --> $DIR/validate_uninhabited_zsts.rs:23:1 | LL | const BAR: [empty::Empty; 3] = [unsafe { std::mem::transmute(()) }; 3]; - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ constructing invalid value at [0].0: encountered a value of uninhabited type empty::Void + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ constructing invalid value at [0].0: encountered a value of uninhabited type empty::Void | = note: The rules on what exactly is undefined behavior aren't clear, so this check might be overzealous. Please open an issue on the rustc repository if you believe it should not be considered undefined behavior. = note: the raw bytes of the constant (size: 0, align: 1) {} diff --git a/src/test/ui/consts/const-eval/validate_uninhabited_zsts.64bit.stderr b/src/test/ui/consts/const-eval/validate_uninhabited_zsts.64bit.stderr index 22afc9779e8..bdaeb4a0fbe 100644 --- a/src/test/ui/consts/const-eval/validate_uninhabited_zsts.64bit.stderr +++ b/src/test/ui/consts/const-eval/validate_uninhabited_zsts.64bit.stderr @@ -26,7 +26,7 @@ error[E0080]: it is undefined behavior to use this value --> $DIR/validate_uninhabited_zsts.rs:23:1 | LL | const BAR: [empty::Empty; 3] = [unsafe { std::mem::transmute(()) }; 3]; - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ constructing invalid value at [0].0: encountered a value of uninhabited type empty::Void + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ constructing invalid value at [0].0: encountered a value of uninhabited type empty::Void | = note: The rules on what exactly is undefined behavior aren't clear, so this check might be overzealous. Please open an issue on the rustc repository if you believe it should not be considered undefined behavior. = note: the raw bytes of the constant (size: 0, align: 1) {} diff --git a/src/test/ui/consts/const-float-bits-reject-conv.stderr b/src/test/ui/consts/const-float-bits-reject-conv.stderr index d822171df72..b77c6591d49 100644 --- a/src/test/ui/consts/const-float-bits-reject-conv.stderr +++ b/src/test/ui/consts/const-float-bits-reject-conv.stderr @@ -60,7 +60,7 @@ error: any use of this value will cause an error --> $DIR/const-float-bits-reject-conv.rs:30:34 | LL | const _: () = assert!($a); - | -------------------------- + | ----------- ... LL | const_assert!(f32::from_bits(MASKED_NAN1).is_nan()); | ^^^^^^^^^^^ referenced constant has errors @@ -73,7 +73,7 @@ error: any use of this value will cause an error --> $DIR/const-float-bits-reject-conv.rs:33:34 | LL | const _: () = assert!($a); - | -------------------------- + | ----------- ... LL | const_assert!(f32::from_bits(MASKED_NAN1).is_nan()); | ^^^^^^^^^^^ referenced constant has errors @@ -85,7 +85,7 @@ error: any use of this value will cause an error --> $DIR/const-float-bits-reject-conv.rs:41:38 | LL | const _: () = assert!($a == $b); - | -------------------------------- + | ----------- ... LL | const_assert!(f32::from_bits(MASKED_NAN1).to_bits(), MASKED_NAN1); | ^^^^^^^^^^^ referenced constant has errors @@ -97,7 +97,7 @@ error: any use of this value will cause an error --> $DIR/const-float-bits-reject-conv.rs:44:38 | LL | const _: () = assert!($a == $b); - | -------------------------------- + | ----------- ... LL | const_assert!(f32::from_bits(MASKED_NAN2).to_bits(), MASKED_NAN2); | ^^^^^^^^^^^ referenced constant has errors @@ -167,7 +167,7 @@ error: any use of this value will cause an error --> $DIR/const-float-bits-reject-conv.rs:57:34 | LL | const _: () = assert!($a); - | -------------------------- + | ----------- ... LL | const_assert!(f64::from_bits(MASKED_NAN1).is_nan()); | ^^^^^^^^^^^ referenced constant has errors @@ -179,7 +179,7 @@ error: any use of this value will cause an error --> $DIR/const-float-bits-reject-conv.rs:60:34 | LL | const _: () = assert!($a); - | -------------------------- + | ----------- ... LL | const_assert!(f64::from_bits(MASKED_NAN1).is_nan()); | ^^^^^^^^^^^ referenced constant has errors @@ -191,7 +191,7 @@ error: any use of this value will cause an error --> $DIR/const-float-bits-reject-conv.rs:66:38 | LL | const _: () = assert!($a == $b); - | -------------------------------- + | ----------- ... LL | const_assert!(f64::from_bits(MASKED_NAN1).to_bits(), MASKED_NAN1); | ^^^^^^^^^^^ referenced constant has errors @@ -203,7 +203,7 @@ error: any use of this value will cause an error --> $DIR/const-float-bits-reject-conv.rs:69:38 | LL | const _: () = assert!($a == $b); - | -------------------------------- + | ----------- ... LL | const_assert!(f64::from_bits(MASKED_NAN2).to_bits(), MASKED_NAN2); | ^^^^^^^^^^^ referenced constant has errors @@ -219,7 +219,7 @@ error: any use of this value will cause an error --> $DIR/const-float-bits-reject-conv.rs:30:34 | LL | const _: () = assert!($a); - | -------------------------- + | ----------- ... LL | const_assert!(f32::from_bits(MASKED_NAN1).is_nan()); | ^^^^^^^^^^^ referenced constant has errors @@ -233,7 +233,7 @@ error: any use of this value will cause an error --> $DIR/const-float-bits-reject-conv.rs:33:34 | LL | const _: () = assert!($a); - | -------------------------- + | ----------- ... LL | const_assert!(f32::from_bits(MASKED_NAN1).is_nan()); | ^^^^^^^^^^^ referenced constant has errors @@ -247,7 +247,7 @@ error: any use of this value will cause an error --> $DIR/const-float-bits-reject-conv.rs:41:38 | LL | const _: () = assert!($a == $b); - | -------------------------------- + | ----------- ... LL | const_assert!(f32::from_bits(MASKED_NAN1).to_bits(), MASKED_NAN1); | ^^^^^^^^^^^ referenced constant has errors @@ -261,7 +261,7 @@ error: any use of this value will cause an error --> $DIR/const-float-bits-reject-conv.rs:44:38 | LL | const _: () = assert!($a == $b); - | -------------------------------- + | ----------- ... LL | const_assert!(f32::from_bits(MASKED_NAN2).to_bits(), MASKED_NAN2); | ^^^^^^^^^^^ referenced constant has errors @@ -275,7 +275,7 @@ error: any use of this value will cause an error --> $DIR/const-float-bits-reject-conv.rs:57:34 | LL | const _: () = assert!($a); - | -------------------------- + | ----------- ... LL | const_assert!(f64::from_bits(MASKED_NAN1).is_nan()); | ^^^^^^^^^^^ referenced constant has errors @@ -289,7 +289,7 @@ error: any use of this value will cause an error --> $DIR/const-float-bits-reject-conv.rs:60:34 | LL | const _: () = assert!($a); - | -------------------------- + | ----------- ... LL | const_assert!(f64::from_bits(MASKED_NAN1).is_nan()); | ^^^^^^^^^^^ referenced constant has errors @@ -303,7 +303,7 @@ error: any use of this value will cause an error --> $DIR/const-float-bits-reject-conv.rs:66:38 | LL | const _: () = assert!($a == $b); - | -------------------------------- + | ----------- ... LL | const_assert!(f64::from_bits(MASKED_NAN1).to_bits(), MASKED_NAN1); | ^^^^^^^^^^^ referenced constant has errors @@ -317,7 +317,7 @@ error: any use of this value will cause an error --> $DIR/const-float-bits-reject-conv.rs:69:38 | LL | const _: () = assert!($a == $b); - | -------------------------------- + | ----------- ... LL | const_assert!(f64::from_bits(MASKED_NAN2).to_bits(), MASKED_NAN2); | ^^^^^^^^^^^ referenced constant has errors diff --git a/src/test/ui/consts/const-len-underflow-separate-spans.stderr b/src/test/ui/consts/const-len-underflow-separate-spans.stderr index 0c10783476a..d1bf4b92e6a 100644 --- a/src/test/ui/consts/const-len-underflow-separate-spans.stderr +++ b/src/test/ui/consts/const-len-underflow-separate-spans.stderr @@ -2,9 +2,7 @@ error: any use of this value will cause an error --> $DIR/const-len-underflow-separate-spans.rs:7:20 | LL | const LEN: usize = ONE - TWO; - | -------------------^^^^^^^^^- - | | - | attempt to compute `1_usize - 2_usize`, which would overflow + | ---------------- ^^^^^^^^^ attempt to compute `1_usize - 2_usize`, which would overflow | = note: `#[deny(const_err)]` on by default = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release! @@ -24,9 +22,7 @@ error: any use of this value will cause an error --> $DIR/const-len-underflow-separate-spans.rs:7:20 | LL | const LEN: usize = ONE - TWO; - | -------------------^^^^^^^^^- - | | - | attempt to compute `1_usize - 2_usize`, which would overflow + | ---------------- ^^^^^^^^^ attempt to compute `1_usize - 2_usize`, which would overflow | = note: `#[deny(const_err)]` on by default = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release! diff --git a/src/test/ui/consts/const-mut-refs/mut_ref_in_final_dynamic_check.rs b/src/test/ui/consts/const-mut-refs/mut_ref_in_final_dynamic_check.rs index e0704e24a2e..074beaab2c4 100644 --- a/src/test/ui/consts/const-mut-refs/mut_ref_in_final_dynamic_check.rs +++ b/src/test/ui/consts/const-mut-refs/mut_ref_in_final_dynamic_check.rs @@ -11,7 +11,7 @@ const fn helper() -> Option<&'static mut i32> { unsafe { // Undefined behaviour (integer as pointer), who doesn't love tests like this. // This code never gets executed, because the static checks fail before that. Some(&mut *(42 as *mut i32)) //~ ERROR evaluation of constant value failed - //~| 0x2a is not a valid pointer + //~| 0x2a[noalloc] is a dangling pointer } } // The error is an evaluation error and not a validation error, so the error is reported // directly at the site where it occurs. diff --git a/src/test/ui/consts/const-mut-refs/mut_ref_in_final_dynamic_check.stderr b/src/test/ui/consts/const-mut-refs/mut_ref_in_final_dynamic_check.stderr index 9c1733e827d..234e55e3a96 100644 --- a/src/test/ui/consts/const-mut-refs/mut_ref_in_final_dynamic_check.stderr +++ b/src/test/ui/consts/const-mut-refs/mut_ref_in_final_dynamic_check.stderr @@ -4,7 +4,7 @@ error[E0080]: evaluation of constant value failed LL | Some(&mut *(42 as *mut i32)) | ^^^^^^^^^^^^^^^^^^^^^^ | | - | dereferencing pointer failed: 0x2a is not a valid pointer + | dereferencing pointer failed: 0x2a[noalloc] is a dangling pointer (it has no provenance) | inside `helper` at $DIR/mut_ref_in_final_dynamic_check.rs:13:10 ... LL | const A: Option<&mut i32> = helper(); @@ -14,7 +14,7 @@ error: encountered dangling pointer in final constant --> $DIR/mut_ref_in_final_dynamic_check.rs:25:1 | LL | const B: Option<&mut i32> = helper2(); - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | ^^^^^^^^^^^^^^^^^^^^^^^^^ error: aborting due to 2 previous errors diff --git a/src/test/ui/consts/const-pattern-irrefutable.stderr b/src/test/ui/consts/const-pattern-irrefutable.stderr index 3e3bc1979a2..a2b8f072c6e 100644 --- a/src/test/ui/consts/const-pattern-irrefutable.stderr +++ b/src/test/ui/consts/const-pattern-irrefutable.stderr @@ -2,7 +2,7 @@ error[E0005]: refutable pattern in local binding: `0_u8..=1_u8` and `3_u8..=u8:: --> $DIR/const-pattern-irrefutable.rs:12:9 | LL | const a: u8 = 2; - | ---------------- constant defined here + | ----------- constant defined here ... LL | let a = 4; | ^ @@ -16,7 +16,7 @@ error[E0005]: refutable pattern in local binding: `0_u8..=1_u8` and `3_u8..=u8:: --> $DIR/const-pattern-irrefutable.rs:13:9 | LL | pub const b: u8 = 2; - | -------------------- constant defined here + | --------------- constant defined here ... LL | let c = 4; | ^ @@ -30,7 +30,7 @@ error[E0005]: refutable pattern in local binding: `0_u8..=1_u8` and `3_u8..=u8:: --> $DIR/const-pattern-irrefutable.rs:14:9 | LL | pub const d: u8 = 2; - | -------------------- constant defined here + | --------------- constant defined here ... LL | let d = 4; | ^ diff --git a/src/test/ui/consts/const-points-to-static.32bit.stderr b/src/test/ui/consts/const-points-to-static.32bit.stderr index db7d489ade7..97825dd0eb5 100644 --- a/src/test/ui/consts/const-points-to-static.32bit.stderr +++ b/src/test/ui/consts/const-points-to-static.32bit.stderr @@ -2,7 +2,7 @@ error[E0080]: it is undefined behavior to use this value --> $DIR/const-points-to-static.rs:6:1 | LL | const TEST: &u8 = &MY_STATIC; - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ constructing invalid value: encountered a reference pointing to a static variable + | ^^^^^^^^^^^^^^^ constructing invalid value: encountered a reference pointing to a static variable | = note: The rules on what exactly is undefined behavior aren't clear, so this check might be overzealous. Please open an issue on the rustc repository if you believe it should not be considered undefined behavior. = note: the raw bytes of the constant (size: 4, align: 4) { diff --git a/src/test/ui/consts/const-points-to-static.64bit.stderr b/src/test/ui/consts/const-points-to-static.64bit.stderr index de5e02ae58f..0d4a5a8ce4f 100644 --- a/src/test/ui/consts/const-points-to-static.64bit.stderr +++ b/src/test/ui/consts/const-points-to-static.64bit.stderr @@ -2,7 +2,7 @@ error[E0080]: it is undefined behavior to use this value --> $DIR/const-points-to-static.rs:6:1 | LL | const TEST: &u8 = &MY_STATIC; - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ constructing invalid value: encountered a reference pointing to a static variable + | ^^^^^^^^^^^^^^^ constructing invalid value: encountered a reference pointing to a static variable | = note: The rules on what exactly is undefined behavior aren't clear, so this check might be overzealous. Please open an issue on the rustc repository if you believe it should not be considered undefined behavior. = note: the raw bytes of the constant (size: 8, align: 8) { diff --git a/src/test/ui/consts/const-prop-read-static-in-const.stderr b/src/test/ui/consts/const-prop-read-static-in-const.stderr index a60cd16f05a..ea5ad24b0b1 100644 --- a/src/test/ui/consts/const-prop-read-static-in-const.stderr +++ b/src/test/ui/consts/const-prop-read-static-in-const.stderr @@ -2,9 +2,7 @@ error: any use of this value will cause an error --> $DIR/const-prop-read-static-in-const.rs:5:18 | LL | const TEST: u8 = MY_STATIC; - | -----------------^^^^^^^^^- - | | - | constant accesses static + | -------------- ^^^^^^^^^ constant accesses static | = note: `#[deny(const_err)]` on by default = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release! @@ -25,9 +23,7 @@ error: any use of this value will cause an error --> $DIR/const-prop-read-static-in-const.rs:5:18 | LL | const TEST: u8 = MY_STATIC; - | -----------------^^^^^^^^^- - | | - | constant accesses static + | -------------- ^^^^^^^^^ constant accesses static | = note: `#[deny(const_err)]` on by default = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release! diff --git a/src/test/ui/consts/const-size_of_val-align_of_val-extern-type.stderr b/src/test/ui/consts/const-size_of_val-align_of_val-extern-type.stderr index c6e0b321124..d19a89378ec 100644 --- a/src/test/ui/consts/const-size_of_val-align_of_val-extern-type.stderr +++ b/src/test/ui/consts/const-size_of_val-align_of_val-extern-type.stderr @@ -2,9 +2,7 @@ error: any use of this value will cause an error --> $DIR/const-size_of_val-align_of_val-extern-type.rs:11:31 | LL | const _SIZE: usize = unsafe { size_of_val(&4 as *const i32 as *const Opaque) }; - | ------------------------------^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^--- - | | - | `extern type` does not have known layout + | ------------------ ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ `extern type` does not have known layout | = note: `#[deny(const_err)]` on by default = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release! @@ -14,9 +12,7 @@ error: any use of this value will cause an error --> $DIR/const-size_of_val-align_of_val-extern-type.rs:13:32 | LL | const _ALIGN: usize = unsafe { min_align_of_val(&4 as *const i32 as *const Opaque) }; - | -------------------------------^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^--- - | | - | `extern type` does not have known layout + | ------------------- ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ `extern type` does not have known layout | = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release! = note: for more information, see issue #71800 <https://github.com/rust-lang/rust/issues/71800> @@ -28,9 +24,7 @@ error: any use of this value will cause an error --> $DIR/const-size_of_val-align_of_val-extern-type.rs:11:31 | LL | const _SIZE: usize = unsafe { size_of_val(&4 as *const i32 as *const Opaque) }; - | ------------------------------^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^--- - | | - | `extern type` does not have known layout + | ------------------ ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ `extern type` does not have known layout | = note: `#[deny(const_err)]` on by default = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release! @@ -41,9 +35,7 @@ error: any use of this value will cause an error --> $DIR/const-size_of_val-align_of_val-extern-type.rs:13:32 | LL | const _ALIGN: usize = unsafe { min_align_of_val(&4 as *const i32 as *const Opaque) }; - | -------------------------------^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^--- - | | - | `extern type` does not have known layout + | ------------------- ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ `extern type` does not have known layout | = note: `#[deny(const_err)]` on by default = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release! diff --git a/src/test/ui/consts/const-slice-oob.stderr b/src/test/ui/consts/const-slice-oob.stderr index c9f949727bc..27c21e7af14 100644 --- a/src/test/ui/consts/const-slice-oob.stderr +++ b/src/test/ui/consts/const-slice-oob.stderr @@ -2,9 +2,7 @@ error: any use of this value will cause an error --> $DIR/const-slice-oob.rs:4:18 | LL | const BAR: u32 = FOO[5]; - | -----------------^^^^^^- - | | - | index out of bounds: the length is 3 but the index is 5 + | -------------- ^^^^^^ index out of bounds: the length is 3 but the index is 5 | = note: `#[deny(const_err)]` on by default = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release! @@ -17,9 +15,7 @@ error: any use of this value will cause an error --> $DIR/const-slice-oob.rs:4:18 | LL | const BAR: u32 = FOO[5]; - | -----------------^^^^^^- - | | - | index out of bounds: the length is 3 but the index is 5 + | -------------- ^^^^^^ index out of bounds: the length is 3 but the index is 5 | = note: `#[deny(const_err)]` on by default = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release! diff --git a/src/test/ui/consts/const_limit/const_eval_limit_reached.stderr b/src/test/ui/consts/const_limit/const_eval_limit_reached.stderr index ee95b0d5180..e450f4aa3bd 100644 --- a/src/test/ui/consts/const_limit/const_eval_limit_reached.stderr +++ b/src/test/ui/consts/const_limit/const_eval_limit_reached.stderr @@ -1,15 +1,11 @@ error: any use of this value will cause an error --> $DIR/const_eval_limit_reached.rs:6:11 | -LL | / const X: usize = { -LL | | let mut x = 0; -LL | | while x != 1000 { - | | ^^^^^^^^^ exceeded interpreter step limit (see `#[const_eval_limit]`) -LL | | -... | -LL | | x -LL | | }; - | |__- +LL | const X: usize = { + | -------------- +LL | let mut x = 0; +LL | while x != 1000 { + | ^^^^^^^^^ exceeded interpreter step limit (see `#[const_eval_limit]`) | = note: `#[deny(const_err)]` on by default = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release! @@ -21,15 +17,11 @@ Future incompatibility report: Future breakage diagnostic: error: any use of this value will cause an error --> $DIR/const_eval_limit_reached.rs:6:11 | -LL | / const X: usize = { -LL | | let mut x = 0; -LL | | while x != 1000 { - | | ^^^^^^^^^ exceeded interpreter step limit (see `#[const_eval_limit]`) -LL | | -... | -LL | | x -LL | | }; - | |__- +LL | const X: usize = { + | -------------- +LL | let mut x = 0; +LL | while x != 1000 { + | ^^^^^^^^^ exceeded interpreter step limit (see `#[const_eval_limit]`) | = note: `#[deny(const_err)]` on by default = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release! diff --git a/src/test/ui/consts/dangling-alloc-id-ice.stderr b/src/test/ui/consts/dangling-alloc-id-ice.stderr index 24f57449872..8410034c041 100644 --- a/src/test/ui/consts/dangling-alloc-id-ice.stderr +++ b/src/test/ui/consts/dangling-alloc-id-ice.stderr @@ -1,12 +1,8 @@ error: encountered dangling pointer in final constant --> $DIR/dangling-alloc-id-ice.rs:9:1 | -LL | / const FOO: &() = { -LL | | -LL | | let y = (); -LL | | unsafe { Foo { y: &y }.long_live_the_unit } -LL | | }; - | |__^ +LL | const FOO: &() = { + | ^^^^^^^^^^^^^^ error: aborting due to previous error diff --git a/src/test/ui/consts/dangling_raw_ptr.stderr b/src/test/ui/consts/dangling_raw_ptr.stderr index a79ac62d5cd..bdfe1e4effe 100644 --- a/src/test/ui/consts/dangling_raw_ptr.stderr +++ b/src/test/ui/consts/dangling_raw_ptr.stderr @@ -1,11 +1,8 @@ error: encountered dangling pointer in final constant --> $DIR/dangling_raw_ptr.rs:1:1 | -LL | / const FOO: *const u32 = { -LL | | let x = 42; -LL | | &x -LL | | }; - | |__^ +LL | const FOO: *const u32 = { + | ^^^^^^^^^^^^^^^^^^^^^ error: aborting due to previous error diff --git a/src/test/ui/consts/issue-36163.stderr b/src/test/ui/consts/issue-36163.stderr index 9ac6c984cb0..4797d10b7a8 100644 --- a/src/test/ui/consts/issue-36163.stderr +++ b/src/test/ui/consts/issue-36163.stderr @@ -8,7 +8,7 @@ note: ...which requires const-evaluating + checking `A`... --> $DIR/issue-36163.rs:1:1 | LL | const A: isize = Foo::B as isize; - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | ^^^^^^^^^^^^^^ = note: ...which again requires const-evaluating + checking `Foo::B::{constant#0}`, completing the cycle note: cycle used when simplifying constant for the type system `Foo::B::{constant#0}` --> $DIR/issue-36163.rs:4:9 diff --git a/src/test/ui/consts/issue-50439.rs b/src/test/ui/consts/issue-50439.rs new file mode 100644 index 00000000000..0be7c405473 --- /dev/null +++ b/src/test/ui/consts/issue-50439.rs @@ -0,0 +1,29 @@ +#![feature(specialization)] +#![allow(incomplete_features)] + +pub trait ReflectDrop { + const REFLECT_DROP: bool = false; +} + +impl<T> ReflectDrop for T where T: Clone {} + +pub trait PinDropInternal { + fn is_valid() + where + Self: ReflectDrop; +} + +struct Bears<T>(T); + +default impl<T> ReflectDrop for Bears<T> {} + +impl<T: Sized> PinDropInternal for Bears<T> { + fn is_valid() + where + Self: ReflectDrop, + { + let _ = [(); 0 - !!(<Bears<T> as ReflectDrop>::REFLECT_DROP) as usize]; //~ ERROR constant expression depends on a generic parameter + } +} + +fn main() {} diff --git a/src/test/ui/consts/issue-50439.stderr b/src/test/ui/consts/issue-50439.stderr new file mode 100644 index 00000000000..3fbdf33b2d8 --- /dev/null +++ b/src/test/ui/consts/issue-50439.stderr @@ -0,0 +1,10 @@ +error: constant expression depends on a generic parameter + --> $DIR/issue-50439.rs:25:22 + | +LL | let _ = [(); 0 - !!(<Bears<T> as ReflectDrop>::REFLECT_DROP) as usize]; + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | + = note: this may fail depending on what value the parameter takes + +error: aborting due to previous error + diff --git a/src/test/ui/consts/issue-63952.32bit.stderr b/src/test/ui/consts/issue-63952.32bit.stderr index 0d770837582..755c7fb7d4d 100644 --- a/src/test/ui/consts/issue-63952.32bit.stderr +++ b/src/test/ui/consts/issue-63952.32bit.stderr @@ -1,14 +1,8 @@ error[E0080]: it is undefined behavior to use this value --> $DIR/issue-63952.rs:17:1 | -LL | / const SLICE_WAY_TOO_LONG: &[u8] = unsafe { -LL | | SliceTransmute { -LL | | repr: SliceRepr { -LL | | ptr: &42, -... | -LL | | .slice -LL | | }; - | |__^ constructing invalid value: encountered invalid reference metadata: slice is bigger than largest supported object +LL | const SLICE_WAY_TOO_LONG: &[u8] = unsafe { + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ constructing invalid value: encountered invalid reference metadata: slice is bigger than largest supported object | = note: The rules on what exactly is undefined behavior aren't clear, so this check might be overzealous. Please open an issue on the rustc repository if you believe it should not be considered undefined behavior. = note: the raw bytes of the constant (size: 8, align: 4) { diff --git a/src/test/ui/consts/issue-63952.64bit.stderr b/src/test/ui/consts/issue-63952.64bit.stderr index 9b0f45920d6..abdb9a4f792 100644 --- a/src/test/ui/consts/issue-63952.64bit.stderr +++ b/src/test/ui/consts/issue-63952.64bit.stderr @@ -1,14 +1,8 @@ error[E0080]: it is undefined behavior to use this value --> $DIR/issue-63952.rs:17:1 | -LL | / const SLICE_WAY_TOO_LONG: &[u8] = unsafe { -LL | | SliceTransmute { -LL | | repr: SliceRepr { -LL | | ptr: &42, -... | -LL | | .slice -LL | | }; - | |__^ constructing invalid value: encountered invalid reference metadata: slice is bigger than largest supported object +LL | const SLICE_WAY_TOO_LONG: &[u8] = unsafe { + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ constructing invalid value: encountered invalid reference metadata: slice is bigger than largest supported object | = note: The rules on what exactly is undefined behavior aren't clear, so this check might be overzealous. Please open an issue on the rustc repository if you believe it should not be considered undefined behavior. = note: the raw bytes of the constant (size: 16, align: 8) { diff --git a/src/test/ui/consts/issue-79690.64bit.stderr b/src/test/ui/consts/issue-79690.64bit.stderr index 14c42d893c3..c7aba555370 100644 --- a/src/test/ui/consts/issue-79690.64bit.stderr +++ b/src/test/ui/consts/issue-79690.64bit.stderr @@ -2,7 +2,7 @@ error[E0080]: it is undefined behavior to use this value --> $DIR/issue-79690.rs:30:1 | LL | const G: Fat = unsafe { Transmute { t: FOO }.u }; - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ constructing invalid value at .1.<deref>.size.foo: encountered (potentially part of) a pointer, but expected plain (non-pointer) bytes + | ^^^^^^^^^^^^ constructing invalid value at .1.<deref>.size.foo: encountered (potentially part of) a pointer, but expected plain (non-pointer) bytes | = note: The rules on what exactly is undefined behavior aren't clear, so this check might be overzealous. Please open an issue on the rustc repository if you believe it should not be considered undefined behavior. = note: the raw bytes of the constant (size: 16, align: 8) { diff --git a/src/test/ui/consts/issue-83182.32bit.stderr b/src/test/ui/consts/issue-83182.32bit.stderr index fdd56bce958..c810c8a7848 100644 --- a/src/test/ui/consts/issue-83182.32bit.stderr +++ b/src/test/ui/consts/issue-83182.32bit.stderr @@ -2,7 +2,7 @@ error[E0080]: it is undefined behavior to use this value --> $DIR/issue-83182.rs:5:1 | LL | const MYSTR_NO_INIT: &MyStr = unsafe { mem::transmute::<&[_], _>(&[&()]) }; - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ constructing invalid value at .<deref>.0: encountered a pointer in `str` + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^ constructing invalid value at .<deref>.0: encountered a pointer in `str` | = note: The rules on what exactly is undefined behavior aren't clear, so this check might be overzealous. Please open an issue on the rustc repository if you believe it should not be considered undefined behavior. = note: the raw bytes of the constant (size: 8, align: 4) { diff --git a/src/test/ui/consts/issue-83182.64bit.stderr b/src/test/ui/consts/issue-83182.64bit.stderr index 284c1da3b3e..5fc2c934474 100644 --- a/src/test/ui/consts/issue-83182.64bit.stderr +++ b/src/test/ui/consts/issue-83182.64bit.stderr @@ -2,7 +2,7 @@ error[E0080]: it is undefined behavior to use this value --> $DIR/issue-83182.rs:5:1 | LL | const MYSTR_NO_INIT: &MyStr = unsafe { mem::transmute::<&[_], _>(&[&()]) }; - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ constructing invalid value at .<deref>.0: encountered a pointer in `str` + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^ constructing invalid value at .<deref>.0: encountered a pointer in `str` | = note: The rules on what exactly is undefined behavior aren't clear, so this check might be overzealous. Please open an issue on the rustc repository if you believe it should not be considered undefined behavior. = note: the raw bytes of the constant (size: 16, align: 8) { diff --git a/src/test/ui/consts/issue-miri-1910.stderr b/src/test/ui/consts/issue-miri-1910.stderr index e76a1f96b46..afcf11bd5f2 100644 --- a/src/test/ui/consts/issue-miri-1910.stderr +++ b/src/test/ui/consts/issue-miri-1910.stderr @@ -1,22 +1,18 @@ error: any use of this value will cause an error --> $SRC_DIR/core/src/ptr/mod.rs:LL:COL | -LL | copy_nonoverlapping(src, tmp.as_mut_ptr(), 1); - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ - | | - | unable to turn pointer into raw bytes - | inside `std::ptr::read::<u8>` at $SRC_DIR/core/src/ptr/mod.rs:LL:COL - | inside `ptr::const_ptr::<impl *const u8>::read` at $SRC_DIR/core/src/ptr/const_ptr.rs:LL:COL - | inside `C` at $DIR/issue-miri-1910.rs:7:5 +LL | copy_nonoverlapping(src, tmp.as_mut_ptr(), 1); + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | | + | unable to turn pointer into raw bytes + | inside `std::ptr::read::<u8>` at $SRC_DIR/core/src/ptr/mod.rs:LL:COL + | inside `ptr::const_ptr::<impl *const u8>::read` at $SRC_DIR/core/src/ptr/const_ptr.rs:LL:COL + | inside `C` at $DIR/issue-miri-1910.rs:7:5 | ::: $DIR/issue-miri-1910.rs:4:1 | -LL | / const C: () = unsafe { -LL | | let foo = Some(&42 as *const i32); -LL | | let one_and_a_half_pointers = std::mem::size_of::<*const i32>()/2*3; -LL | | (&foo as *const _ as *const u8).add(one_and_a_half_pointers).read(); -LL | | }; - | |__- +LL | const C: () = unsafe { + | ----------- | = note: `#[deny(const_err)]` on by default = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release! @@ -28,22 +24,18 @@ Future incompatibility report: Future breakage diagnostic: error: any use of this value will cause an error --> $SRC_DIR/core/src/ptr/mod.rs:LL:COL | -LL | copy_nonoverlapping(src, tmp.as_mut_ptr(), 1); - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ - | | - | unable to turn pointer into raw bytes - | inside `std::ptr::read::<u8>` at $SRC_DIR/core/src/ptr/mod.rs:LL:COL - | inside `ptr::const_ptr::<impl *const u8>::read` at $SRC_DIR/core/src/ptr/const_ptr.rs:LL:COL - | inside `C` at $DIR/issue-miri-1910.rs:7:5 +LL | copy_nonoverlapping(src, tmp.as_mut_ptr(), 1); + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | | + | unable to turn pointer into raw bytes + | inside `std::ptr::read::<u8>` at $SRC_DIR/core/src/ptr/mod.rs:LL:COL + | inside `ptr::const_ptr::<impl *const u8>::read` at $SRC_DIR/core/src/ptr/const_ptr.rs:LL:COL + | inside `C` at $DIR/issue-miri-1910.rs:7:5 | ::: $DIR/issue-miri-1910.rs:4:1 | -LL | / const C: () = unsafe { -LL | | let foo = Some(&42 as *const i32); -LL | | let one_and_a_half_pointers = std::mem::size_of::<*const i32>()/2*3; -LL | | (&foo as *const _ as *const u8).add(one_and_a_half_pointers).read(); -LL | | }; - | |__- +LL | const C: () = unsafe { + | ----------- | = note: `#[deny(const_err)]` on by default = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release! diff --git a/src/test/ui/consts/miri_unleashed/assoc_const.stderr b/src/test/ui/consts/miri_unleashed/assoc_const.stderr index 1765c9ed10a..1f82ac827ad 100644 --- a/src/test/ui/consts/miri_unleashed/assoc_const.stderr +++ b/src/test/ui/consts/miri_unleashed/assoc_const.stderr @@ -30,7 +30,7 @@ LL | pub unsafe fn drop_in_place<T: ?Sized>(to_drop: *mut T) { ::: $DIR/assoc_const.rs:14:5 | LL | const F: u32 = (U::X, 42).1; - | ---------------------------- + | ------------ | note: the lint level is defined here --> $DIR/assoc_const.rs:4:10 diff --git a/src/test/ui/consts/miri_unleashed/assoc_const_2.stderr b/src/test/ui/consts/miri_unleashed/assoc_const_2.stderr index f7be42de03f..cbf02199f5b 100644 --- a/src/test/ui/consts/miri_unleashed/assoc_const_2.stderr +++ b/src/test/ui/consts/miri_unleashed/assoc_const_2.stderr @@ -12,9 +12,7 @@ warning: any use of this value will cause an error --> $DIR/assoc_const_2.rs:12:20 | LL | const F: u32 = 100 / U::X; - | ---------------^^^^^^^^^^- - | | - | attempt to divide `100_u32` by zero + | ------------ ^^^^^^^^^^ attempt to divide `100_u32` by zero | note: the lint level is defined here --> $DIR/assoc_const_2.rs:3:10 diff --git a/src/test/ui/consts/miri_unleashed/const_refers_to_static.stderr b/src/test/ui/consts/miri_unleashed/const_refers_to_static.stderr index 98d4dff648a..fa2088124b0 100644 --- a/src/test/ui/consts/miri_unleashed/const_refers_to_static.stderr +++ b/src/test/ui/consts/miri_unleashed/const_refers_to_static.stderr @@ -51,12 +51,11 @@ Future incompatibility report: Future breakage diagnostic: warning: any use of this value will cause an error --> $DIR/const_refers_to_static.rs:13:5 | -LL | / const MUTATE_INTERIOR_MUT: usize = { -LL | | static FOO: AtomicUsize = AtomicUsize::new(0); -LL | | FOO.fetch_add(1, Ordering::Relaxed) - | | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ calling non-const function `AtomicUsize::fetch_add` -LL | | }; - | |__- +LL | const MUTATE_INTERIOR_MUT: usize = { + | -------------------------------- +LL | static FOO: AtomicUsize = AtomicUsize::new(0); +LL | FOO.fetch_add(1, Ordering::Relaxed) + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ calling non-const function `AtomicUsize::fetch_add` | note: the lint level is defined here --> $DIR/const_refers_to_static.rs:3:10 @@ -70,12 +69,11 @@ Future breakage diagnostic: warning: any use of this value will cause an error --> $DIR/const_refers_to_static.rs:18:14 | -LL | / const READ_INTERIOR_MUT: usize = { -LL | | static FOO: AtomicUsize = AtomicUsize::new(0); -LL | | unsafe { *(&FOO as *const _ as *const usize) } - | | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ constant accesses static -LL | | }; - | |__- +LL | const READ_INTERIOR_MUT: usize = { + | ------------------------------ +LL | static FOO: AtomicUsize = AtomicUsize::new(0); +LL | unsafe { *(&FOO as *const _ as *const usize) } + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ constant accesses static | note: the lint level is defined here --> $DIR/const_refers_to_static.rs:3:10 @@ -90,9 +88,7 @@ warning: any use of this value will cause an error --> $DIR/const_refers_to_static.rs:22:32 | LL | const READ_MUT: u32 = unsafe { MUTABLE }; - | -------------------------------^^^^^^^--- - | | - | constant accesses static + | ------------------- ^^^^^^^ constant accesses static | note: the lint level is defined here --> $DIR/const_refers_to_static.rs:3:10 diff --git a/src/test/ui/consts/miri_unleashed/const_refers_to_static2.32bit.stderr b/src/test/ui/consts/miri_unleashed/const_refers_to_static2.32bit.stderr index 9eda2f60c8f..b3ad81e49bc 100644 --- a/src/test/ui/consts/miri_unleashed/const_refers_to_static2.32bit.stderr +++ b/src/test/ui/consts/miri_unleashed/const_refers_to_static2.32bit.stderr @@ -1,12 +1,8 @@ error[E0080]: it is undefined behavior to use this value --> $DIR/const_refers_to_static2.rs:11:1 | -LL | / const REF_INTERIOR_MUT: &usize = { -LL | | -LL | | static FOO: AtomicUsize = AtomicUsize::new(0); -LL | | unsafe { &*(&FOO as *const _ as *const usize) } -LL | | }; - | |__^ constructing invalid value: encountered a reference pointing to a static variable +LL | const REF_INTERIOR_MUT: &usize = { + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ constructing invalid value: encountered a reference pointing to a static variable | = note: The rules on what exactly is undefined behavior aren't clear, so this check might be overzealous. Please open an issue on the rustc repository if you believe it should not be considered undefined behavior. = note: the raw bytes of the constant (size: 4, align: 4) { @@ -16,12 +12,8 @@ LL | | }; error[E0080]: it is undefined behavior to use this value --> $DIR/const_refers_to_static2.rs:18:1 | -LL | / const READ_IMMUT: &usize = { -LL | | -LL | | static FOO: usize = 0; -LL | | &FOO -LL | | }; - | |__^ constructing invalid value: encountered a reference pointing to a static variable +LL | const READ_IMMUT: &usize = { + | ^^^^^^^^^^^^^^^^^^^^^^^^ constructing invalid value: encountered a reference pointing to a static variable | = note: The rules on what exactly is undefined behavior aren't clear, so this check might be overzealous. Please open an issue on the rustc repository if you believe it should not be considered undefined behavior. = note: the raw bytes of the constant (size: 4, align: 4) { diff --git a/src/test/ui/consts/miri_unleashed/const_refers_to_static2.64bit.stderr b/src/test/ui/consts/miri_unleashed/const_refers_to_static2.64bit.stderr index 7aa826dbb76..24bd0709282 100644 --- a/src/test/ui/consts/miri_unleashed/const_refers_to_static2.64bit.stderr +++ b/src/test/ui/consts/miri_unleashed/const_refers_to_static2.64bit.stderr @@ -1,12 +1,8 @@ error[E0080]: it is undefined behavior to use this value --> $DIR/const_refers_to_static2.rs:11:1 | -LL | / const REF_INTERIOR_MUT: &usize = { -LL | | -LL | | static FOO: AtomicUsize = AtomicUsize::new(0); -LL | | unsafe { &*(&FOO as *const _ as *const usize) } -LL | | }; - | |__^ constructing invalid value: encountered a reference pointing to a static variable +LL | const REF_INTERIOR_MUT: &usize = { + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ constructing invalid value: encountered a reference pointing to a static variable | = note: The rules on what exactly is undefined behavior aren't clear, so this check might be overzealous. Please open an issue on the rustc repository if you believe it should not be considered undefined behavior. = note: the raw bytes of the constant (size: 8, align: 8) { @@ -16,12 +12,8 @@ LL | | }; error[E0080]: it is undefined behavior to use this value --> $DIR/const_refers_to_static2.rs:18:1 | -LL | / const READ_IMMUT: &usize = { -LL | | -LL | | static FOO: usize = 0; -LL | | &FOO -LL | | }; - | |__^ constructing invalid value: encountered a reference pointing to a static variable +LL | const READ_IMMUT: &usize = { + | ^^^^^^^^^^^^^^^^^^^^^^^^ constructing invalid value: encountered a reference pointing to a static variable | = note: The rules on what exactly is undefined behavior aren't clear, so this check might be overzealous. Please open an issue on the rustc repository if you believe it should not be considered undefined behavior. = note: the raw bytes of the constant (size: 8, align: 8) { diff --git a/src/test/ui/consts/miri_unleashed/const_refers_to_static_cross_crate.32bit.stderr b/src/test/ui/consts/miri_unleashed/const_refers_to_static_cross_crate.32bit.stderr index b5d8872e633..20a96b57f29 100644 --- a/src/test/ui/consts/miri_unleashed/const_refers_to_static_cross_crate.32bit.stderr +++ b/src/test/ui/consts/miri_unleashed/const_refers_to_static_cross_crate.32bit.stderr @@ -1,11 +1,8 @@ error[E0080]: it is undefined behavior to use this value --> $DIR/const_refers_to_static_cross_crate.rs:12:1 | -LL | / const SLICE_MUT: &[u8; 1] = { -LL | | -LL | | unsafe { &static_cross_crate::ZERO } -LL | | }; - | |__^ constructing invalid value: encountered a reference pointing to a static variable +LL | const SLICE_MUT: &[u8; 1] = { + | ^^^^^^^^^^^^^^^^^^^^^^^^^ constructing invalid value: encountered a reference pointing to a static variable | = note: The rules on what exactly is undefined behavior aren't clear, so this check might be overzealous. Please open an issue on the rustc repository if you believe it should not be considered undefined behavior. = note: the raw bytes of the constant (size: 4, align: 4) { @@ -21,11 +18,8 @@ LL | SLICE_MUT => true, error[E0080]: it is undefined behavior to use this value --> $DIR/const_refers_to_static_cross_crate.rs:17:1 | -LL | / const U8_MUT: &u8 = { -LL | | -LL | | unsafe { &static_cross_crate::ZERO[0] } -LL | | }; - | |__^ constructing invalid value: encountered a reference pointing to a static variable +LL | const U8_MUT: &u8 = { + | ^^^^^^^^^^^^^^^^^ constructing invalid value: encountered a reference pointing to a static variable | = note: The rules on what exactly is undefined behavior aren't clear, so this check might be overzealous. Please open an issue on the rustc repository if you believe it should not be considered undefined behavior. = note: the raw bytes of the constant (size: 4, align: 4) { @@ -41,14 +35,10 @@ LL | U8_MUT => true, warning: any use of this value will cause an error --> $DIR/const_refers_to_static_cross_crate.rs:25:15 | -LL | / const U8_MUT2: &u8 = { -LL | | unsafe { &(*static_cross_crate::ZERO_REF)[0] } - | | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ constant accesses static -LL | | -LL | | -LL | | -LL | | }; - | |__- +LL | const U8_MUT2: &u8 = { + | ------------------ +LL | unsafe { &(*static_cross_crate::ZERO_REF)[0] } + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ constant accesses static | note: the lint level is defined here --> $DIR/const_refers_to_static_cross_crate.rs:23:8 @@ -67,14 +57,10 @@ LL | U8_MUT2 => true, warning: any use of this value will cause an error --> $DIR/const_refers_to_static_cross_crate.rs:32:20 | -LL | / const U8_MUT3: &u8 = { -LL | | unsafe { match static_cross_crate::OPT_ZERO { Some(ref u) => u, None => panic!() } } - | | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ constant accesses static -LL | | -LL | | -LL | | -LL | | }; - | |__- +LL | const U8_MUT3: &u8 = { + | ------------------ +LL | unsafe { match static_cross_crate::OPT_ZERO { Some(ref u) => u, None => panic!() } } + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ constant accesses static | note: the lint level is defined here --> $DIR/const_refers_to_static_cross_crate.rs:30:8 @@ -174,14 +160,10 @@ Future incompatibility report: Future breakage diagnostic: warning: any use of this value will cause an error --> $DIR/const_refers_to_static_cross_crate.rs:25:15 | -LL | / const U8_MUT2: &u8 = { -LL | | unsafe { &(*static_cross_crate::ZERO_REF)[0] } - | | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ constant accesses static -LL | | -LL | | -LL | | -LL | | }; - | |__- +LL | const U8_MUT2: &u8 = { + | ------------------ +LL | unsafe { &(*static_cross_crate::ZERO_REF)[0] } + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ constant accesses static | note: the lint level is defined here --> $DIR/const_refers_to_static_cross_crate.rs:23:8 @@ -195,14 +177,10 @@ Future breakage diagnostic: warning: any use of this value will cause an error --> $DIR/const_refers_to_static_cross_crate.rs:32:20 | -LL | / const U8_MUT3: &u8 = { -LL | | unsafe { match static_cross_crate::OPT_ZERO { Some(ref u) => u, None => panic!() } } - | | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ constant accesses static -LL | | -LL | | -LL | | -LL | | }; - | |__- +LL | const U8_MUT3: &u8 = { + | ------------------ +LL | unsafe { match static_cross_crate::OPT_ZERO { Some(ref u) => u, None => panic!() } } + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ constant accesses static | note: the lint level is defined here --> $DIR/const_refers_to_static_cross_crate.rs:30:8 diff --git a/src/test/ui/consts/miri_unleashed/const_refers_to_static_cross_crate.64bit.stderr b/src/test/ui/consts/miri_unleashed/const_refers_to_static_cross_crate.64bit.stderr index ec3eeb912b2..dfa0f76baa1 100644 --- a/src/test/ui/consts/miri_unleashed/const_refers_to_static_cross_crate.64bit.stderr +++ b/src/test/ui/consts/miri_unleashed/const_refers_to_static_cross_crate.64bit.stderr @@ -1,11 +1,8 @@ error[E0080]: it is undefined behavior to use this value --> $DIR/const_refers_to_static_cross_crate.rs:12:1 | -LL | / const SLICE_MUT: &[u8; 1] = { -LL | | -LL | | unsafe { &static_cross_crate::ZERO } -LL | | }; - | |__^ constructing invalid value: encountered a reference pointing to a static variable +LL | const SLICE_MUT: &[u8; 1] = { + | ^^^^^^^^^^^^^^^^^^^^^^^^^ constructing invalid value: encountered a reference pointing to a static variable | = note: The rules on what exactly is undefined behavior aren't clear, so this check might be overzealous. Please open an issue on the rustc repository if you believe it should not be considered undefined behavior. = note: the raw bytes of the constant (size: 8, align: 8) { @@ -21,11 +18,8 @@ LL | SLICE_MUT => true, error[E0080]: it is undefined behavior to use this value --> $DIR/const_refers_to_static_cross_crate.rs:17:1 | -LL | / const U8_MUT: &u8 = { -LL | | -LL | | unsafe { &static_cross_crate::ZERO[0] } -LL | | }; - | |__^ constructing invalid value: encountered a reference pointing to a static variable +LL | const U8_MUT: &u8 = { + | ^^^^^^^^^^^^^^^^^ constructing invalid value: encountered a reference pointing to a static variable | = note: The rules on what exactly is undefined behavior aren't clear, so this check might be overzealous. Please open an issue on the rustc repository if you believe it should not be considered undefined behavior. = note: the raw bytes of the constant (size: 8, align: 8) { @@ -41,14 +35,10 @@ LL | U8_MUT => true, warning: any use of this value will cause an error --> $DIR/const_refers_to_static_cross_crate.rs:25:15 | -LL | / const U8_MUT2: &u8 = { -LL | | unsafe { &(*static_cross_crate::ZERO_REF)[0] } - | | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ constant accesses static -LL | | -LL | | -LL | | -LL | | }; - | |__- +LL | const U8_MUT2: &u8 = { + | ------------------ +LL | unsafe { &(*static_cross_crate::ZERO_REF)[0] } + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ constant accesses static | note: the lint level is defined here --> $DIR/const_refers_to_static_cross_crate.rs:23:8 @@ -67,14 +57,10 @@ LL | U8_MUT2 => true, warning: any use of this value will cause an error --> $DIR/const_refers_to_static_cross_crate.rs:32:20 | -LL | / const U8_MUT3: &u8 = { -LL | | unsafe { match static_cross_crate::OPT_ZERO { Some(ref u) => u, None => panic!() } } - | | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ constant accesses static -LL | | -LL | | -LL | | -LL | | }; - | |__- +LL | const U8_MUT3: &u8 = { + | ------------------ +LL | unsafe { match static_cross_crate::OPT_ZERO { Some(ref u) => u, None => panic!() } } + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ constant accesses static | note: the lint level is defined here --> $DIR/const_refers_to_static_cross_crate.rs:30:8 @@ -174,14 +160,10 @@ Future incompatibility report: Future breakage diagnostic: warning: any use of this value will cause an error --> $DIR/const_refers_to_static_cross_crate.rs:25:15 | -LL | / const U8_MUT2: &u8 = { -LL | | unsafe { &(*static_cross_crate::ZERO_REF)[0] } - | | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ constant accesses static -LL | | -LL | | -LL | | -LL | | }; - | |__- +LL | const U8_MUT2: &u8 = { + | ------------------ +LL | unsafe { &(*static_cross_crate::ZERO_REF)[0] } + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ constant accesses static | note: the lint level is defined here --> $DIR/const_refers_to_static_cross_crate.rs:23:8 @@ -195,14 +177,10 @@ Future breakage diagnostic: warning: any use of this value will cause an error --> $DIR/const_refers_to_static_cross_crate.rs:32:20 | -LL | / const U8_MUT3: &u8 = { -LL | | unsafe { match static_cross_crate::OPT_ZERO { Some(ref u) => u, None => panic!() } } - | | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ constant accesses static -LL | | -LL | | -LL | | -LL | | }; - | |__- +LL | const U8_MUT3: &u8 = { + | ------------------ +LL | unsafe { match static_cross_crate::OPT_ZERO { Some(ref u) => u, None => panic!() } } + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ constant accesses static | note: the lint level is defined here --> $DIR/const_refers_to_static_cross_crate.rs:30:8 diff --git a/src/test/ui/consts/miri_unleashed/mutable_references_err.32bit.stderr b/src/test/ui/consts/miri_unleashed/mutable_references_err.32bit.stderr index 70ce8db482a..bb8636f1225 100644 --- a/src/test/ui/consts/miri_unleashed/mutable_references_err.32bit.stderr +++ b/src/test/ui/consts/miri_unleashed/mutable_references_err.32bit.stderr @@ -1,10 +1,8 @@ error[E0080]: it is undefined behavior to use this value --> $DIR/mutable_references_err.rs:17:1 | -LL | / const MUH: Meh = Meh { -LL | | x: &UnsafeCell::new(42), -LL | | }; - | |__^ constructing invalid value at .x.<deref>: encountered `UnsafeCell` in a `const` +LL | const MUH: Meh = Meh { + | ^^^^^^^^^^^^^^ constructing invalid value at .x.<deref>: encountered `UnsafeCell` in a `const` | = note: The rules on what exactly is undefined behavior aren't clear, so this check might be overzealous. Please open an issue on the rustc repository if you believe it should not be considered undefined behavior. = note: the raw bytes of the constant (size: 4, align: 4) { @@ -15,7 +13,7 @@ error[E0080]: it is undefined behavior to use this value --> $DIR/mutable_references_err.rs:27:1 | LL | const SNEAKY: &dyn Sync = &Synced { x: UnsafeCell::new(42) }; - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ constructing invalid value at .<deref>.<dyn-downcast>.x: encountered `UnsafeCell` in a `const` + | ^^^^^^^^^^^^^^^^^^^^^^^ constructing invalid value at .<deref>.<dyn-downcast>.x: encountered `UnsafeCell` in a `const` | = note: The rules on what exactly is undefined behavior aren't clear, so this check might be overzealous. Please open an issue on the rustc repository if you believe it should not be considered undefined behavior. = note: the raw bytes of the constant (size: 8, align: 4) { @@ -26,7 +24,7 @@ error[E0080]: it is undefined behavior to use this value --> $DIR/mutable_references_err.rs:31:1 | LL | const BLUNT: &mut i32 = &mut 42; - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ constructing invalid value: encountered mutable reference in a `const` + | ^^^^^^^^^^^^^^^^^^^^^ constructing invalid value: encountered mutable reference in a `const` | = note: The rules on what exactly is undefined behavior aren't clear, so this check might be overzealous. Please open an issue on the rustc repository if you believe it should not be considered undefined behavior. = note: the raw bytes of the constant (size: 4, align: 4) { diff --git a/src/test/ui/consts/miri_unleashed/mutable_references_err.64bit.stderr b/src/test/ui/consts/miri_unleashed/mutable_references_err.64bit.stderr index 8ea00aace3d..f1652da922a 100644 --- a/src/test/ui/consts/miri_unleashed/mutable_references_err.64bit.stderr +++ b/src/test/ui/consts/miri_unleashed/mutable_references_err.64bit.stderr @@ -1,10 +1,8 @@ error[E0080]: it is undefined behavior to use this value --> $DIR/mutable_references_err.rs:17:1 | -LL | / const MUH: Meh = Meh { -LL | | x: &UnsafeCell::new(42), -LL | | }; - | |__^ constructing invalid value at .x.<deref>: encountered `UnsafeCell` in a `const` +LL | const MUH: Meh = Meh { + | ^^^^^^^^^^^^^^ constructing invalid value at .x.<deref>: encountered `UnsafeCell` in a `const` | = note: The rules on what exactly is undefined behavior aren't clear, so this check might be overzealous. Please open an issue on the rustc repository if you believe it should not be considered undefined behavior. = note: the raw bytes of the constant (size: 8, align: 8) { @@ -15,7 +13,7 @@ error[E0080]: it is undefined behavior to use this value --> $DIR/mutable_references_err.rs:27:1 | LL | const SNEAKY: &dyn Sync = &Synced { x: UnsafeCell::new(42) }; - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ constructing invalid value at .<deref>.<dyn-downcast>.x: encountered `UnsafeCell` in a `const` + | ^^^^^^^^^^^^^^^^^^^^^^^ constructing invalid value at .<deref>.<dyn-downcast>.x: encountered `UnsafeCell` in a `const` | = note: The rules on what exactly is undefined behavior aren't clear, so this check might be overzealous. Please open an issue on the rustc repository if you believe it should not be considered undefined behavior. = note: the raw bytes of the constant (size: 16, align: 8) { @@ -26,7 +24,7 @@ error[E0080]: it is undefined behavior to use this value --> $DIR/mutable_references_err.rs:31:1 | LL | const BLUNT: &mut i32 = &mut 42; - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ constructing invalid value: encountered mutable reference in a `const` + | ^^^^^^^^^^^^^^^^^^^^^ constructing invalid value: encountered mutable reference in a `const` | = note: The rules on what exactly is undefined behavior aren't clear, so this check might be overzealous. Please open an issue on the rustc repository if you believe it should not be considered undefined behavior. = note: the raw bytes of the constant (size: 8, align: 8) { diff --git a/src/test/ui/consts/miri_unleashed/raw_mutable_const.stderr b/src/test/ui/consts/miri_unleashed/raw_mutable_const.stderr index b5b5a965295..e145f6dd2ef 100644 --- a/src/test/ui/consts/miri_unleashed/raw_mutable_const.stderr +++ b/src/test/ui/consts/miri_unleashed/raw_mutable_const.stderr @@ -2,7 +2,7 @@ error: untyped pointers are not allowed in constant --> $DIR/raw_mutable_const.rs:7:1 | LL | const MUTABLE_BEHIND_RAW: *mut i32 = &UnsafeCell::new(42) as *const _ as *mut _; - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ warning: skipping const checks | diff --git a/src/test/ui/consts/offset_from_ub.rs b/src/test/ui/consts/offset_from_ub.rs index 10e368ba133..db2d421427c 100644 --- a/src/test/ui/consts/offset_from_ub.rs +++ b/src/test/ui/consts/offset_from_ub.rs @@ -34,14 +34,14 @@ pub const NOT_MULTIPLE_OF_SIZE: isize = { pub const OFFSET_FROM_NULL: isize = { let ptr = 0 as *const u8; unsafe { ptr_offset_from(ptr, ptr) } //~ERROR evaluation of constant value failed - //~| null pointer is not a valid pointer + //~| null pointer is a dangling pointer }; pub const DIFFERENT_INT: isize = { // offset_from with two different integers: like DIFFERENT_ALLOC let ptr1 = 8 as *const u8; let ptr2 = 16 as *const u8; unsafe { ptr_offset_from(ptr2, ptr1) } //~ERROR evaluation of constant value failed - //~| 0x8 is not a valid pointer + //~| 0x8[noalloc] is a dangling pointer }; const OUT_OF_BOUNDS_1: isize = { diff --git a/src/test/ui/consts/offset_from_ub.stderr b/src/test/ui/consts/offset_from_ub.stderr index eb7f1d7a6b2..daa1d736758 100644 --- a/src/test/ui/consts/offset_from_ub.stderr +++ b/src/test/ui/consts/offset_from_ub.stderr @@ -28,13 +28,13 @@ error[E0080]: evaluation of constant value failed --> $DIR/offset_from_ub.rs:36:14 | LL | unsafe { ptr_offset_from(ptr, ptr) } - | ^^^^^^^^^^^^^^^^^^^^^^^^^ out-of-bounds offset_from: null pointer is not a valid pointer + | ^^^^^^^^^^^^^^^^^^^^^^^^^ out-of-bounds offset_from: null pointer is a dangling pointer (it has no provenance) error[E0080]: evaluation of constant value failed --> $DIR/offset_from_ub.rs:43:14 | LL | unsafe { ptr_offset_from(ptr2, ptr1) } - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^ out-of-bounds offset_from: 0x8 is not a valid pointer + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^ out-of-bounds offset_from: 0x8[noalloc] is a dangling pointer (it has no provenance) error[E0080]: evaluation of constant value failed --> $DIR/offset_from_ub.rs:52:14 diff --git a/src/test/ui/consts/offset_ub.stderr b/src/test/ui/consts/offset_ub.stderr index 4d3e7ee2411..5a792bba50c 100644 --- a/src/test/ui/consts/offset_ub.stderr +++ b/src/test/ui/consts/offset_ub.stderr @@ -18,7 +18,7 @@ error[E0080]: evaluation of constant value failed LL | unsafe { intrinsics::offset(self, count) } | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ | | - | pointer arithmetic failed: allocN has size 1, so pointer to 2 bytes starting at offset 0 is out-of-bounds + | out-of-bounds pointer arithmetic: allocN has size 1, so pointer to 2 bytes starting at offset 0 is out-of-bounds | inside `ptr::const_ptr::<impl *const u8>::offset` at $SRC_DIR/core/src/ptr/const_ptr.rs:LL:COL | ::: $DIR/offset_ub.rs:8:43 @@ -32,7 +32,7 @@ error[E0080]: evaluation of constant value failed LL | unsafe { intrinsics::offset(self, count) } | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ | | - | pointer arithmetic failed: allocN has size 100, so pointer to 101 bytes starting at offset 0 is out-of-bounds + | out-of-bounds pointer arithmetic: allocN has size 100, so pointer to 101 bytes starting at offset 0 is out-of-bounds | inside `ptr::const_ptr::<impl *const u8>::offset` at $SRC_DIR/core/src/ptr/const_ptr.rs:LL:COL | ::: $DIR/offset_ub.rs:9:45 @@ -102,7 +102,7 @@ error[E0080]: evaluation of constant value failed LL | unsafe { intrinsics::offset(self, count) } | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ | | - | pointer arithmetic failed: allocN has size 1, so pointer to 2 bytes starting at offset -4 is out-of-bounds + | out-of-bounds pointer arithmetic: allocN has size 1, so pointer to 2 bytes starting at offset -4 is out-of-bounds | inside `ptr::const_ptr::<impl *const u8>::offset` at $SRC_DIR/core/src/ptr/const_ptr.rs:LL:COL | ::: $DIR/offset_ub.rs:15:49 @@ -116,7 +116,7 @@ error[E0080]: evaluation of constant value failed LL | unsafe { intrinsics::offset(self, count) } | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ | | - | pointer arithmetic failed: allocN has size 0, so pointer to 1 byte starting at offset 0 is out-of-bounds + | out-of-bounds pointer arithmetic: allocN has size 0, so pointer to 1 byte starting at offset 0 is out-of-bounds | inside `ptr::const_ptr::<impl *const u8>::offset` at $SRC_DIR/core/src/ptr/const_ptr.rs:LL:COL | ::: $DIR/offset_ub.rs:17:50 @@ -130,7 +130,7 @@ error[E0080]: evaluation of constant value failed LL | unsafe { intrinsics::offset(self, count) as *mut T } | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ | | - | pointer arithmetic failed: 0x1 is not a valid pointer + | out-of-bounds pointer arithmetic: 0x1[noalloc] is a dangling pointer (it has no provenance) | inside `ptr::mut_ptr::<impl *mut u8>::offset` at $SRC_DIR/core/src/ptr/mut_ptr.rs:LL:COL | ::: $DIR/offset_ub.rs:18:42 @@ -144,7 +144,7 @@ error[E0080]: evaluation of constant value failed LL | unsafe { intrinsics::offset(self, count) } | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ | | - | pointer arithmetic failed: null pointer is not a valid pointer + | out-of-bounds pointer arithmetic: null pointer is a dangling pointer (it has no provenance) | inside `ptr::const_ptr::<impl *const u8>::offset` at $SRC_DIR/core/src/ptr/const_ptr.rs:LL:COL | ::: $DIR/offset_ub.rs:21:50 @@ -158,7 +158,7 @@ error[E0080]: evaluation of constant value failed LL | unsafe { intrinsics::offset(self, count) } | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ | | - | pointer arithmetic failed: 0x7f..f is not a valid pointer + | out-of-bounds pointer arithmetic: 0x7f..f[noalloc] is a dangling pointer (it has no provenance) | inside `ptr::const_ptr::<impl *const u8>::offset` at $SRC_DIR/core/src/ptr/const_ptr.rs:LL:COL | ::: $DIR/offset_ub.rs:24:47 diff --git a/src/test/ui/consts/ptr_comparisons.stderr b/src/test/ui/consts/ptr_comparisons.stderr index 594576fe2cf..67b9fec4a0e 100644 --- a/src/test/ui/consts/ptr_comparisons.stderr +++ b/src/test/ui/consts/ptr_comparisons.stderr @@ -4,7 +4,7 @@ error[E0080]: evaluation of constant value failed LL | unsafe { intrinsics::offset(self, count) } | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ | | - | pointer arithmetic failed: alloc3 has size $WORD, so pointer to $TWO_WORDS bytes starting at offset 0 is out-of-bounds + | out-of-bounds pointer arithmetic: alloc3 has size $WORD, so pointer to $TWO_WORDS bytes starting at offset 0 is out-of-bounds | inside `ptr::const_ptr::<impl *const usize>::offset` at $SRC_DIR/core/src/ptr/const_ptr.rs:LL:COL | ::: $DIR/ptr_comparisons.rs:58:34 @@ -22,9 +22,7 @@ error: any use of this value will cause an error --> $DIR/ptr_comparisons.rs:65:27 | LL | const _: usize = unsafe { std::mem::transmute::<*const usize, usize>(FOO) + 4 }; - | --------------------------^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^--- - | | - | unable to turn pointer into raw bytes + | -------------- ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ unable to turn pointer into raw bytes | = note: `#[deny(const_err)]` on by default = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release! @@ -34,9 +32,7 @@ error: any use of this value will cause an error --> $DIR/ptr_comparisons.rs:70:27 | LL | const _: usize = unsafe { *std::mem::transmute::<&&usize, &usize>(&FOO) + 4 }; - | --------------------------^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^------- - | | - | unable to turn pointer into raw bytes + | -------------- ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ unable to turn pointer into raw bytes | = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release! = note: for more information, see issue #71800 <https://github.com/rust-lang/rust/issues/71800> @@ -49,9 +45,7 @@ error: any use of this value will cause an error --> $DIR/ptr_comparisons.rs:65:27 | LL | const _: usize = unsafe { std::mem::transmute::<*const usize, usize>(FOO) + 4 }; - | --------------------------^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^--- - | | - | unable to turn pointer into raw bytes + | -------------- ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ unable to turn pointer into raw bytes | = note: `#[deny(const_err)]` on by default = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release! @@ -62,9 +56,7 @@ error: any use of this value will cause an error --> $DIR/ptr_comparisons.rs:70:27 | LL | const _: usize = unsafe { *std::mem::transmute::<&&usize, &usize>(&FOO) + 4 }; - | --------------------------^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^------- - | | - | unable to turn pointer into raw bytes + | -------------- ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ unable to turn pointer into raw bytes | = note: `#[deny(const_err)]` on by default = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release! diff --git a/src/test/ui/consts/raw-ptr-const.stderr b/src/test/ui/consts/raw-ptr-const.stderr index 974b1c3ff45..0ebe1e95ca3 100644 --- a/src/test/ui/consts/raw-ptr-const.stderr +++ b/src/test/ui/consts/raw-ptr-const.stderr @@ -2,7 +2,7 @@ error: untyped pointers are not allowed in constant --> $DIR/raw-ptr-const.rs:7:1 | LL | const CONST_RAW: *const Vec<i32> = &Vec::new() as *const _; - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ error: aborting due to previous error diff --git a/src/test/ui/consts/recursive-zst-static.default.stderr b/src/test/ui/consts/recursive-zst-static.default.stderr index 104899f4900..d68960b0972 100644 --- a/src/test/ui/consts/recursive-zst-static.default.stderr +++ b/src/test/ui/consts/recursive-zst-static.default.stderr @@ -2,7 +2,7 @@ error[E0391]: cycle detected when const-evaluating + checking `FOO` --> $DIR/recursive-zst-static.rs:10:1 | LL | static FOO: () = FOO; - | ^^^^^^^^^^^^^^^^^^^^^ + | ^^^^^^^^^^^^^^ | note: ...which requires const-evaluating + checking `FOO`... --> $DIR/recursive-zst-static.rs:10:18 diff --git a/src/test/ui/consts/recursive-zst-static.unleash.stderr b/src/test/ui/consts/recursive-zst-static.unleash.stderr index 104899f4900..d68960b0972 100644 --- a/src/test/ui/consts/recursive-zst-static.unleash.stderr +++ b/src/test/ui/consts/recursive-zst-static.unleash.stderr @@ -2,7 +2,7 @@ error[E0391]: cycle detected when const-evaluating + checking `FOO` --> $DIR/recursive-zst-static.rs:10:1 | LL | static FOO: () = FOO; - | ^^^^^^^^^^^^^^^^^^^^^ + | ^^^^^^^^^^^^^^ | note: ...which requires const-evaluating + checking `FOO`... --> $DIR/recursive-zst-static.rs:10:18 diff --git a/src/test/ui/consts/recursive.stderr b/src/test/ui/consts/recursive.stderr index 8d1e10d4176..647ed1db20b 100644 --- a/src/test/ui/consts/recursive.stderr +++ b/src/test/ui/consts/recursive.stderr @@ -21,7 +21,7 @@ LL | f(x); | inside `X` at $DIR/recursive.rs:9:15 ... LL | const X: () = f(1); - | ------------------- + | ----------- | = note: `#[deny(const_err)]` on by default = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release! @@ -42,7 +42,7 @@ LL | f(x); | inside `X` at $DIR/recursive.rs:9:15 ... LL | const X: () = f(1); - | ------------------- + | ----------- | = note: `#[deny(const_err)]` on by default = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release! diff --git a/src/test/ui/consts/std/alloc.32bit.stderr b/src/test/ui/consts/std/alloc.32bit.stderr index 33e574b1708..79efcd3f62e 100644 --- a/src/test/ui/consts/std/alloc.32bit.stderr +++ b/src/test/ui/consts/std/alloc.32bit.stderr @@ -2,7 +2,7 @@ error[E0080]: it is undefined behavior to use this value --> $DIR/alloc.rs:9:1 | LL | const LAYOUT_INVALID_ZERO: Layout = unsafe { Layout::from_size_align_unchecked(0x1000, 0x00) }; - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ constructing invalid value at .align.0.<enum-tag>: encountered 0x00000000, but expected a valid enum tag + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ constructing invalid value at .align.0.<enum-tag>: encountered 0x00000000, but expected a valid enum tag | = note: The rules on what exactly is undefined behavior aren't clear, so this check might be overzealous. Please open an issue on the rustc repository if you believe it should not be considered undefined behavior. = note: the raw bytes of the constant (size: 8, align: 4) { @@ -13,7 +13,7 @@ error[E0080]: it is undefined behavior to use this value --> $DIR/alloc.rs:13:1 | LL | const LAYOUT_INVALID_THREE: Layout = unsafe { Layout::from_size_align_unchecked(9, 3) }; - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ constructing invalid value at .align.0.<enum-tag>: encountered 0x00000003, but expected a valid enum tag + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ constructing invalid value at .align.0.<enum-tag>: encountered 0x00000003, but expected a valid enum tag | = note: The rules on what exactly is undefined behavior aren't clear, so this check might be overzealous. Please open an issue on the rustc repository if you believe it should not be considered undefined behavior. = note: the raw bytes of the constant (size: 8, align: 4) { diff --git a/src/test/ui/consts/std/alloc.64bit.stderr b/src/test/ui/consts/std/alloc.64bit.stderr index 9556e30334d..cb477b72b31 100644 --- a/src/test/ui/consts/std/alloc.64bit.stderr +++ b/src/test/ui/consts/std/alloc.64bit.stderr @@ -2,7 +2,7 @@ error[E0080]: it is undefined behavior to use this value --> $DIR/alloc.rs:9:1 | LL | const LAYOUT_INVALID_ZERO: Layout = unsafe { Layout::from_size_align_unchecked(0x1000, 0x00) }; - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ constructing invalid value at .align.0.<enum-tag>: encountered 0x0000000000000000, but expected a valid enum tag + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ constructing invalid value at .align.0.<enum-tag>: encountered 0x0000000000000000, but expected a valid enum tag | = note: The rules on what exactly is undefined behavior aren't clear, so this check might be overzealous. Please open an issue on the rustc repository if you believe it should not be considered undefined behavior. = note: the raw bytes of the constant (size: 16, align: 8) { @@ -13,7 +13,7 @@ error[E0080]: it is undefined behavior to use this value --> $DIR/alloc.rs:13:1 | LL | const LAYOUT_INVALID_THREE: Layout = unsafe { Layout::from_size_align_unchecked(9, 3) }; - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ constructing invalid value at .align.0.<enum-tag>: encountered 0x0000000000000003, but expected a valid enum tag + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ constructing invalid value at .align.0.<enum-tag>: encountered 0x0000000000000003, but expected a valid enum tag | = note: The rules on what exactly is undefined behavior aren't clear, so this check might be overzealous. Please open an issue on the rustc repository if you believe it should not be considered undefined behavior. = note: the raw bytes of the constant (size: 16, align: 8) { diff --git a/src/test/ui/consts/std/cell.stderr b/src/test/ui/consts/std/cell.stderr index 355c326f0b6..937fa7db0c8 100644 --- a/src/test/ui/consts/std/cell.stderr +++ b/src/test/ui/consts/std/cell.stderr @@ -2,25 +2,25 @@ error: encountered dangling pointer in final constant --> $DIR/cell.rs:6:1 | LL | static FOO: Wrap<*mut u32> = Wrap(Cell::new(42).as_ptr()); - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | ^^^^^^^^^^^^^^^^^^^^^^^^^^ error: encountered dangling pointer in final constant --> $DIR/cell.rs:8:1 | LL | const FOO_CONST: Wrap<*mut u32> = Wrap(Cell::new(42).as_ptr()); - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ error: encountered dangling pointer in final constant --> $DIR/cell.rs:22:1 | LL | const FOO4_CONST: Wrap<*mut u32> = Wrap(FOO3_CONST.0.as_ptr()); - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ error: encountered dangling pointer in final constant --> $DIR/cell.rs:27:1 | LL | const FOO2: *mut u32 = Cell::new(42).as_ptr(); - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | ^^^^^^^^^^^^^^^^^^^^ error: aborting due to 4 previous errors diff --git a/src/test/ui/consts/uninhabited-const-issue-61744.stderr b/src/test/ui/consts/uninhabited-const-issue-61744.stderr index 17dd6131436..d3177784789 100644 --- a/src/test/ui/consts/uninhabited-const-issue-61744.stderr +++ b/src/test/ui/consts/uninhabited-const-issue-61744.stderr @@ -135,7 +135,7 @@ LL | hint_unreachable() | inside `<i32 as Const>::CONSTANT` at $DIR/uninhabited-const-issue-61744.rs:13:36 ... LL | const CONSTANT: i32 = unsafe { fake_type() }; - | --------------------------------------------- + | ------------------- | = note: `#[deny(const_err)]` on by default = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release! @@ -288,7 +288,7 @@ LL | hint_unreachable() | inside `<i32 as Const>::CONSTANT` at $DIR/uninhabited-const-issue-61744.rs:13:36 ... LL | const CONSTANT: i32 = unsafe { fake_type() }; - | --------------------------------------------- + | ------------------- | = note: `#[deny(const_err)]` on by default = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release! diff --git a/src/test/ui/consts/validate_never_arrays.32bit.stderr b/src/test/ui/consts/validate_never_arrays.32bit.stderr index fe36d9d2a28..a5dbc718145 100644 --- a/src/test/ui/consts/validate_never_arrays.32bit.stderr +++ b/src/test/ui/consts/validate_never_arrays.32bit.stderr @@ -2,7 +2,7 @@ error[E0080]: it is undefined behavior to use this value --> $DIR/validate_never_arrays.rs:4:1 | LL | const _: &[!; 1] = unsafe { &*(1_usize as *const [!; 1]) }; - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ constructing invalid value: encountered a reference pointing to uninhabited type [!; 1] + | ^^^^^^^^^^^^^^^^ constructing invalid value: encountered a reference pointing to uninhabited type [!; 1] | = note: The rules on what exactly is undefined behavior aren't clear, so this check might be overzealous. Please open an issue on the rustc repository if you believe it should not be considered undefined behavior. = note: the raw bytes of the constant (size: 4, align: 4) { @@ -13,7 +13,7 @@ error[E0080]: it is undefined behavior to use this value --> $DIR/validate_never_arrays.rs:7:1 | LL | const _: &[!] = unsafe { &*(1_usize as *const [!; 1]) }; - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ constructing invalid value at .<deref>[0]: encountered a value of the never type `!` + | ^^^^^^^^^^^^^ constructing invalid value at .<deref>[0]: encountered a value of the never type `!` | = note: The rules on what exactly is undefined behavior aren't clear, so this check might be overzealous. Please open an issue on the rustc repository if you believe it should not be considered undefined behavior. = note: the raw bytes of the constant (size: 8, align: 4) { @@ -24,7 +24,7 @@ error[E0080]: it is undefined behavior to use this value --> $DIR/validate_never_arrays.rs:8:1 | LL | const _: &[!] = unsafe { &*(1_usize as *const [!; 42]) }; - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ constructing invalid value at .<deref>[0]: encountered a value of the never type `!` + | ^^^^^^^^^^^^^ constructing invalid value at .<deref>[0]: encountered a value of the never type `!` | = note: The rules on what exactly is undefined behavior aren't clear, so this check might be overzealous. Please open an issue on the rustc repository if you believe it should not be considered undefined behavior. = note: the raw bytes of the constant (size: 8, align: 4) { diff --git a/src/test/ui/consts/validate_never_arrays.64bit.stderr b/src/test/ui/consts/validate_never_arrays.64bit.stderr index 9c545ac1546..dac4e200a89 100644 --- a/src/test/ui/consts/validate_never_arrays.64bit.stderr +++ b/src/test/ui/consts/validate_never_arrays.64bit.stderr @@ -2,7 +2,7 @@ error[E0080]: it is undefined behavior to use this value --> $DIR/validate_never_arrays.rs:4:1 | LL | const _: &[!; 1] = unsafe { &*(1_usize as *const [!; 1]) }; - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ constructing invalid value: encountered a reference pointing to uninhabited type [!; 1] + | ^^^^^^^^^^^^^^^^ constructing invalid value: encountered a reference pointing to uninhabited type [!; 1] | = note: The rules on what exactly is undefined behavior aren't clear, so this check might be overzealous. Please open an issue on the rustc repository if you believe it should not be considered undefined behavior. = note: the raw bytes of the constant (size: 8, align: 8) { @@ -13,7 +13,7 @@ error[E0080]: it is undefined behavior to use this value --> $DIR/validate_never_arrays.rs:7:1 | LL | const _: &[!] = unsafe { &*(1_usize as *const [!; 1]) }; - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ constructing invalid value at .<deref>[0]: encountered a value of the never type `!` + | ^^^^^^^^^^^^^ constructing invalid value at .<deref>[0]: encountered a value of the never type `!` | = note: The rules on what exactly is undefined behavior aren't clear, so this check might be overzealous. Please open an issue on the rustc repository if you believe it should not be considered undefined behavior. = note: the raw bytes of the constant (size: 16, align: 8) { @@ -24,7 +24,7 @@ error[E0080]: it is undefined behavior to use this value --> $DIR/validate_never_arrays.rs:8:1 | LL | const _: &[!] = unsafe { &*(1_usize as *const [!; 42]) }; - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ constructing invalid value at .<deref>[0]: encountered a value of the never type `!` + | ^^^^^^^^^^^^^ constructing invalid value at .<deref>[0]: encountered a value of the never type `!` | = note: The rules on what exactly is undefined behavior aren't clear, so this check might be overzealous. Please open an issue on the rustc repository if you believe it should not be considered undefined behavior. = note: the raw bytes of the constant (size: 16, align: 8) { diff --git a/src/test/ui/consts/write-to-static-mut-in-static.stderr b/src/test/ui/consts/write-to-static-mut-in-static.stderr index 8d5113cbfd9..395b2d42f97 100644 --- a/src/test/ui/consts/write-to-static-mut-in-static.stderr +++ b/src/test/ui/consts/write-to-static-mut-in-static.stderr @@ -8,7 +8,7 @@ error[E0391]: cycle detected when const-evaluating + checking `C` --> $DIR/write-to-static-mut-in-static.rs:5:1 | LL | pub static mut C: u32 = unsafe { C = 1; 0 }; - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | ^^^^^^^^^^^^^^^^^^^^^ | note: ...which requires const-evaluating + checking `C`... --> $DIR/write-to-static-mut-in-static.rs:5:34 diff --git a/src/test/ui/derive-uninhabited-enum-38885.stderr b/src/test/ui/derive-uninhabited-enum-38885.stderr index 4feaf3ac961..bd36a25686a 100644 --- a/src/test/ui/derive-uninhabited-enum-38885.stderr +++ b/src/test/ui/derive-uninhabited-enum-38885.stderr @@ -5,7 +5,7 @@ LL | enum Foo { | --- variant in this enum LL | Bar(u8), LL | Void(Void), - | ^^^^^^^^^^ + | ^^^^ | = note: `-W dead-code` implied by `-W unused` = note: `Foo` has a derived impl for the trait `Debug`, but this is intentionally ignored during dead code analysis diff --git a/src/test/ui/derives/clone-debug-dead-code-in-the-same-struct.stderr b/src/test/ui/derives/clone-debug-dead-code-in-the-same-struct.stderr index 383e0b4b725..baf34b46d8b 100644 --- a/src/test/ui/derives/clone-debug-dead-code-in-the-same-struct.stderr +++ b/src/test/ui/derives/clone-debug-dead-code-in-the-same-struct.stderr @@ -5,13 +5,13 @@ LL | pub struct Whatever { | -------- fields in this struct LL | pub field0: (), LL | field1: (), - | ^^^^^^^^^^ + | ^^^^^^ LL | field2: (), - | ^^^^^^^^^^ + | ^^^^^^ LL | field3: (), - | ^^^^^^^^^^ + | ^^^^^^ LL | field4: (), - | ^^^^^^^^^^ + | ^^^^^^ | note: the lint level is defined here --> $DIR/clone-debug-dead-code-in-the-same-struct.rs:1:11 diff --git a/src/test/ui/derives/clone-debug-dead-code.stderr b/src/test/ui/derives/clone-debug-dead-code.stderr index 73a00251188..38be486e332 100644 --- a/src/test/ui/derives/clone-debug-dead-code.stderr +++ b/src/test/ui/derives/clone-debug-dead-code.stderr @@ -2,7 +2,7 @@ error: field `f` is never read --> $DIR/clone-debug-dead-code.rs:6:12 | LL | struct A { f: () } - | - ^^^^^ + | - ^ | | | field in this struct | @@ -16,7 +16,7 @@ error: field `f` is never read --> $DIR/clone-debug-dead-code.rs:10:12 | LL | struct B { f: () } - | - ^^^^^ + | - ^ | | | field in this struct | @@ -26,7 +26,7 @@ error: field `f` is never read --> $DIR/clone-debug-dead-code.rs:14:12 | LL | struct C { f: () } - | - ^^^^^ + | - ^ | | | field in this struct | @@ -36,7 +36,7 @@ error: field `f` is never read --> $DIR/clone-debug-dead-code.rs:18:12 | LL | struct D { f: () } - | - ^^^^^ + | - ^ | | | field in this struct | @@ -46,7 +46,7 @@ error: field `f` is never read --> $DIR/clone-debug-dead-code.rs:21:12 | LL | struct E { f: () } - | - ^^^^^ + | - ^ | | | field in this struct diff --git a/src/test/ui/derives/derive-assoc-type-not-impl.stderr b/src/test/ui/derives/derive-assoc-type-not-impl.stderr index 592cc0ae90f..55847aeec55 100644 --- a/src/test/ui/derives/derive-assoc-type-not-impl.stderr +++ b/src/test/ui/derives/derive-assoc-type-not-impl.stderr @@ -8,7 +8,7 @@ LL | struct Bar<T: Foo> { | doesn't satisfy `Bar<NotClone>: Clone` ... LL | struct NotClone; - | ---------------- doesn't satisfy `NotClone: Clone` + | --------------- doesn't satisfy `NotClone: Clone` ... LL | Bar::<NotClone> { x: 1 }.clone(); | ^^^^^ method cannot be called on `Bar<NotClone>` due to unsatisfied trait bounds diff --git a/src/test/ui/derives/derives-span-PartialEq-enum-struct-variant.stderr b/src/test/ui/derives/derives-span-PartialEq-enum-struct-variant.stderr index 19d2425ff23..f655600b760 100644 --- a/src/test/ui/derives/derives-span-PartialEq-enum-struct-variant.stderr +++ b/src/test/ui/derives/derives-span-PartialEq-enum-struct-variant.stderr @@ -11,7 +11,7 @@ note: an implementation of `PartialEq<_>` might be missing for `Error` --> $DIR/derives-span-PartialEq-enum-struct-variant.rs:4:1 | LL | struct Error; - | ^^^^^^^^^^^^^ must implement `PartialEq<_>` + | ^^^^^^^^^^^^ must implement `PartialEq<_>` = note: this error originates in the derive macro `PartialEq` (in Nightly builds, run with -Z macro-backtrace for more info) help: consider annotating `Error` with `#[derive(PartialEq)]` | @@ -31,7 +31,7 @@ note: an implementation of `PartialEq<_>` might be missing for `Error` --> $DIR/derives-span-PartialEq-enum-struct-variant.rs:4:1 | LL | struct Error; - | ^^^^^^^^^^^^^ must implement `PartialEq<_>` + | ^^^^^^^^^^^^ must implement `PartialEq<_>` = note: this error originates in the derive macro `PartialEq` (in Nightly builds, run with -Z macro-backtrace for more info) help: consider annotating `Error` with `#[derive(PartialEq)]` | diff --git a/src/test/ui/derives/derives-span-PartialEq-enum.stderr b/src/test/ui/derives/derives-span-PartialEq-enum.stderr index 419832817ca..ce4b00bfbf5 100644 --- a/src/test/ui/derives/derives-span-PartialEq-enum.stderr +++ b/src/test/ui/derives/derives-span-PartialEq-enum.stderr @@ -11,7 +11,7 @@ note: an implementation of `PartialEq<_>` might be missing for `Error` --> $DIR/derives-span-PartialEq-enum.rs:4:1 | LL | struct Error; - | ^^^^^^^^^^^^^ must implement `PartialEq<_>` + | ^^^^^^^^^^^^ must implement `PartialEq<_>` = note: this error originates in the derive macro `PartialEq` (in Nightly builds, run with -Z macro-backtrace for more info) help: consider annotating `Error` with `#[derive(PartialEq)]` | @@ -31,7 +31,7 @@ note: an implementation of `PartialEq<_>` might be missing for `Error` --> $DIR/derives-span-PartialEq-enum.rs:4:1 | LL | struct Error; - | ^^^^^^^^^^^^^ must implement `PartialEq<_>` + | ^^^^^^^^^^^^ must implement `PartialEq<_>` = note: this error originates in the derive macro `PartialEq` (in Nightly builds, run with -Z macro-backtrace for more info) help: consider annotating `Error` with `#[derive(PartialEq)]` | diff --git a/src/test/ui/derives/derives-span-PartialEq-struct.stderr b/src/test/ui/derives/derives-span-PartialEq-struct.stderr index 0000f882542..c5c8f255fb3 100644 --- a/src/test/ui/derives/derives-span-PartialEq-struct.stderr +++ b/src/test/ui/derives/derives-span-PartialEq-struct.stderr @@ -11,7 +11,7 @@ note: an implementation of `PartialEq<_>` might be missing for `Error` --> $DIR/derives-span-PartialEq-struct.rs:4:1 | LL | struct Error; - | ^^^^^^^^^^^^^ must implement `PartialEq<_>` + | ^^^^^^^^^^^^ must implement `PartialEq<_>` = note: this error originates in the derive macro `PartialEq` (in Nightly builds, run with -Z macro-backtrace for more info) help: consider annotating `Error` with `#[derive(PartialEq)]` | @@ -31,7 +31,7 @@ note: an implementation of `PartialEq<_>` might be missing for `Error` --> $DIR/derives-span-PartialEq-struct.rs:4:1 | LL | struct Error; - | ^^^^^^^^^^^^^ must implement `PartialEq<_>` + | ^^^^^^^^^^^^ must implement `PartialEq<_>` = note: this error originates in the derive macro `PartialEq` (in Nightly builds, run with -Z macro-backtrace for more info) help: consider annotating `Error` with `#[derive(PartialEq)]` | diff --git a/src/test/ui/derives/derives-span-PartialEq-tuple-struct.stderr b/src/test/ui/derives/derives-span-PartialEq-tuple-struct.stderr index 07fa900a8c8..f5d609cb33f 100644 --- a/src/test/ui/derives/derives-span-PartialEq-tuple-struct.stderr +++ b/src/test/ui/derives/derives-span-PartialEq-tuple-struct.stderr @@ -11,7 +11,7 @@ note: an implementation of `PartialEq<_>` might be missing for `Error` --> $DIR/derives-span-PartialEq-tuple-struct.rs:4:1 | LL | struct Error; - | ^^^^^^^^^^^^^ must implement `PartialEq<_>` + | ^^^^^^^^^^^^ must implement `PartialEq<_>` = note: this error originates in the derive macro `PartialEq` (in Nightly builds, run with -Z macro-backtrace for more info) help: consider annotating `Error` with `#[derive(PartialEq)]` | @@ -31,7 +31,7 @@ note: an implementation of `PartialEq<_>` might be missing for `Error` --> $DIR/derives-span-PartialEq-tuple-struct.rs:4:1 | LL | struct Error; - | ^^^^^^^^^^^^^ must implement `PartialEq<_>` + | ^^^^^^^^^^^^ must implement `PartialEq<_>` = note: this error originates in the derive macro `PartialEq` (in Nightly builds, run with -Z macro-backtrace for more info) help: consider annotating `Error` with `#[derive(PartialEq)]` | diff --git a/src/test/ui/derives/deriving-meta-unknown-trait.stderr b/src/test/ui/derives/deriving-meta-unknown-trait.stderr index bfb673f86f4..f3ff95a85da 100644 --- a/src/test/ui/derives/deriving-meta-unknown-trait.stderr +++ b/src/test/ui/derives/deriving-meta-unknown-trait.stderr @@ -7,7 +7,7 @@ LL | #[derive(Eqr)] ::: $SRC_DIR/core/src/cmp.rs:LL:COL | LL | pub macro Eq($item:item) { - | ------------------------ similarly named derive macro `Eq` defined here + | ------------ similarly named derive macro `Eq` defined here error: cannot find derive macro `Eqr` in this scope --> $DIR/deriving-meta-unknown-trait.rs:1:10 @@ -18,7 +18,7 @@ LL | #[derive(Eqr)] ::: $SRC_DIR/core/src/cmp.rs:LL:COL | LL | pub macro Eq($item:item) { - | ------------------------ similarly named derive macro `Eq` defined here + | ------------ similarly named derive macro `Eq` defined here error: aborting due to 2 previous errors diff --git a/src/test/ui/derives/deriving-no-inner-impl-error-message.stderr b/src/test/ui/derives/deriving-no-inner-impl-error-message.stderr index 451058cd0ee..7875f072356 100644 --- a/src/test/ui/derives/deriving-no-inner-impl-error-message.stderr +++ b/src/test/ui/derives/deriving-no-inner-impl-error-message.stderr @@ -11,7 +11,7 @@ note: an implementation of `PartialEq<_>` might be missing for `NoCloneOrEq` --> $DIR/deriving-no-inner-impl-error-message.rs:1:1 | LL | struct NoCloneOrEq; - | ^^^^^^^^^^^^^^^^^^^ must implement `PartialEq<_>` + | ^^^^^^^^^^^^^^^^^^ must implement `PartialEq<_>` = note: this error originates in the derive macro `PartialEq` (in Nightly builds, run with -Z macro-backtrace for more info) help: consider annotating `NoCloneOrEq` with `#[derive(PartialEq)]` | @@ -31,7 +31,7 @@ note: an implementation of `PartialEq<_>` might be missing for `NoCloneOrEq` --> $DIR/deriving-no-inner-impl-error-message.rs:1:1 | LL | struct NoCloneOrEq; - | ^^^^^^^^^^^^^^^^^^^ must implement `PartialEq<_>` + | ^^^^^^^^^^^^^^^^^^ must implement `PartialEq<_>` = note: this error originates in the derive macro `PartialEq` (in Nightly builds, run with -Z macro-backtrace for more info) help: consider annotating `NoCloneOrEq` with `#[derive(PartialEq)]` | diff --git a/src/test/ui/derives/issue-91492.stderr b/src/test/ui/derives/issue-91492.stderr index e479b539fec..5b4feaeb52a 100644 --- a/src/test/ui/derives/issue-91492.stderr +++ b/src/test/ui/derives/issue-91492.stderr @@ -2,7 +2,7 @@ error[E0599]: the method `extend_from_slice` exists for mutable reference `&mut --> $DIR/issue-91492.rs:4:9 | LL | pub struct NoDerives; - | --------------------- doesn't satisfy `NoDerives: Clone` + | -------------------- doesn't satisfy `NoDerives: Clone` LL | fn fun1(foo: &mut Vec<NoDerives>, bar: &[NoDerives]) { LL | foo.extend_from_slice(bar); | ^^^^^^^^^^^^^^^^^ @@ -18,7 +18,7 @@ error[E0599]: the method `extend_from_slice` exists for mutable reference `&mut --> $DIR/issue-91492.rs:12:9 | LL | pub struct SomeDerives; - | ----------------------- doesn't satisfy `SomeDerives: Clone` + | ---------------------- doesn't satisfy `SomeDerives: Clone` LL | fn fun2(foo: &mut Vec<SomeDerives>, bar: &[SomeDerives]) { LL | foo.extend_from_slice(bar); | ^^^^^^^^^^^^^^^^^ @@ -34,7 +34,7 @@ error[E0599]: the method `use_clone` exists for struct `Object<NoDerives, SomeDe --> $DIR/issue-91492.rs:22:9 | LL | pub struct NoDerives; - | --------------------- doesn't satisfy `NoDerives: Clone` + | -------------------- doesn't satisfy `NoDerives: Clone` ... LL | struct Object<T, A>(T, A); | ------ method `use_clone` not found for this struct diff --git a/src/test/ui/derives/issue-91550.stderr b/src/test/ui/derives/issue-91550.stderr index b1bec5432e3..3608052e2ff 100644 --- a/src/test/ui/derives/issue-91550.stderr +++ b/src/test/ui/derives/issue-91550.stderr @@ -2,7 +2,7 @@ error[E0599]: the method `insert` exists for struct `HashSet<Value>`, but its tr --> $DIR/issue-91550.rs:8:8 | LL | struct Value(u32); - | ------------------ + | ------------ | | | doesn't satisfy `Value: Eq` | doesn't satisfy `Value: Hash` @@ -22,7 +22,7 @@ error[E0599]: the method `use_eq` exists for struct `Object<NoDerives>`, but its --> $DIR/issue-91550.rs:26:9 | LL | pub struct NoDerives; - | --------------------- doesn't satisfy `NoDerives: Eq` + | -------------------- doesn't satisfy `NoDerives: Eq` LL | LL | struct Object<T>(T); | ------ method `use_eq` not found for this struct @@ -41,7 +41,7 @@ error[E0599]: the method `use_ord` exists for struct `Object<NoDerives>`, but it --> $DIR/issue-91550.rs:27:9 | LL | pub struct NoDerives; - | --------------------- doesn't satisfy `NoDerives: Ord` + | -------------------- doesn't satisfy `NoDerives: Ord` LL | LL | struct Object<T>(T); | ------ method `use_ord` not found for this struct @@ -60,7 +60,7 @@ error[E0599]: the method `use_ord_and_partial_ord` exists for struct `Object<NoD --> $DIR/issue-91550.rs:28:9 | LL | pub struct NoDerives; - | --------------------- + | -------------------- | | | doesn't satisfy `NoDerives: Ord` | doesn't satisfy `NoDerives: PartialOrd` diff --git a/src/test/ui/deriving/deriving-all-codegen.rs b/src/test/ui/deriving/deriving-all-codegen.rs index 2f6ef74ac49..028ed9c2305 100644 --- a/src/test/ui/deriving/deriving-all-codegen.rs +++ b/src/test/ui/deriving/deriving-all-codegen.rs @@ -28,12 +28,17 @@ struct Point { y: u32, } -// A long struct. +// A large struct. #[derive(Clone, Debug, Default, Hash, PartialEq, Eq, PartialOrd, Ord)] struct Big { b1: u32, b2: u32, b3: u32, b4: u32, b5: u32, b6: u32, b7: u32, b8:u32, } +// A packed tuple struct. +#[derive(Clone, Copy, Debug, Default, Hash, PartialEq, Eq, PartialOrd, Ord)] +#[repr(packed)] +struct Packed(u32); + // A C-like, fieldless enum. #[derive(Clone, Copy, Debug, Default, Hash, PartialEq, Eq, PartialOrd, Ord)] enum Fieldless { diff --git a/src/test/ui/deriving/deriving-all-codegen.stdout b/src/test/ui/deriving/deriving-all-codegen.stdout index faa5a3c3ddf..c24ed4237b8 100644 --- a/src/test/ui/deriving/deriving-all-codegen.stdout +++ b/src/test/ui/deriving/deriving-all-codegen.stdout @@ -37,7 +37,7 @@ impl ::core::marker::Copy for Empty { } #[allow(unused_qualifications)] impl ::core::fmt::Debug for Empty { fn fmt(&self, f: &mut ::core::fmt::Formatter) -> ::core::fmt::Result { - match *self { Self => ::core::fmt::Formatter::write_str(f, "Empty"), } + ::core::fmt::Formatter::write_str(f, "Empty") } } #[automatically_derived] @@ -49,18 +49,14 @@ impl ::core::default::Default for Empty { #[automatically_derived] #[allow(unused_qualifications)] impl ::core::hash::Hash for Empty { - fn hash<__H: ::core::hash::Hasher>(&self, state: &mut __H) -> () { - match *self { Self => {} } - } + fn hash<__H: ::core::hash::Hasher>(&self, state: &mut __H) -> () { {} } } impl ::core::marker::StructuralPartialEq for Empty {} #[automatically_derived] #[allow(unused_qualifications)] impl ::core::cmp::PartialEq for Empty { #[inline] - fn eq(&self, other: &Empty) -> bool { - match *other { Self => match *self { Self => true, }, } - } + fn eq(&self, other: &Empty) -> bool { true } } impl ::core::marker::StructuralEq for Empty {} #[automatically_derived] @@ -77,13 +73,7 @@ impl ::core::cmp::PartialOrd for Empty { #[inline] fn partial_cmp(&self, other: &Empty) -> ::core::option::Option<::core::cmp::Ordering> { - match *other { - Self => - match *self { - Self => - ::core::option::Option::Some(::core::cmp::Ordering::Equal), - }, - } + ::core::option::Option::Some(::core::cmp::Ordering::Equal) } } #[automatically_derived] @@ -91,9 +81,7 @@ impl ::core::cmp::PartialOrd for Empty { impl ::core::cmp::Ord for Empty { #[inline] fn cmp(&self, other: &Empty) -> ::core::cmp::Ordering { - match *other { - Self => match *self { Self => ::core::cmp::Ordering::Equal, }, - } + ::core::cmp::Ordering::Equal } } @@ -121,11 +109,8 @@ impl ::core::marker::Copy for Point { } #[allow(unused_qualifications)] impl ::core::fmt::Debug for Point { fn fmt(&self, f: &mut ::core::fmt::Formatter) -> ::core::fmt::Result { - match *self { - Self { x: ref __self_0_0, y: ref __self_0_1 } => - ::core::fmt::Formatter::debug_struct_field2_finish(f, "Point", - "x", &&(*__self_0_0), "y", &&(*__self_0_1)), - } + ::core::fmt::Formatter::debug_struct_field2_finish(f, "Point", "x", + &&self.x, "y", &&self.y) } } #[automatically_derived] @@ -143,11 +128,9 @@ impl ::core::default::Default for Point { #[allow(unused_qualifications)] impl ::core::hash::Hash for Point { fn hash<__H: ::core::hash::Hasher>(&self, state: &mut __H) -> () { - match *self { - Self { x: ref __self_0_0, y: ref __self_0_1 } => { - ::core::hash::Hash::hash(&(*__self_0_0), state); - ::core::hash::Hash::hash(&(*__self_0_1), state) - } + { + ::core::hash::Hash::hash(&self.x, state); + ::core::hash::Hash::hash(&self.y, state) } } } @@ -157,25 +140,11 @@ impl ::core::marker::StructuralPartialEq for Point {} impl ::core::cmp::PartialEq for Point { #[inline] fn eq(&self, other: &Point) -> bool { - match *other { - Self { x: ref __self_1_0, y: ref __self_1_1 } => - match *self { - Self { x: ref __self_0_0, y: ref __self_0_1 } => - (*__self_0_0) == (*__self_1_0) && - (*__self_0_1) == (*__self_1_1), - }, - } + self.x == other.x && self.y == other.y } #[inline] fn ne(&self, other: &Point) -> bool { - match *other { - Self { x: ref __self_1_0, y: ref __self_1_1 } => - match *self { - Self { x: ref __self_0_0, y: ref __self_0_1 } => - (*__self_0_0) != (*__self_1_0) || - (*__self_0_1) != (*__self_1_1), - }, - } + self.x != other.x || self.y != other.y } } impl ::core::marker::StructuralEq for Point {} @@ -198,24 +167,16 @@ impl ::core::cmp::PartialOrd for Point { #[inline] fn partial_cmp(&self, other: &Point) -> ::core::option::Option<::core::cmp::Ordering> { - match *other { - Self { x: ref __self_1_0, y: ref __self_1_1 } => - match *self { - Self { x: ref __self_0_0, y: ref __self_0_1 } => - match ::core::cmp::PartialOrd::partial_cmp(&(*__self_0_0), - &(*__self_1_0)) { - ::core::option::Option::Some(::core::cmp::Ordering::Equal) - => - match ::core::cmp::PartialOrd::partial_cmp(&(*__self_0_1), - &(*__self_1_1)) { - ::core::option::Option::Some(::core::cmp::Ordering::Equal) - => - ::core::option::Option::Some(::core::cmp::Ordering::Equal), - cmp => cmp, - }, - cmp => cmp, - }, + match ::core::cmp::PartialOrd::partial_cmp(&self.x, &other.x) { + ::core::option::Option::Some(::core::cmp::Ordering::Equal) => + match ::core::cmp::PartialOrd::partial_cmp(&self.y, &other.y) + { + ::core::option::Option::Some(::core::cmp::Ordering::Equal) + => + ::core::option::Option::Some(::core::cmp::Ordering::Equal), + cmp => cmp, }, + cmp => cmp, } } } @@ -224,27 +185,19 @@ impl ::core::cmp::PartialOrd for Point { impl ::core::cmp::Ord for Point { #[inline] fn cmp(&self, other: &Point) -> ::core::cmp::Ordering { - match *other { - Self { x: ref __self_1_0, y: ref __self_1_1 } => - match *self { - Self { x: ref __self_0_0, y: ref __self_0_1 } => - match ::core::cmp::Ord::cmp(&(*__self_0_0), &(*__self_1_0)) - { - ::core::cmp::Ordering::Equal => - match ::core::cmp::Ord::cmp(&(*__self_0_1), &(*__self_1_1)) - { - ::core::cmp::Ordering::Equal => - ::core::cmp::Ordering::Equal, - cmp => cmp, - }, - cmp => cmp, - }, + match ::core::cmp::Ord::cmp(&self.x, &other.x) { + ::core::cmp::Ordering::Equal => + match ::core::cmp::Ord::cmp(&self.y, &other.y) { + ::core::cmp::Ordering::Equal => + ::core::cmp::Ordering::Equal, + cmp => cmp, }, + cmp => cmp, } } } -// A long struct. +// A large struct. struct Big { b1: u32, b2: u32, @@ -260,26 +213,15 @@ struct Big { impl ::core::clone::Clone for Big { #[inline] fn clone(&self) -> Big { - match *self { - Self { - b1: ref __self_0_0, - b2: ref __self_0_1, - b3: ref __self_0_2, - b4: ref __self_0_3, - b5: ref __self_0_4, - b6: ref __self_0_5, - b7: ref __self_0_6, - b8: ref __self_0_7 } => - Big { - b1: ::core::clone::Clone::clone(&(*__self_0_0)), - b2: ::core::clone::Clone::clone(&(*__self_0_1)), - b3: ::core::clone::Clone::clone(&(*__self_0_2)), - b4: ::core::clone::Clone::clone(&(*__self_0_3)), - b5: ::core::clone::Clone::clone(&(*__self_0_4)), - b6: ::core::clone::Clone::clone(&(*__self_0_5)), - b7: ::core::clone::Clone::clone(&(*__self_0_6)), - b8: ::core::clone::Clone::clone(&(*__self_0_7)), - }, + Big { + b1: ::core::clone::Clone::clone(&self.b1), + b2: ::core::clone::Clone::clone(&self.b2), + b3: ::core::clone::Clone::clone(&self.b3), + b4: ::core::clone::Clone::clone(&self.b4), + b5: ::core::clone::Clone::clone(&self.b5), + b6: ::core::clone::Clone::clone(&self.b6), + b7: ::core::clone::Clone::clone(&self.b7), + b8: ::core::clone::Clone::clone(&self.b8), } } } @@ -287,25 +229,14 @@ impl ::core::clone::Clone for Big { #[allow(unused_qualifications)] impl ::core::fmt::Debug for Big { fn fmt(&self, f: &mut ::core::fmt::Formatter) -> ::core::fmt::Result { - match *self { - Self { - b1: ref __self_0_0, - b2: ref __self_0_1, - b3: ref __self_0_2, - b4: ref __self_0_3, - b5: ref __self_0_4, - b6: ref __self_0_5, - b7: ref __self_0_6, - b8: ref __self_0_7 } => { - let names: &'static _ = - &["b1", "b2", "b3", "b4", "b5", "b6", "b7", "b8"]; - let values: &[&dyn ::core::fmt::Debug] = - &[&&(*__self_0_0), &&(*__self_0_1), &&(*__self_0_2), - &&(*__self_0_3), &&(*__self_0_4), &&(*__self_0_5), - &&(*__self_0_6), &&(*__self_0_7)]; - ::core::fmt::Formatter::debug_struct_fields_finish(f, "Big", - names, values) - } + { + let names: &'static _ = + &["b1", "b2", "b3", "b4", "b5", "b6", "b7", "b8"]; + let values: &[&dyn ::core::fmt::Debug] = + &[&&self.b1, &&self.b2, &&self.b3, &&self.b4, &&self.b5, + &&self.b6, &&self.b7, &&self.b8]; + ::core::fmt::Formatter::debug_struct_fields_finish(f, "Big", + names, values) } } } @@ -330,25 +261,15 @@ impl ::core::default::Default for Big { #[allow(unused_qualifications)] impl ::core::hash::Hash for Big { fn hash<__H: ::core::hash::Hasher>(&self, state: &mut __H) -> () { - match *self { - Self { - b1: ref __self_0_0, - b2: ref __self_0_1, - b3: ref __self_0_2, - b4: ref __self_0_3, - b5: ref __self_0_4, - b6: ref __self_0_5, - b7: ref __self_0_6, - b8: ref __self_0_7 } => { - ::core::hash::Hash::hash(&(*__self_0_0), state); - ::core::hash::Hash::hash(&(*__self_0_1), state); - ::core::hash::Hash::hash(&(*__self_0_2), state); - ::core::hash::Hash::hash(&(*__self_0_3), state); - ::core::hash::Hash::hash(&(*__self_0_4), state); - ::core::hash::Hash::hash(&(*__self_0_5), state); - ::core::hash::Hash::hash(&(*__self_0_6), state); - ::core::hash::Hash::hash(&(*__self_0_7), state) - } + { + ::core::hash::Hash::hash(&self.b1, state); + ::core::hash::Hash::hash(&self.b2, state); + ::core::hash::Hash::hash(&self.b3, state); + ::core::hash::Hash::hash(&self.b4, state); + ::core::hash::Hash::hash(&self.b5, state); + ::core::hash::Hash::hash(&self.b6, state); + ::core::hash::Hash::hash(&self.b7, state); + ::core::hash::Hash::hash(&self.b8, state) } } } @@ -358,69 +279,17 @@ impl ::core::marker::StructuralPartialEq for Big {} impl ::core::cmp::PartialEq for Big { #[inline] fn eq(&self, other: &Big) -> bool { - match *other { - Self { - b1: ref __self_1_0, - b2: ref __self_1_1, - b3: ref __self_1_2, - b4: ref __self_1_3, - b5: ref __self_1_4, - b6: ref __self_1_5, - b7: ref __self_1_6, - b8: ref __self_1_7 } => - match *self { - Self { - b1: ref __self_0_0, - b2: ref __self_0_1, - b3: ref __self_0_2, - b4: ref __self_0_3, - b5: ref __self_0_4, - b6: ref __self_0_5, - b7: ref __self_0_6, - b8: ref __self_0_7 } => - (*__self_0_0) == (*__self_1_0) && - (*__self_0_1) == (*__self_1_1) && - (*__self_0_2) == (*__self_1_2) && - (*__self_0_3) == (*__self_1_3) && - (*__self_0_4) == (*__self_1_4) && - (*__self_0_5) == (*__self_1_5) && - (*__self_0_6) == (*__self_1_6) && - (*__self_0_7) == (*__self_1_7), - }, - } + self.b1 == other.b1 && self.b2 == other.b2 && self.b3 == other.b3 && + self.b4 == other.b4 && self.b5 == other.b5 && + self.b6 == other.b6 && self.b7 == other.b7 && + self.b8 == other.b8 } #[inline] fn ne(&self, other: &Big) -> bool { - match *other { - Self { - b1: ref __self_1_0, - b2: ref __self_1_1, - b3: ref __self_1_2, - b4: ref __self_1_3, - b5: ref __self_1_4, - b6: ref __self_1_5, - b7: ref __self_1_6, - b8: ref __self_1_7 } => - match *self { - Self { - b1: ref __self_0_0, - b2: ref __self_0_1, - b3: ref __self_0_2, - b4: ref __self_0_3, - b5: ref __self_0_4, - b6: ref __self_0_5, - b7: ref __self_0_6, - b8: ref __self_0_7 } => - (*__self_0_0) != (*__self_1_0) || - (*__self_0_1) != (*__self_1_1) || - (*__self_0_2) != (*__self_1_2) || - (*__self_0_3) != (*__self_1_3) || - (*__self_0_4) != (*__self_1_4) || - (*__self_0_5) != (*__self_1_5) || - (*__self_0_6) != (*__self_1_6) || - (*__self_0_7) != (*__self_1_7), - }, - } + self.b1 != other.b1 || self.b2 != other.b2 || self.b3 != other.b3 || + self.b4 != other.b4 || self.b5 != other.b5 || + self.b6 != other.b6 || self.b7 != other.b7 || + self.b8 != other.b8 } } impl ::core::marker::StructuralEq for Big {} @@ -449,63 +318,37 @@ impl ::core::cmp::PartialOrd for Big { #[inline] fn partial_cmp(&self, other: &Big) -> ::core::option::Option<::core::cmp::Ordering> { - match *other { - Self { - b1: ref __self_1_0, - b2: ref __self_1_1, - b3: ref __self_1_2, - b4: ref __self_1_3, - b5: ref __self_1_4, - b6: ref __self_1_5, - b7: ref __self_1_6, - b8: ref __self_1_7 } => - match *self { - Self { - b1: ref __self_0_0, - b2: ref __self_0_1, - b3: ref __self_0_2, - b4: ref __self_0_3, - b5: ref __self_0_4, - b6: ref __self_0_5, - b7: ref __self_0_6, - b8: ref __self_0_7 } => - match ::core::cmp::PartialOrd::partial_cmp(&(*__self_0_0), - &(*__self_1_0)) { + match ::core::cmp::PartialOrd::partial_cmp(&self.b1, &other.b1) { + ::core::option::Option::Some(::core::cmp::Ordering::Equal) => + match ::core::cmp::PartialOrd::partial_cmp(&self.b2, + &other.b2) { + ::core::option::Option::Some(::core::cmp::Ordering::Equal) + => + match ::core::cmp::PartialOrd::partial_cmp(&self.b3, + &other.b3) { ::core::option::Option::Some(::core::cmp::Ordering::Equal) => - match ::core::cmp::PartialOrd::partial_cmp(&(*__self_0_1), - &(*__self_1_1)) { + match ::core::cmp::PartialOrd::partial_cmp(&self.b4, + &other.b4) { ::core::option::Option::Some(::core::cmp::Ordering::Equal) => - match ::core::cmp::PartialOrd::partial_cmp(&(*__self_0_2), - &(*__self_1_2)) { + match ::core::cmp::PartialOrd::partial_cmp(&self.b5, + &other.b5) { ::core::option::Option::Some(::core::cmp::Ordering::Equal) => - match ::core::cmp::PartialOrd::partial_cmp(&(*__self_0_3), - &(*__self_1_3)) { + match ::core::cmp::PartialOrd::partial_cmp(&self.b6, + &other.b6) { ::core::option::Option::Some(::core::cmp::Ordering::Equal) => - match ::core::cmp::PartialOrd::partial_cmp(&(*__self_0_4), - &(*__self_1_4)) { + match ::core::cmp::PartialOrd::partial_cmp(&self.b7, + &other.b7) { ::core::option::Option::Some(::core::cmp::Ordering::Equal) => - match ::core::cmp::PartialOrd::partial_cmp(&(*__self_0_5), - &(*__self_1_5)) { + match ::core::cmp::PartialOrd::partial_cmp(&self.b8, + &other.b8) { ::core::option::Option::Some(::core::cmp::Ordering::Equal) => - match ::core::cmp::PartialOrd::partial_cmp(&(*__self_0_6), - &(*__self_1_6)) { - ::core::option::Option::Some(::core::cmp::Ordering::Equal) - => - match ::core::cmp::PartialOrd::partial_cmp(&(*__self_0_7), - &(*__self_1_7)) { - ::core::option::Option::Some(::core::cmp::Ordering::Equal) - => - ::core::option::Option::Some(::core::cmp::Ordering::Equal), - cmp => cmp, - }, - cmp => cmp, - }, + ::core::option::Option::Some(::core::cmp::Ordering::Equal), cmp => cmp, }, cmp => cmp, @@ -518,7 +361,9 @@ impl ::core::cmp::PartialOrd for Big { }, cmp => cmp, }, + cmp => cmp, }, + cmp => cmp, } } } @@ -527,55 +372,23 @@ impl ::core::cmp::PartialOrd for Big { impl ::core::cmp::Ord for Big { #[inline] fn cmp(&self, other: &Big) -> ::core::cmp::Ordering { - match *other { - Self { - b1: ref __self_1_0, - b2: ref __self_1_1, - b3: ref __self_1_2, - b4: ref __self_1_3, - b5: ref __self_1_4, - b6: ref __self_1_5, - b7: ref __self_1_6, - b8: ref __self_1_7 } => - match *self { - Self { - b1: ref __self_0_0, - b2: ref __self_0_1, - b3: ref __self_0_2, - b4: ref __self_0_3, - b5: ref __self_0_4, - b6: ref __self_0_5, - b7: ref __self_0_6, - b8: ref __self_0_7 } => - match ::core::cmp::Ord::cmp(&(*__self_0_0), &(*__self_1_0)) - { + match ::core::cmp::Ord::cmp(&self.b1, &other.b1) { + ::core::cmp::Ordering::Equal => + match ::core::cmp::Ord::cmp(&self.b2, &other.b2) { + ::core::cmp::Ordering::Equal => + match ::core::cmp::Ord::cmp(&self.b3, &other.b3) { ::core::cmp::Ordering::Equal => - match ::core::cmp::Ord::cmp(&(*__self_0_1), &(*__self_1_1)) - { + match ::core::cmp::Ord::cmp(&self.b4, &other.b4) { ::core::cmp::Ordering::Equal => - match ::core::cmp::Ord::cmp(&(*__self_0_2), &(*__self_1_2)) - { + match ::core::cmp::Ord::cmp(&self.b5, &other.b5) { ::core::cmp::Ordering::Equal => - match ::core::cmp::Ord::cmp(&(*__self_0_3), &(*__self_1_3)) - { + match ::core::cmp::Ord::cmp(&self.b6, &other.b6) { ::core::cmp::Ordering::Equal => - match ::core::cmp::Ord::cmp(&(*__self_0_4), &(*__self_1_4)) - { + match ::core::cmp::Ord::cmp(&self.b7, &other.b7) { ::core::cmp::Ordering::Equal => - match ::core::cmp::Ord::cmp(&(*__self_0_5), &(*__self_1_5)) - { + match ::core::cmp::Ord::cmp(&self.b8, &other.b8) { ::core::cmp::Ordering::Equal => - match ::core::cmp::Ord::cmp(&(*__self_0_6), &(*__self_1_6)) - { - ::core::cmp::Ordering::Equal => - match ::core::cmp::Ord::cmp(&(*__self_0_7), &(*__self_1_7)) - { - ::core::cmp::Ordering::Equal => - ::core::cmp::Ordering::Equal, - cmp => cmp, - }, - cmp => cmp, - }, + ::core::cmp::Ordering::Equal, cmp => cmp, }, cmp => cmp, @@ -588,7 +401,116 @@ impl ::core::cmp::Ord for Big { }, cmp => cmp, }, + cmp => cmp, }, + cmp => cmp, + } + } +} + +// A packed tuple struct. +#[repr(packed)] +struct Packed(u32); +#[automatically_derived] +#[allow(unused_qualifications)] +impl ::core::clone::Clone for Packed { + #[inline] + fn clone(&self) -> Packed { + { let _: ::core::clone::AssertParamIsClone<u32>; *self } + } +} +#[automatically_derived] +#[allow(unused_qualifications)] +impl ::core::marker::Copy for Packed { } +#[automatically_derived] +#[allow(unused_qualifications)] +impl ::core::fmt::Debug for Packed { + fn fmt(&self, f: &mut ::core::fmt::Formatter) -> ::core::fmt::Result { + { + let Self(__self_0_0) = *self; + ::core::fmt::Formatter::debug_tuple_field1_finish(f, "Packed", + &&__self_0_0) + } + } +} +#[automatically_derived] +#[allow(unused_qualifications)] +impl ::core::default::Default for Packed { + #[inline] + fn default() -> Packed { Packed(::core::default::Default::default()) } +} +#[automatically_derived] +#[allow(unused_qualifications)] +impl ::core::hash::Hash for Packed { + fn hash<__H: ::core::hash::Hasher>(&self, state: &mut __H) -> () { + { + let Self(__self_0_0) = *self; + { ::core::hash::Hash::hash(&__self_0_0, state) } + } + } +} +impl ::core::marker::StructuralPartialEq for Packed {} +#[automatically_derived] +#[allow(unused_qualifications)] +impl ::core::cmp::PartialEq for Packed { + #[inline] + fn eq(&self, other: &Packed) -> bool { + { + let Self(__self_0_0) = *self; + let Self(__self_1_0) = *other; + __self_0_0 == __self_1_0 + } + } + #[inline] + fn ne(&self, other: &Packed) -> bool { + { + let Self(__self_0_0) = *self; + let Self(__self_1_0) = *other; + __self_0_0 != __self_1_0 + } + } +} +impl ::core::marker::StructuralEq for Packed {} +#[automatically_derived] +#[allow(unused_qualifications)] +impl ::core::cmp::Eq for Packed { + #[inline] + #[doc(hidden)] + #[no_coverage] + fn assert_receiver_is_total_eq(&self) -> () { + { let _: ::core::cmp::AssertParamIsEq<u32>; } + } +} +#[automatically_derived] +#[allow(unused_qualifications)] +impl ::core::cmp::PartialOrd for Packed { + #[inline] + fn partial_cmp(&self, other: &Packed) + -> ::core::option::Option<::core::cmp::Ordering> { + { + let Self(__self_0_0) = *self; + let Self(__self_1_0) = *other; + match ::core::cmp::PartialOrd::partial_cmp(&__self_0_0, + &__self_1_0) { + ::core::option::Option::Some(::core::cmp::Ordering::Equal) => + ::core::option::Option::Some(::core::cmp::Ordering::Equal), + cmp => cmp, + } + } + } +} +#[automatically_derived] +#[allow(unused_qualifications)] +impl ::core::cmp::Ord for Packed { + #[inline] + fn cmp(&self, other: &Packed) -> ::core::cmp::Ordering { + { + let Self(__self_0_0) = *self; + let Self(__self_1_0) = *other; + match ::core::cmp::Ord::cmp(&__self_0_0, &__self_1_0) { + ::core::cmp::Ordering::Equal => ::core::cmp::Ordering::Equal, + cmp => cmp, + } } } } @@ -738,10 +660,10 @@ impl ::core::fmt::Debug for Mixed { (&Mixed::Q,) => ::core::fmt::Formatter::write_str(f, "Q"), (&Mixed::R(ref __self_0),) => ::core::fmt::Formatter::debug_tuple_field1_finish(f, "R", - &&(*__self_0)), + &&*__self_0), (&Mixed::S { d1: ref __self_0, d2: ref __self_1 },) => ::core::fmt::Formatter::debug_struct_field2_finish(f, "S", - "d1", &&(*__self_0), "d2", &&(*__self_1)), + "d1", &&*__self_0, "d2", &&*__self_1), } } } @@ -759,13 +681,13 @@ impl ::core::hash::Hash for Mixed { (&Mixed::R(ref __self_0),) => { ::core::hash::Hash::hash(&::core::intrinsics::discriminant_value(self), state); - ::core::hash::Hash::hash(&(*__self_0), state) + ::core::hash::Hash::hash(&*__self_0, state) } (&Mixed::S { d1: ref __self_0, d2: ref __self_1 },) => { ::core::hash::Hash::hash(&::core::intrinsics::discriminant_value(self), state); - ::core::hash::Hash::hash(&(*__self_0), state); - ::core::hash::Hash::hash(&(*__self_1), state) + ::core::hash::Hash::hash(&*__self_0, state); + ::core::hash::Hash::hash(&*__self_1, state) } _ => { ::core::hash::Hash::hash(&::core::intrinsics::discriminant_value(self), @@ -786,10 +708,10 @@ impl ::core::cmp::PartialEq for Mixed { if __self_vi == __arg_1_vi { match (&*self, &*other) { (&Mixed::R(ref __self_0), &Mixed::R(ref __arg_1_0)) => - (*__self_0) == (*__arg_1_0), + *__self_0 == *__arg_1_0, (&Mixed::S { d1: ref __self_0, d2: ref __self_1 }, &Mixed::S { d1: ref __arg_1_0, d2: ref __arg_1_1 }) => - (*__self_0) == (*__arg_1_0) && (*__self_1) == (*__arg_1_1), + *__self_0 == *__arg_1_0 && *__self_1 == *__arg_1_1, _ => true, } } else { false } @@ -803,10 +725,10 @@ impl ::core::cmp::PartialEq for Mixed { if __self_vi == __arg_1_vi { match (&*self, &*other) { (&Mixed::R(ref __self_0), &Mixed::R(ref __arg_1_0)) => - (*__self_0) != (*__arg_1_0), + *__self_0 != *__arg_1_0, (&Mixed::S { d1: ref __self_0, d2: ref __self_1 }, &Mixed::S { d1: ref __arg_1_0, d2: ref __arg_1_1 }) => - (*__self_0) != (*__arg_1_0) || (*__self_1) != (*__arg_1_1), + *__self_0 != *__arg_1_0 || *__self_1 != *__arg_1_1, _ => false, } } else { true } @@ -840,8 +762,8 @@ impl ::core::cmp::PartialOrd for Mixed { if __self_vi == __arg_1_vi { match (&*self, &*other) { (&Mixed::R(ref __self_0), &Mixed::R(ref __arg_1_0)) => - match ::core::cmp::PartialOrd::partial_cmp(&(*__self_0), - &(*__arg_1_0)) { + match ::core::cmp::PartialOrd::partial_cmp(&*__self_0, + &*__arg_1_0) { ::core::option::Option::Some(::core::cmp::Ordering::Equal) => ::core::option::Option::Some(::core::cmp::Ordering::Equal), @@ -849,12 +771,12 @@ impl ::core::cmp::PartialOrd for Mixed { }, (&Mixed::S { d1: ref __self_0, d2: ref __self_1 }, &Mixed::S { d1: ref __arg_1_0, d2: ref __arg_1_1 }) => - match ::core::cmp::PartialOrd::partial_cmp(&(*__self_0), - &(*__arg_1_0)) { + match ::core::cmp::PartialOrd::partial_cmp(&*__self_0, + &*__arg_1_0) { ::core::option::Option::Some(::core::cmp::Ordering::Equal) => - match ::core::cmp::PartialOrd::partial_cmp(&(*__self_1), - &(*__arg_1_1)) { + match ::core::cmp::PartialOrd::partial_cmp(&*__self_1, + &*__arg_1_1) { ::core::option::Option::Some(::core::cmp::Ordering::Equal) => ::core::option::Option::Some(::core::cmp::Ordering::Equal), @@ -883,16 +805,16 @@ impl ::core::cmp::Ord for Mixed { if __self_vi == __arg_1_vi { match (&*self, &*other) { (&Mixed::R(ref __self_0), &Mixed::R(ref __arg_1_0)) => - match ::core::cmp::Ord::cmp(&(*__self_0), &(*__arg_1_0)) { + match ::core::cmp::Ord::cmp(&*__self_0, &*__arg_1_0) { ::core::cmp::Ordering::Equal => ::core::cmp::Ordering::Equal, cmp => cmp, }, (&Mixed::S { d1: ref __self_0, d2: ref __self_1 }, &Mixed::S { d1: ref __arg_1_0, d2: ref __arg_1_1 }) => - match ::core::cmp::Ord::cmp(&(*__self_0), &(*__arg_1_0)) { + match ::core::cmp::Ord::cmp(&*__self_0, &*__arg_1_0) { ::core::cmp::Ordering::Equal => - match ::core::cmp::Ord::cmp(&(*__self_1), &(*__arg_1_1)) { + match ::core::cmp::Ord::cmp(&*__self_1, &*__arg_1_1) { ::core::cmp::Ordering::Equal => ::core::cmp::Ordering::Equal, cmp => cmp, @@ -916,11 +838,11 @@ impl ::core::clone::Clone for Fielded { fn clone(&self) -> Fielded { match (&*self,) { (&Fielded::X(ref __self_0),) => - Fielded::X(::core::clone::Clone::clone(&(*__self_0))), + Fielded::X(::core::clone::Clone::clone(&*__self_0)), (&Fielded::Y(ref __self_0),) => - Fielded::Y(::core::clone::Clone::clone(&(*__self_0))), + Fielded::Y(::core::clone::Clone::clone(&*__self_0)), (&Fielded::Z(ref __self_0),) => - Fielded::Z(::core::clone::Clone::clone(&(*__self_0))), + Fielded::Z(::core::clone::Clone::clone(&*__self_0)), } } } @@ -931,13 +853,13 @@ impl ::core::fmt::Debug for Fielded { match (&*self,) { (&Fielded::X(ref __self_0),) => ::core::fmt::Formatter::debug_tuple_field1_finish(f, "X", - &&(*__self_0)), + &&*__self_0), (&Fielded::Y(ref __self_0),) => ::core::fmt::Formatter::debug_tuple_field1_finish(f, "Y", - &&(*__self_0)), + &&*__self_0), (&Fielded::Z(ref __self_0),) => ::core::fmt::Formatter::debug_tuple_field1_finish(f, "Z", - &&(*__self_0)), + &&*__self_0), } } } @@ -949,17 +871,17 @@ impl ::core::hash::Hash for Fielded { (&Fielded::X(ref __self_0),) => { ::core::hash::Hash::hash(&::core::intrinsics::discriminant_value(self), state); - ::core::hash::Hash::hash(&(*__self_0), state) + ::core::hash::Hash::hash(&*__self_0, state) } (&Fielded::Y(ref __self_0),) => { ::core::hash::Hash::hash(&::core::intrinsics::discriminant_value(self), state); - ::core::hash::Hash::hash(&(*__self_0), state) + ::core::hash::Hash::hash(&*__self_0, state) } (&Fielded::Z(ref __self_0),) => { ::core::hash::Hash::hash(&::core::intrinsics::discriminant_value(self), state); - ::core::hash::Hash::hash(&(*__self_0), state) + ::core::hash::Hash::hash(&*__self_0, state) } } } @@ -976,11 +898,11 @@ impl ::core::cmp::PartialEq for Fielded { if __self_vi == __arg_1_vi { match (&*self, &*other) { (&Fielded::X(ref __self_0), &Fielded::X(ref __arg_1_0)) => - (*__self_0) == (*__arg_1_0), + *__self_0 == *__arg_1_0, (&Fielded::Y(ref __self_0), &Fielded::Y(ref __arg_1_0)) => - (*__self_0) == (*__arg_1_0), + *__self_0 == *__arg_1_0, (&Fielded::Z(ref __self_0), &Fielded::Z(ref __arg_1_0)) => - (*__self_0) == (*__arg_1_0), + *__self_0 == *__arg_1_0, _ => unsafe { ::core::intrinsics::unreachable() } } } else { false } @@ -994,11 +916,11 @@ impl ::core::cmp::PartialEq for Fielded { if __self_vi == __arg_1_vi { match (&*self, &*other) { (&Fielded::X(ref __self_0), &Fielded::X(ref __arg_1_0)) => - (*__self_0) != (*__arg_1_0), + *__self_0 != *__arg_1_0, (&Fielded::Y(ref __self_0), &Fielded::Y(ref __arg_1_0)) => - (*__self_0) != (*__arg_1_0), + *__self_0 != *__arg_1_0, (&Fielded::Z(ref __self_0), &Fielded::Z(ref __arg_1_0)) => - (*__self_0) != (*__arg_1_0), + *__self_0 != *__arg_1_0, _ => unsafe { ::core::intrinsics::unreachable() } } } else { true } @@ -1032,24 +954,24 @@ impl ::core::cmp::PartialOrd for Fielded { if __self_vi == __arg_1_vi { match (&*self, &*other) { (&Fielded::X(ref __self_0), &Fielded::X(ref __arg_1_0)) => - match ::core::cmp::PartialOrd::partial_cmp(&(*__self_0), - &(*__arg_1_0)) { + match ::core::cmp::PartialOrd::partial_cmp(&*__self_0, + &*__arg_1_0) { ::core::option::Option::Some(::core::cmp::Ordering::Equal) => ::core::option::Option::Some(::core::cmp::Ordering::Equal), cmp => cmp, }, (&Fielded::Y(ref __self_0), &Fielded::Y(ref __arg_1_0)) => - match ::core::cmp::PartialOrd::partial_cmp(&(*__self_0), - &(*__arg_1_0)) { + match ::core::cmp::PartialOrd::partial_cmp(&*__self_0, + &*__arg_1_0) { ::core::option::Option::Some(::core::cmp::Ordering::Equal) => ::core::option::Option::Some(::core::cmp::Ordering::Equal), cmp => cmp, }, (&Fielded::Z(ref __self_0), &Fielded::Z(ref __arg_1_0)) => - match ::core::cmp::PartialOrd::partial_cmp(&(*__self_0), - &(*__arg_1_0)) { + match ::core::cmp::PartialOrd::partial_cmp(&*__self_0, + &*__arg_1_0) { ::core::option::Option::Some(::core::cmp::Ordering::Equal) => ::core::option::Option::Some(::core::cmp::Ordering::Equal), @@ -1075,19 +997,19 @@ impl ::core::cmp::Ord for Fielded { if __self_vi == __arg_1_vi { match (&*self, &*other) { (&Fielded::X(ref __self_0), &Fielded::X(ref __arg_1_0)) => - match ::core::cmp::Ord::cmp(&(*__self_0), &(*__arg_1_0)) { + match ::core::cmp::Ord::cmp(&*__self_0, &*__arg_1_0) { ::core::cmp::Ordering::Equal => ::core::cmp::Ordering::Equal, cmp => cmp, }, (&Fielded::Y(ref __self_0), &Fielded::Y(ref __arg_1_0)) => - match ::core::cmp::Ord::cmp(&(*__self_0), &(*__arg_1_0)) { + match ::core::cmp::Ord::cmp(&*__self_0, &*__arg_1_0) { ::core::cmp::Ordering::Equal => ::core::cmp::Ordering::Equal, cmp => cmp, }, (&Fielded::Z(ref __self_0), &Fielded::Z(ref __arg_1_0)) => - match ::core::cmp::Ord::cmp(&(*__self_0), &(*__arg_1_0)) { + match ::core::cmp::Ord::cmp(&*__self_0, &*__arg_1_0) { ::core::cmp::Ordering::Equal => ::core::cmp::Ordering::Equal, cmp => cmp, diff --git a/src/test/ui/destructuring-assignment/note-unsupported.stderr b/src/test/ui/destructuring-assignment/note-unsupported.stderr index 3e2282743bf..e45344aa51f 100644 --- a/src/test/ui/destructuring-assignment/note-unsupported.stderr +++ b/src/test/ui/destructuring-assignment/note-unsupported.stderr @@ -52,14 +52,8 @@ LL | struct S { x: u8, y: u8 } note: the following trait must be implemented --> $SRC_DIR/core/src/ops/arith.rs:LL:COL | -LL | / pub trait AddAssign<Rhs = Self> { -LL | | /// Performs the `+=` operation. -LL | | /// -LL | | /// # Example -... | -LL | | fn add_assign(&mut self, rhs: Rhs); -LL | | } - | |_^ +LL | pub trait AddAssign<Rhs = Self> { + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ error[E0067]: invalid left-hand side of assignment --> $DIR/note-unsupported.rs:17:22 diff --git a/src/test/ui/did_you_mean/compatible-variants-in-pat.stderr b/src/test/ui/did_you_mean/compatible-variants-in-pat.stderr index a4c77e08efe..473468af6ee 100644 --- a/src/test/ui/did_you_mean/compatible-variants-in-pat.stderr +++ b/src/test/ui/did_you_mean/compatible-variants-in-pat.stderr @@ -15,7 +15,7 @@ error[E0308]: mismatched types --> $DIR/compatible-variants-in-pat.rs:21:9 | LL | struct S; - | --------- unit struct defined here + | -------- unit struct defined here ... LL | match s { | - this expression has type `Option<S>` @@ -40,7 +40,7 @@ error[E0308]: mismatched types --> $DIR/compatible-variants-in-pat.rs:32:9 | LL | struct S; - | --------- unit struct defined here + | -------- unit struct defined here ... LL | match s { | - this expression has type `Result<S, S>` diff --git a/src/test/ui/dropck/dropck_no_diverge_on_nonregular_1.rs b/src/test/ui/dropck/dropck_no_diverge_on_nonregular_1.rs index 6ca5f5e3c5f..43c1c775978 100644 --- a/src/test/ui/dropck/dropck_no_diverge_on_nonregular_1.rs +++ b/src/test/ui/dropck/dropck_no_diverge_on_nonregular_1.rs @@ -23,5 +23,4 @@ enum FingerTree<T:'static> { fn main() { let ft = //~ ERROR overflow while adding drop-check rules for FingerTree FingerTree::Single(1); - //~^ ERROR overflow while adding drop-check rules for FingerTree } diff --git a/src/test/ui/dropck/dropck_no_diverge_on_nonregular_1.stderr b/src/test/ui/dropck/dropck_no_diverge_on_nonregular_1.stderr index 5df69e4649d..c447e2f7987 100644 --- a/src/test/ui/dropck/dropck_no_diverge_on_nonregular_1.stderr +++ b/src/test/ui/dropck/dropck_no_diverge_on_nonregular_1.stderr @@ -6,13 +6,5 @@ LL | let ft = | = note: overflowed on FingerTree<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<i32>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> -error[E0320]: overflow while adding drop-check rules for FingerTree<i32> - --> $DIR/dropck_no_diverge_on_nonregular_1.rs:25:9 - | -LL | FingerTree::Single(1); - | ^^^^^^^^^^^^^^^^^^^^^ - | - = note: overflowed on FingerTree<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<i32>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> - -error: aborting due to 2 previous errors +error: aborting due to previous error diff --git a/src/test/ui/dropck/dropck_no_diverge_on_nonregular_2.rs b/src/test/ui/dropck/dropck_no_diverge_on_nonregular_2.rs index d34f7e326d1..edd07652e53 100644 --- a/src/test/ui/dropck/dropck_no_diverge_on_nonregular_2.rs +++ b/src/test/ui/dropck/dropck_no_diverge_on_nonregular_2.rs @@ -22,5 +22,4 @@ enum FingerTree<T:'static> { fn main() { let ft = //~ ERROR overflow while adding drop-check rules for FingerTree FingerTree::Single(1); - //~^ ERROR overflow while adding drop-check rules for FingerTree } diff --git a/src/test/ui/dropck/dropck_no_diverge_on_nonregular_2.stderr b/src/test/ui/dropck/dropck_no_diverge_on_nonregular_2.stderr index d34097d4010..cd4706dd903 100644 --- a/src/test/ui/dropck/dropck_no_diverge_on_nonregular_2.stderr +++ b/src/test/ui/dropck/dropck_no_diverge_on_nonregular_2.stderr @@ -6,13 +6,5 @@ LL | let ft = | = note: overflowed on FingerTree<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<i32>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> -error[E0320]: overflow while adding drop-check rules for FingerTree<i32> - --> $DIR/dropck_no_diverge_on_nonregular_2.rs:24:9 - | -LL | FingerTree::Single(1); - | ^^^^^^^^^^^^^^^^^^^^^ - | - = note: overflowed on FingerTree<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<i32>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> - -error: aborting due to 2 previous errors +error: aborting due to previous error diff --git a/src/test/ui/dropck/dropck_no_diverge_on_nonregular_3.rs b/src/test/ui/dropck/dropck_no_diverge_on_nonregular_3.rs index 558b4342da7..af7402ca4a1 100644 --- a/src/test/ui/dropck/dropck_no_diverge_on_nonregular_3.rs +++ b/src/test/ui/dropck/dropck_no_diverge_on_nonregular_3.rs @@ -31,6 +31,5 @@ enum Wrapper<T:'static> { fn main() { let w = //~ ERROR overflow while adding drop-check rules for Option Some(Wrapper::Simple::<u32>); - //~^ ERROR overflow while adding drop-check rules for Option - //~| ERROR overflow while adding drop-check rules for Wrapper + //~^ ERROR overflow while adding drop-check rules for Wrapper } diff --git a/src/test/ui/dropck/dropck_no_diverge_on_nonregular_3.stderr b/src/test/ui/dropck/dropck_no_diverge_on_nonregular_3.stderr index b24e1d1bf79..18cd1b6cd41 100644 --- a/src/test/ui/dropck/dropck_no_diverge_on_nonregular_3.stderr +++ b/src/test/ui/dropck/dropck_no_diverge_on_nonregular_3.stderr @@ -6,14 +6,6 @@ LL | let w = | = note: overflowed on FingerTree<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<u32>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> -error[E0320]: overflow while adding drop-check rules for Option<Wrapper<u32>> - --> $DIR/dropck_no_diverge_on_nonregular_3.rs:33:9 - | -LL | Some(Wrapper::Simple::<u32>); - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ - | - = note: overflowed on FingerTree<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<u32>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> - error[E0320]: overflow while adding drop-check rules for Wrapper<u32> --> $DIR/dropck_no_diverge_on_nonregular_3.rs:33:14 | @@ -22,5 +14,5 @@ LL | Some(Wrapper::Simple::<u32>); | = note: overflowed on FingerTree<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<u32>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> -error: aborting due to 3 previous errors +error: aborting due to 2 previous errors diff --git a/src/test/ui/dropck/issue-38868.stderr b/src/test/ui/dropck/issue-38868.stderr index f267abc0bfa..ec81c2ea646 100644 --- a/src/test/ui/dropck/issue-38868.stderr +++ b/src/test/ui/dropck/issue-38868.stderr @@ -1,21 +1,15 @@ error[E0366]: `Drop` impls cannot be specialized --> $DIR/issue-38868.rs:5:1 | -LL | / impl Drop for List<i32> { -LL | | fn drop(&mut self) { -LL | | panic!() -LL | | } -LL | | } - | |_^ +LL | impl Drop for List<i32> { + | ^^^^^^^^^^^^^^^^^^^^^^^ | = note: `i32` is not a generic parameter note: use the same sequence of generic lifetime, type and const parameters as the struct definition --> $DIR/issue-38868.rs:1:1 | -LL | / pub struct List<T> { -LL | | head: T, -LL | | } - | |_^ +LL | pub struct List<T> { + | ^^^^^^^^^^^^^^^^^^ error: aborting due to previous error diff --git a/src/test/ui/dropck/reject-specialized-drops-8142.stderr b/src/test/ui/dropck/reject-specialized-drops-8142.stderr index 7f50cf5ab15..ebd484b8800 100644 --- a/src/test/ui/dropck/reject-specialized-drops-8142.stderr +++ b/src/test/ui/dropck/reject-specialized-drops-8142.stderr @@ -8,7 +8,7 @@ note: the implementor must specify the same requirement --> $DIR/reject-specialized-drops-8142.rs:4:1 | LL | struct K<'l1,'l2> { x: &'l1 i8, y: &'l2 u8 } - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | ^^^^^^^^^^^^^^^^^ error[E0367]: `Drop` impl requires `'adds_bnd: 'al` but the struct it is implemented for does not --> $DIR/reject-specialized-drops-8142.rs:28:67 @@ -20,33 +20,33 @@ note: the implementor must specify the same requirement --> $DIR/reject-specialized-drops-8142.rs:5:1 | LL | struct L<'l1,'l2> { x: &'l1 i8, y: &'l2 u8 } - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | ^^^^^^^^^^^^^^^^^ error[E0366]: `Drop` impls cannot be specialized --> $DIR/reject-specialized-drops-8142.rs:34:1 | LL | impl Drop for N<'static> { fn drop(&mut self) { } } // REJECT - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ | = note: `'static` is not a generic parameter note: use the same sequence of generic lifetime, type and const parameters as the struct definition --> $DIR/reject-specialized-drops-8142.rs:7:1 | LL | struct N<'n> { x: &'n i8 } - | ^^^^^^^^^^^^^^^^^^^^^^^^^^ + | ^^^^^^^^^^^^ error[E0366]: `Drop` impls cannot be specialized --> $DIR/reject-specialized-drops-8142.rs:39:1 | LL | impl Drop for P<i8> { fn drop(&mut self) { } } // REJECT - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ | = note: `i8` is not a generic parameter note: use the same sequence of generic lifetime, type and const parameters as the struct definition --> $DIR/reject-specialized-drops-8142.rs:9:1 | LL | struct P<Tp> { x: *const Tp } - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | ^^^^^^^^^^^^ error[E0367]: `Drop` impl requires `AddsBnd: Bound` but the struct it is implemented for does not --> $DIR/reject-specialized-drops-8142.rs:42:14 @@ -58,7 +58,7 @@ note: the implementor must specify the same requirement --> $DIR/reject-specialized-drops-8142.rs:10:1 | LL | struct Q<Tq> { x: *const Tq } - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | ^^^^^^^^^^^^ error[E0367]: `Drop` impl requires `AddsRBnd: 'rbnd` but the struct it is implemented for does not --> $DIR/reject-specialized-drops-8142.rs:45:21 @@ -70,59 +70,59 @@ note: the implementor must specify the same requirement --> $DIR/reject-specialized-drops-8142.rs:11:1 | LL | struct R<Tr> { x: *const Tr } - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | ^^^^^^^^^^^^ error[E0366]: `Drop` impls cannot be specialized --> $DIR/reject-specialized-drops-8142.rs:54:1 | LL | impl<One> Drop for V<One,One> { fn drop(&mut self) { } } // REJECT - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ | = note: `One` is mentioned multiple times note: use the same sequence of generic lifetime, type and const parameters as the struct definition --> $DIR/reject-specialized-drops-8142.rs:15:1 | LL | struct V<Tva, Tvb> { x: *const Tva, y: *const Tvb } - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | ^^^^^^^^^^^^^^^^^^ error[E0366]: `Drop` impls cannot be specialized --> $DIR/reject-specialized-drops-8142.rs:57:1 | LL | impl<'lw> Drop for W<'lw,'lw> { fn drop(&mut self) { } } // REJECT - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ | = note: `'lw` is mentioned multiple times note: use the same sequence of generic lifetime, type and const parameters as the struct definition --> $DIR/reject-specialized-drops-8142.rs:16:1 | LL | struct W<'l1, 'l2> { x: &'l1 i8, y: &'l2 u8 } - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | ^^^^^^^^^^^^^^^^^^ error[E0366]: `Drop` impls cannot be specialized --> $DIR/reject-specialized-drops-8142.rs:60:1 | LL | impl Drop for X<3> { fn drop(&mut self) { } } // REJECT - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ | = note: `3_usize` is not a generic parameter note: use the same sequence of generic lifetime, type and const parameters as the struct definition --> $DIR/reject-specialized-drops-8142.rs:17:1 | LL | struct X<const Ca: usize>; - | ^^^^^^^^^^^^^^^^^^^^^^^^^^ + | ^^^^^^^^^^^^^^^^^^^^^^^^^ error[E0366]: `Drop` impls cannot be specialized --> $DIR/reject-specialized-drops-8142.rs:63:1 | LL | impl<const Ca: usize> Drop for Y<Ca, Ca> { fn drop(&mut self) { } } // REJECT - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ | = note: `Ca` is mentioned multiple times note: use the same sequence of generic lifetime, type and const parameters as the struct definition --> $DIR/reject-specialized-drops-8142.rs:18:1 | LL | struct Y<const Ca: usize, const Cb: usize>; - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ error[E0367]: `Drop` impl requires `AddsBnd: Bound` but the enum it is implemented for does not --> $DIR/reject-specialized-drops-8142.rs:66:14 @@ -134,7 +134,7 @@ note: the implementor must specify the same requirement --> $DIR/reject-specialized-drops-8142.rs:20:1 | LL | enum Enum<T> { Variant(T) } - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | ^^^^^^^^^^^^ error[E0367]: `Drop` impl requires `AddsBnd: Bound` but the struct it is implemented for does not --> $DIR/reject-specialized-drops-8142.rs:69:14 @@ -146,7 +146,7 @@ note: the implementor must specify the same requirement --> $DIR/reject-specialized-drops-8142.rs:21:1 | LL | struct TupleStruct<T>(T); - | ^^^^^^^^^^^^^^^^^^^^^^^^^ + | ^^^^^^^^^^^^^^^^^^^^^ error[E0367]: `Drop` impl requires `AddsBnd: Bound` but the union it is implemented for does not --> $DIR/reject-specialized-drops-8142.rs:72:21 @@ -158,7 +158,7 @@ note: the implementor must specify the same requirement --> $DIR/reject-specialized-drops-8142.rs:22:1 | LL | union Union<T: Copy> { f: T } - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | ^^^^^^^^^^^^^^^^^^^^ error: aborting due to 13 previous errors diff --git a/src/test/ui/dropck/relate_lt_in_type_outlives_bound.stderr b/src/test/ui/dropck/relate_lt_in_type_outlives_bound.stderr index 5176684e153..3d9685db683 100644 --- a/src/test/ui/dropck/relate_lt_in_type_outlives_bound.stderr +++ b/src/test/ui/dropck/relate_lt_in_type_outlives_bound.stderr @@ -7,10 +7,8 @@ LL | T: 'static, note: the implementor must specify the same requirement --> $DIR/relate_lt_in_type_outlives_bound.rs:1:1 | -LL | / struct Wrapper<'a, T>(&'a T) -LL | | where -LL | | T: 'a; - | |__________^ +LL | struct Wrapper<'a, T>(&'a T) + | ^^^^^^^^^^^^^^^^^^^^^ error: aborting due to previous error diff --git a/src/test/ui/duplicate/dupe-symbols-6.stderr b/src/test/ui/duplicate/dupe-symbols-6.stderr index 8d5b7fb35bf..6692a63dce8 100644 --- a/src/test/ui/duplicate/dupe-symbols-6.stderr +++ b/src/test/ui/duplicate/dupe-symbols-6.stderr @@ -2,7 +2,7 @@ error: symbol `fail` is already defined --> $DIR/dupe-symbols-6.rs:10:1 | LL | static HELLO_TWICE: u16 = 0; - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | ^^^^^^^^^^^^^^^^^^^^^^^ error: aborting due to previous error diff --git a/src/test/ui/empty/empty-struct-braces-expr.stderr b/src/test/ui/empty/empty-struct-braces-expr.stderr index 48e5ea8ec86..5fc0a916a09 100644 --- a/src/test/ui/empty/empty-struct-braces-expr.stderr +++ b/src/test/ui/empty/empty-struct-braces-expr.stderr @@ -10,7 +10,7 @@ LL | let e1 = Empty1; ::: $DIR/auxiliary/empty-struct.rs:2:1 | LL | pub struct XEmpty2; - | ------------------- similarly named unit struct `XEmpty2` defined here + | ------------------ similarly named unit struct `XEmpty2` defined here | help: use struct literal syntax instead | @@ -33,7 +33,7 @@ LL | let e1 = Empty1(); ::: $DIR/auxiliary/empty-struct.rs:2:1 | LL | pub struct XEmpty2; - | ------------------- similarly named unit struct `XEmpty2` defined here + | ------------------ similarly named unit struct `XEmpty2` defined here | help: use struct literal syntax instead | @@ -73,7 +73,7 @@ LL | let xe1 = XEmpty1; LL | pub struct XEmpty1 {} | ------------------ `XEmpty1` defined here LL | pub struct XEmpty2; - | ------------------- similarly named unit struct `XEmpty2` defined here + | ------------------ similarly named unit struct `XEmpty2` defined here | help: use struct literal syntax instead | @@ -95,7 +95,7 @@ LL | let xe1 = XEmpty1(); LL | pub struct XEmpty1 {} | ------------------ `XEmpty1` defined here LL | pub struct XEmpty2; - | ------------------- similarly named unit struct `XEmpty2` defined here + | ------------------ similarly named unit struct `XEmpty2` defined here | help: use struct literal syntax instead | diff --git a/src/test/ui/empty/empty-struct-braces-pat-2.stderr b/src/test/ui/empty/empty-struct-braces-pat-2.stderr index 28191615afd..7fb5cb2034a 100644 --- a/src/test/ui/empty/empty-struct-braces-pat-2.stderr +++ b/src/test/ui/empty/empty-struct-braces-pat-2.stderr @@ -10,7 +10,7 @@ LL | Empty1() => () ::: $DIR/auxiliary/empty-struct.rs:3:1 | LL | pub struct XEmpty6(); - | --------------------- similarly named tuple struct `XEmpty6` defined here + | ------------------ similarly named tuple struct `XEmpty6` defined here | help: use struct pattern syntax instead | @@ -33,7 +33,7 @@ LL | pub struct XEmpty1 {} | ------------------ `XEmpty1` defined here LL | pub struct XEmpty2; LL | pub struct XEmpty6(); - | --------------------- similarly named tuple struct `XEmpty6` defined here + | ------------------ similarly named tuple struct `XEmpty6` defined here | help: use struct pattern syntax instead | @@ -56,7 +56,7 @@ LL | Empty1(..) => () ::: $DIR/auxiliary/empty-struct.rs:3:1 | LL | pub struct XEmpty6(); - | --------------------- similarly named tuple struct `XEmpty6` defined here + | ------------------ similarly named tuple struct `XEmpty6` defined here | help: use struct pattern syntax instead | @@ -79,7 +79,7 @@ LL | pub struct XEmpty1 {} | ------------------ `XEmpty1` defined here LL | pub struct XEmpty2; LL | pub struct XEmpty6(); - | --------------------- similarly named tuple struct `XEmpty6` defined here + | ------------------ similarly named tuple struct `XEmpty6` defined here | help: use struct pattern syntax instead | diff --git a/src/test/ui/empty/empty-struct-unit-expr.stderr b/src/test/ui/empty/empty-struct-unit-expr.stderr index c15253ba9cd..cd51274dce8 100644 --- a/src/test/ui/empty/empty-struct-unit-expr.stderr +++ b/src/test/ui/empty/empty-struct-unit-expr.stderr @@ -2,7 +2,7 @@ error[E0618]: expected function, found `Empty2` --> $DIR/empty-struct-unit-expr.rs:15:14 | LL | struct Empty2; - | -------------- `Empty2` defined here + | ------------- `Empty2` defined here ... LL | let e2 = Empty2(); | ^^^^^^-- diff --git a/src/test/ui/empty/empty-struct-unit-pat.stderr b/src/test/ui/empty/empty-struct-unit-pat.stderr index b1b253385fd..acd1070d5d6 100644 --- a/src/test/ui/empty/empty-struct-unit-pat.stderr +++ b/src/test/ui/empty/empty-struct-unit-pat.stderr @@ -10,7 +10,7 @@ LL | Empty2() => () ::: $DIR/auxiliary/empty-struct.rs:3:1 | LL | pub struct XEmpty6(); - | --------------------- similarly named tuple struct `XEmpty6` defined here + | ------------------ similarly named tuple struct `XEmpty6` defined here | help: use this syntax instead | @@ -30,9 +30,9 @@ LL | XEmpty2() => () ::: $DIR/auxiliary/empty-struct.rs:2:1 | LL | pub struct XEmpty2; - | ------------------- `XEmpty2` defined here + | ------------------ `XEmpty2` defined here LL | pub struct XEmpty6(); - | --------------------- similarly named tuple struct `XEmpty6` defined here + | ------------------ similarly named tuple struct `XEmpty6` defined here | help: use this syntax instead | @@ -55,7 +55,7 @@ LL | Empty2(..) => () ::: $DIR/auxiliary/empty-struct.rs:3:1 | LL | pub struct XEmpty6(); - | --------------------- similarly named tuple struct `XEmpty6` defined here + | ------------------ similarly named tuple struct `XEmpty6` defined here | help: use this syntax instead | @@ -75,9 +75,9 @@ LL | XEmpty2(..) => () ::: $DIR/auxiliary/empty-struct.rs:2:1 | LL | pub struct XEmpty2; - | ------------------- `XEmpty2` defined here + | ------------------ `XEmpty2` defined here LL | pub struct XEmpty6(); - | --------------------- similarly named tuple struct `XEmpty6` defined here + | ------------------ similarly named tuple struct `XEmpty6` defined here | help: use this syntax instead | diff --git a/src/test/ui/enum/suggest-default-attribute.rs b/src/test/ui/enum/suggest-default-attribute.rs new file mode 100644 index 00000000000..33bd0d24081 --- /dev/null +++ b/src/test/ui/enum/suggest-default-attribute.rs @@ -0,0 +1,8 @@ +pub enum Test { //~ HELP consider adding `#[derive(Default)]` to this enum + #[default] + //~^ ERROR cannot find attribute `default` in this scope + First, + Second, +} + +fn main() {} diff --git a/src/test/ui/enum/suggest-default-attribute.stderr b/src/test/ui/enum/suggest-default-attribute.stderr new file mode 100644 index 00000000000..791f219e8f9 --- /dev/null +++ b/src/test/ui/enum/suggest-default-attribute.stderr @@ -0,0 +1,14 @@ +error: cannot find attribute `default` in this scope + --> $DIR/suggest-default-attribute.rs:2:7 + | +LL | #[default] + | ^^^^^^^ + | +help: consider adding `#[derive(Default)]` to this enum + --> $DIR/suggest-default-attribute.rs:1:1 + | +LL | pub enum Test { + | ^^^^^^^^^^^^^ + +error: aborting due to previous error + diff --git a/src/test/ui/error-codes/E0004-2.stderr b/src/test/ui/error-codes/E0004-2.stderr index d4519af5408..6f5bb4309c3 100644 --- a/src/test/ui/error-codes/E0004-2.stderr +++ b/src/test/ui/error-codes/E0004-2.stderr @@ -7,17 +7,14 @@ LL | match x { } note: `Option<i32>` defined here --> $SRC_DIR/core/src/option.rs:LL:COL | -LL | / pub enum Option<T> { -LL | | /// No value. -LL | | #[lang = "None"] -LL | | #[stable(feature = "rust1", since = "1.0.0")] -LL | | None, - | | ^^^^ not covered -... | -LL | | Some(#[stable(feature = "rust1", since = "1.0.0")] T), - | | ^^^^ not covered -LL | | } - | |_- +LL | pub enum Option<T> { + | ------------------ +... +LL | None, + | ^^^^ not covered +... +LL | Some(#[stable(feature = "rust1", since = "1.0.0")] T), + | ^^^^ not covered = note: the matched value is of type `Option<i32>` help: ensure that all possible cases are being handled by adding a match arm with a wildcard pattern, a match arm with multiple or-patterns as shown, or multiple match arms | diff --git a/src/test/ui/error-codes/E0005.stderr b/src/test/ui/error-codes/E0005.stderr index 55b1112b5f8..f01a77bd374 100644 --- a/src/test/ui/error-codes/E0005.stderr +++ b/src/test/ui/error-codes/E0005.stderr @@ -9,16 +9,11 @@ LL | let Some(y) = x; note: `Option<i32>` defined here --> $SRC_DIR/core/src/option.rs:LL:COL | -LL | / pub enum Option<T> { -LL | | /// No value. -LL | | #[lang = "None"] -LL | | #[stable(feature = "rust1", since = "1.0.0")] -LL | | None, - | | ^^^^ not covered -... | -LL | | Some(#[stable(feature = "rust1", since = "1.0.0")] T), -LL | | } - | |_- +LL | pub enum Option<T> { + | ------------------ +... +LL | None, + | ^^^^ not covered = note: the matched value is of type `Option<i32>` help: you might want to use `if let` to ignore the variant that isn't matched | diff --git a/src/test/ui/error-codes/E0017.stderr b/src/test/ui/error-codes/E0017.stderr index 7d959b6d148..830e4db345a 100644 --- a/src/test/ui/error-codes/E0017.stderr +++ b/src/test/ui/error-codes/E0017.stderr @@ -11,7 +11,7 @@ note: `const` item defined here --> $DIR/E0017.rs:2:1 | LL | const C: i32 = 2; - | ^^^^^^^^^^^^^^^^^ + | ^^^^^^^^^^^^ error[E0764]: mutable references are not allowed in the final value of constants --> $DIR/E0017.rs:5:30 @@ -52,7 +52,7 @@ note: `const` item defined here --> $DIR/E0017.rs:2:1 | LL | const C: i32 = 2; - | ^^^^^^^^^^^^^^^^^ + | ^^^^^^^^^^^^ error[E0764]: mutable references are not allowed in the final value of statics --> $DIR/E0017.rs:11:38 diff --git a/src/test/ui/error-codes/E0075.stderr b/src/test/ui/error-codes/E0075.stderr index d8b90d0691d..3f927726a03 100644 --- a/src/test/ui/error-codes/E0075.stderr +++ b/src/test/ui/error-codes/E0075.stderr @@ -2,7 +2,7 @@ error[E0075]: SIMD vector cannot be empty --> $DIR/E0075.rs:4:1 | LL | struct Bad; - | ^^^^^^^^^^^ + | ^^^^^^^^^^ error: aborting due to previous error diff --git a/src/test/ui/error-codes/E0076.stderr b/src/test/ui/error-codes/E0076.stderr index 2c2842d152b..7d4ff879816 100644 --- a/src/test/ui/error-codes/E0076.stderr +++ b/src/test/ui/error-codes/E0076.stderr @@ -2,7 +2,7 @@ error[E0076]: SIMD vector should be homogeneous --> $DIR/E0076.rs:4:1 | LL | struct Bad(u16, u32, u32); - | ^^^^^^^^^^^^^^^^^^^^^^^^^^ SIMD elements must have the same type + | ^^^^^^^^^^ SIMD elements must have the same type error: aborting due to previous error diff --git a/src/test/ui/error-codes/E0077.stderr b/src/test/ui/error-codes/E0077.stderr index 1938a9a272a..9a84b2ec406 100644 --- a/src/test/ui/error-codes/E0077.stderr +++ b/src/test/ui/error-codes/E0077.stderr @@ -2,7 +2,7 @@ error[E0077]: SIMD vector element type should be a primitive scalar (integer/flo --> $DIR/E0077.rs:4:1 | LL | struct Bad(String); - | ^^^^^^^^^^^^^^^^^^^ + | ^^^^^^^^^^ error: aborting due to previous error diff --git a/src/test/ui/error-codes/E0152.stderr b/src/test/ui/error-codes/E0152.stderr index 5cdfe1cc556..29f7e4ad683 100644 --- a/src/test/ui/error-codes/E0152.stderr +++ b/src/test/ui/error-codes/E0152.stderr @@ -2,7 +2,7 @@ error[E0152]: found duplicate lang item `owned_box` --> $DIR/E0152.rs:5:1 | LL | struct Foo<T>(T); - | ^^^^^^^^^^^^^^^^^ + | ^^^^^^^^^^^^^ | = note: the lang item is first defined in crate `alloc` (which `std` depends on) = note: first definition in `alloc` loaded from SYSROOT/liballoc-*.rlib diff --git a/src/test/ui/error-codes/E0191.stderr b/src/test/ui/error-codes/E0191.stderr index d69a14916e1..cf80c9c46ca 100644 --- a/src/test/ui/error-codes/E0191.stderr +++ b/src/test/ui/error-codes/E0191.stderr @@ -2,7 +2,7 @@ error[E0191]: the value of the associated type `Bar` (from trait `Trait`) must b --> $DIR/E0191.rs:5:16 | LL | type Bar; - | --------- `Bar` defined here + | -------- `Bar` defined here ... LL | type Foo = dyn Trait; | ^^^^^ help: specify the associated type: `Trait<Bar = Type>` diff --git a/src/test/ui/error-codes/E0201.stderr b/src/test/ui/error-codes/E0201.stderr index af029603fa1..94e06894144 100644 --- a/src/test/ui/error-codes/E0201.stderr +++ b/src/test/ui/error-codes/E0201.stderr @@ -18,10 +18,10 @@ error[E0201]: duplicate definitions with name `Quux`: --> $DIR/E0201.rs:18:5 | LL | type Quux = u32; - | ---------------- previous definition of `Quux` here + | --------- previous definition of `Quux` here ... LL | type Quux = u32; - | ^^^^^^^^^^^^^^^^ duplicate definition + | ^^^^^^^^^ duplicate definition error: aborting due to 3 previous errors diff --git a/src/test/ui/error-codes/E0220.stderr b/src/test/ui/error-codes/E0220.stderr index 4fa83d8bf6e..11763ce788d 100644 --- a/src/test/ui/error-codes/E0220.stderr +++ b/src/test/ui/error-codes/E0220.stderr @@ -8,7 +8,7 @@ error[E0191]: the value of the associated type `Bar` (from trait `Trait`) must b --> $DIR/E0220.rs:5:16 | LL | type Bar; - | --------- `Bar` defined here + | -------- `Bar` defined here ... LL | type Foo = dyn Trait<F=i32>; | ^^^^^^^^^^^^ help: specify the associated type: `Trait<F=i32, Bar = Type>` diff --git a/src/test/ui/error-codes/E0221.stderr b/src/test/ui/error-codes/E0221.stderr index f3dbf122de3..5414d77ad7c 100644 --- a/src/test/ui/error-codes/E0221.stderr +++ b/src/test/ui/error-codes/E0221.stderr @@ -2,10 +2,10 @@ error[E0221]: ambiguous associated type `A` in bounds of `Self` --> $DIR/E0221.rs:11:16 | LL | type A: T1; - | ----------- ambiguous `A` from `Foo` + | ---------- ambiguous `A` from `Foo` ... LL | type A: T2; - | ----------- ambiguous `A` from `Bar` + | ---------- ambiguous `A` from `Bar` LL | fn do_something() { LL | let _: Self::A; | ^^^^^^^ ambiguous associated type `A` @@ -23,7 +23,7 @@ error[E0221]: ambiguous associated type `Err` in bounds of `Self` --> $DIR/E0221.rs:21:16 | LL | type Err: T3; - | ------------- ambiguous `Err` from `My` + | ------------ ambiguous `Err` from `My` LL | fn test() { LL | let _: Self::Err; | ^^^^^^^^^ ambiguous associated type `Err` diff --git a/src/test/ui/error-codes/E0264.stderr b/src/test/ui/error-codes/E0264.stderr index 403c0aa4146..e8e35a12cbb 100644 --- a/src/test/ui/error-codes/E0264.stderr +++ b/src/test/ui/error-codes/E0264.stderr @@ -2,7 +2,7 @@ error[E0264]: unknown external lang item: `cake` --> $DIR/E0264.rs:5:5 | LL | fn cake(); - | ^^^^^^^^^^ + | ^^^^^^^^^ error: aborting due to previous error diff --git a/src/test/ui/error-codes/E0297.stderr b/src/test/ui/error-codes/E0297.stderr index 95d95003c61..693b079238d 100644 --- a/src/test/ui/error-codes/E0297.stderr +++ b/src/test/ui/error-codes/E0297.stderr @@ -7,16 +7,11 @@ LL | for Some(x) in xs {} note: `Option<i32>` defined here --> $SRC_DIR/core/src/option.rs:LL:COL | -LL | / pub enum Option<T> { -LL | | /// No value. -LL | | #[lang = "None"] -LL | | #[stable(feature = "rust1", since = "1.0.0")] -LL | | None, - | | ^^^^ not covered -... | -LL | | Some(#[stable(feature = "rust1", since = "1.0.0")] T), -LL | | } - | |_- +LL | pub enum Option<T> { + | ------------------ +... +LL | None, + | ^^^^ not covered = note: the matched value is of type `Option<i32>` error: aborting due to previous error diff --git a/src/test/ui/error-codes/E0374.stderr b/src/test/ui/error-codes/E0374.stderr index 7ab0f82fc23..68e15e6f8fe 100644 --- a/src/test/ui/error-codes/E0374.stderr +++ b/src/test/ui/error-codes/E0374.stderr @@ -1,9 +1,8 @@ error[E0374]: the trait `CoerceUnsized` may only be implemented for a coercion between structures with one field being coerced, none found --> $DIR/E0374.rs:8:1 | -LL | / impl<T, U> CoerceUnsized<Foo<U>> for Foo<T> -LL | | where T: CoerceUnsized<U> {} - | |________________________________^ +LL | impl<T, U> CoerceUnsized<Foo<U>> for Foo<T> + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ error: aborting due to previous error diff --git a/src/test/ui/error-codes/E0376.stderr b/src/test/ui/error-codes/E0376.stderr index 015448c39ea..e91efb045c1 100644 --- a/src/test/ui/error-codes/E0376.stderr +++ b/src/test/ui/error-codes/E0376.stderr @@ -2,7 +2,7 @@ error[E0376]: the trait `CoerceUnsized` may only be implemented for a coercion b --> $DIR/E0376.rs:8:1 | LL | impl<T, U> CoerceUnsized<U> for Foo<T> {} - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ error: aborting due to previous error diff --git a/src/test/ui/error-codes/E0388.stderr b/src/test/ui/error-codes/E0388.stderr index 4886a156d2e..106efc19ac9 100644 --- a/src/test/ui/error-codes/E0388.stderr +++ b/src/test/ui/error-codes/E0388.stderr @@ -11,7 +11,7 @@ note: `const` item defined here --> $DIR/E0388.rs:2:1 | LL | const C: i32 = 2; - | ^^^^^^^^^^^^^^^^^ + | ^^^^^^^^^^^^ error[E0764]: mutable references are not allowed in the final value of constants --> $DIR/E0388.rs:4:30 @@ -52,7 +52,7 @@ note: `const` item defined here --> $DIR/E0388.rs:2:1 | LL | const C: i32 = 2; - | ^^^^^^^^^^^^^^^^^ + | ^^^^^^^^^^^^ error[E0764]: mutable references are not allowed in the final value of statics --> $DIR/E0388.rs:10:38 diff --git a/src/test/ui/error-codes/E0393.stderr b/src/test/ui/error-codes/E0393.stderr index 8aadf5c8b47..d9f70b72930 100644 --- a/src/test/ui/error-codes/E0393.stderr +++ b/src/test/ui/error-codes/E0393.stderr @@ -2,7 +2,7 @@ error[E0393]: the type parameter `T` must be explicitly specified --> $DIR/E0393.rs:3:47 | LL | trait A<T=Self> {} - | ------------------ type parameter `T` must be specified for this + | --------------- type parameter `T` must be specified for this LL | LL | fn together_we_will_rule_the_galaxy(son: &dyn A) {} | ^ help: set the type parameter to the desired type: `A<T>` diff --git a/src/test/ui/error-codes/E0396-fixed.stderr b/src/test/ui/error-codes/E0396-fixed.stderr index 3eb291f0f70..2efbd6989ad 100644 --- a/src/test/ui/error-codes/E0396-fixed.stderr +++ b/src/test/ui/error-codes/E0396-fixed.stderr @@ -2,7 +2,7 @@ error[E0080]: evaluation of constant value failed --> $DIR/E0396-fixed.rs:5:28 | LL | const VALUE: u8 = unsafe { *REG_ADDR }; - | ^^^^^^^^^ dereferencing pointer failed: 0x5f3759df is not a valid pointer + | ^^^^^^^^^ dereferencing pointer failed: 0x5f3759df[noalloc] is a dangling pointer (it has no provenance) error: aborting due to previous error diff --git a/src/test/ui/error-codes/E0445.stderr b/src/test/ui/error-codes/E0445.stderr index 1a66e0a2f97..23b7a335047 100644 --- a/src/test/ui/error-codes/E0445.stderr +++ b/src/test/ui/error-codes/E0445.stderr @@ -5,7 +5,7 @@ LL | trait Foo { | --------- `Foo` declared as private ... LL | pub trait Bar : Foo {} - | ^^^^^^^^^^^^^^^^^^^^^^ can't leak private trait + | ^^^^^^^^^^^^^^^^^^^ can't leak private trait error[E0445]: private trait `Foo` in public interface --> $DIR/E0445.rs:7:1 @@ -14,7 +14,7 @@ LL | trait Foo { | --------- `Foo` declared as private ... LL | pub struct Bar2<T: Foo>(pub T); - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ can't leak private trait + | ^^^^^^^^^^^^^^^^^^^^^^^ can't leak private trait error[E0445]: private trait `Foo` in public interface --> $DIR/E0445.rs:9:1 diff --git a/src/test/ui/error-codes/E0446.stderr b/src/test/ui/error-codes/E0446.stderr index 35e79e448d5..b6a195c40a9 100644 --- a/src/test/ui/error-codes/E0446.stderr +++ b/src/test/ui/error-codes/E0446.stderr @@ -2,7 +2,7 @@ error[E0446]: private type `Bar` in public interface --> $DIR/E0446.rs:4:5 | LL | struct Bar(u32); - | ---------------- `Bar` declared as private + | ---------- `Bar` declared as private LL | LL | pub fn bar() -> Bar { | ^^^^^^^^^^^^^^^^^^^ can't leak private type diff --git a/src/test/ui/error-codes/E0520.stderr b/src/test/ui/error-codes/E0520.stderr index be7b95465a5..65ebfcdbe32 100644 --- a/src/test/ui/error-codes/E0520.stderr +++ b/src/test/ui/error-codes/E0520.stderr @@ -11,13 +11,11 @@ LL | #![feature(specialization)] error[E0520]: `fly` specializes an item from a parent `impl`, but that item is not marked `default` --> $DIR/E0520.rs:17:5 | -LL | / impl<T: Clone> SpaceLlama for T { -LL | | fn fly(&self) {} -LL | | } - | |_- parent `impl` is here +LL | impl<T: Clone> SpaceLlama for T { + | ------------------------------- parent `impl` is here ... -LL | default fn fly(&self) {} - | ^^^^^^^^^^^^^^^^^^^^^^^^ cannot specialize default item `fly` +LL | default fn fly(&self) {} + | ^^^^^^^^^^^^^^^^^^^^^^^^ cannot specialize default item `fly` | = note: to specialize, `fly` in the parent `impl` must be marked `default` diff --git a/src/test/ui/error-festival.stderr b/src/test/ui/error-festival.stderr index 81aa268cacc..43122c13efb 100644 --- a/src/test/ui/error-festival.stderr +++ b/src/test/ui/error-festival.stderr @@ -44,14 +44,8 @@ LL | enum Question { note: the following trait must be implemented --> $SRC_DIR/core/src/ops/bit.rs:LL:COL | -LL | / pub trait Not { -LL | | /// The resulting type after applying the `!` operator. -LL | | #[stable(feature = "rust1", since = "1.0.0")] -LL | | type Output; -... | -LL | | fn not(self) -> Self::Output; -LL | | } - | |_^ +LL | pub trait Not { + | ^^^^^^^^^^^^^ error[E0604]: only `u8` can be cast as `char`, not `u32` --> $DIR/error-festival.rs:25:5 diff --git a/src/test/ui/extern/extern-main-issue-86110.stderr b/src/test/ui/extern/extern-main-issue-86110.stderr index cd3de227dcf..18dfddc46bd 100644 --- a/src/test/ui/extern/extern-main-issue-86110.stderr +++ b/src/test/ui/extern/extern-main-issue-86110.stderr @@ -2,7 +2,7 @@ error: the `main` function cannot be declared in an `extern` block --> $DIR/extern-main-issue-86110.rs:4:5 | LL | fn main(); - | ^^^^^^^^^^ + | ^^^^^^^^^ error: aborting due to previous error diff --git a/src/test/ui/extern/extern-types-distinct-types.stderr b/src/test/ui/extern/extern-types-distinct-types.stderr index f69629232ae..ca25aa64eb8 100644 --- a/src/test/ui/extern/extern-types-distinct-types.stderr +++ b/src/test/ui/extern/extern-types-distinct-types.stderr @@ -2,9 +2,9 @@ error[E0308]: mismatched types --> $DIR/extern-types-distinct-types.rs:9:5 | LL | type A; - | ------- the found foreign type + | ------ the found foreign type LL | type B; - | ------- the expected foreign type + | ------ the expected foreign type ... LL | fn foo(r: &A) -> &B { | -- expected `&B` because of return type diff --git a/src/test/ui/feature-gates/feature-gate-exhaustive-patterns.stderr b/src/test/ui/feature-gates/feature-gate-exhaustive-patterns.stderr index 21180f31bbd..f8349391a0f 100644 --- a/src/test/ui/feature-gates/feature-gate-exhaustive-patterns.stderr +++ b/src/test/ui/feature-gates/feature-gate-exhaustive-patterns.stderr @@ -9,15 +9,11 @@ LL | let Ok(_x) = foo(); note: `Result<u32, !>` defined here --> $SRC_DIR/core/src/result.rs:LL:COL | -LL | / pub enum Result<T, E> { -LL | | /// Contains the success value -LL | | #[lang = "Ok"] -LL | | #[stable(feature = "rust1", since = "1.0.0")] -... | -LL | | Err(#[stable(feature = "rust1", since = "1.0.0")] E), - | | ^^^ not covered -LL | | } - | |_- +LL | pub enum Result<T, E> { + | --------------------- +... +LL | Err(#[stable(feature = "rust1", since = "1.0.0")] E), + | ^^^ not covered = note: the matched value is of type `Result<u32, !>` help: you might want to use `if let` to ignore the variant that isn't matched | diff --git a/src/test/ui/generic-associated-types/generic-associated-types-where.stderr b/src/test/ui/generic-associated-types/generic-associated-types-where.stderr index 68594bba486..c7ebb9880f7 100644 --- a/src/test/ui/generic-associated-types/generic-associated-types-where.stderr +++ b/src/test/ui/generic-associated-types/generic-associated-types-where.stderr @@ -14,10 +14,10 @@ error[E0276]: impl has stricter requirements than trait --> $DIR/generic-associated-types-where.rs:22:5 | LL | type Assoc3<T>; - | --------------- definition of `Assoc3` from trait + | -------------- definition of `Assoc3` from trait ... LL | type Assoc3<T> = Vec<T> where T: Iterator; - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ impl has extra requirement `T: Iterator` + | ^^^^^^^^^^^^^^ impl has extra requirement `T: Iterator` error: aborting due to 2 previous errors diff --git a/src/test/ui/generic-associated-types/impl_bounds.stderr b/src/test/ui/generic-associated-types/impl_bounds.stderr index 3d90471e398..6aa52b179a3 100644 --- a/src/test/ui/generic-associated-types/impl_bounds.stderr +++ b/src/test/ui/generic-associated-types/impl_bounds.stderr @@ -2,25 +2,25 @@ error: `impl` associated type signature for `A` doesn't match `trait` associated --> $DIR/impl_bounds.rs:15:5 | LL | type A<'a> where Self: 'a; - | -------------------------- expected + | ---------- expected ... LL | type A<'a> = (&'a ()) where Self: 'static; - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ found + | ^^^^^^^^^^ found error: `impl` associated type signature for `B` doesn't match `trait` associated type signature --> $DIR/impl_bounds.rs:17:5 | LL | type B<'a, 'b> where 'a: 'b; - | ---------------------------- expected + | -------------- expected ... LL | type B<'a, 'b> = (&'a(), &'b ()) where 'b: 'a; - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ found + | ^^^^^^^^^^^^^^ found error[E0478]: lifetime bound not satisfied --> $DIR/impl_bounds.rs:17:22 | LL | type B<'a, 'b> where 'a: 'b; - | ---------------------------- definition of `B` from trait + | -------------- definition of `B` from trait ... LL | type B<'a, 'b> = (&'a(), &'b ()) where 'b: 'a; | ^^^^^^^^^^^^^^^ - help: try copying this clause from the trait: `, 'a: 'b` @@ -40,7 +40,7 @@ error[E0277]: the trait bound `T: Copy` is not satisfied --> $DIR/impl_bounds.rs:20:5 | LL | type C = String where Self: Copy; - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ the trait `Copy` is not implemented for `T` + | ^^^^^^ the trait `Copy` is not implemented for `T` | note: required because of the requirements on the impl of `Copy` for `Fooy<T>` --> $DIR/impl_bounds.rs:11:10 @@ -54,7 +54,7 @@ LL | trait Foo { | --- in this trait ... LL | type C where Self: Clone; - | ^^^^^^^^^^^^^^^^^^^^^^^^^ this trait associated type doesn't have the requirement `Fooy<T>: Copy` + | ^^^^^^ this trait associated type doesn't have the requirement `Fooy<T>: Copy` = note: this error originates in the derive macro `Copy` (in Nightly builds, run with -Z macro-backtrace for more info) help: consider restricting type parameter `T` | diff --git a/src/test/ui/generic-associated-types/issue-47206-where-clause.stderr b/src/test/ui/generic-associated-types/issue-47206-where-clause.stderr index 39beac38c0b..c560e2405d5 100644 --- a/src/test/ui/generic-associated-types/issue-47206-where-clause.stderr +++ b/src/test/ui/generic-associated-types/issue-47206-where-clause.stderr @@ -2,10 +2,10 @@ error[E0276]: impl has stricter requirements than trait --> $DIR/issue-47206-where-clause.rs:12:5 | LL | type Assoc3<T>; - | --------------- definition of `Assoc3` from trait + | -------------- definition of `Assoc3` from trait ... LL | type Assoc3<T> = Vec<T> where T: Iterator; - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ impl has extra requirement `T: Iterator` + | ^^^^^^^^^^^^^^ impl has extra requirement `T: Iterator` error: aborting due to previous error diff --git a/src/test/ui/generic-associated-types/issue-78113-lifetime-mismatch-dyn-trait-box.stderr b/src/test/ui/generic-associated-types/issue-78113-lifetime-mismatch-dyn-trait-box.stderr index c4a7d8faa41..d487f19ba74 100644 --- a/src/test/ui/generic-associated-types/issue-78113-lifetime-mismatch-dyn-trait-box.stderr +++ b/src/test/ui/generic-associated-types/issue-78113-lifetime-mismatch-dyn-trait-box.stderr @@ -45,7 +45,7 @@ note: ...does not necessarily outlive the static lifetime introduced by the comp --> $DIR/issue-78113-lifetime-mismatch-dyn-trait-box.rs:21:1 | LL | impl C for Box<dyn A + 'static> {} - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ error: incompatible lifetime on type --> $DIR/issue-78113-lifetime-mismatch-dyn-trait-box.rs:37:18 diff --git a/src/test/ui/generic-associated-types/issue-90014.stderr b/src/test/ui/generic-associated-types/issue-90014.stderr index 51fe3360c7e..457c582e8c8 100644 --- a/src/test/ui/generic-associated-types/issue-90014.stderr +++ b/src/test/ui/generic-associated-types/issue-90014.stderr @@ -2,7 +2,7 @@ error[E0477]: the type `&mut ()` does not fulfill the required lifetime --> $DIR/issue-90014.rs:14:20 | LL | type Fut<'a> where Self: 'a; - | ---------------------------- definition of `Fut` from trait + | ------------ definition of `Fut` from trait ... LL | type Fut<'a> = impl Future<Output = ()>; | ^^^^^^^^^^^^^^^^^^^^^^^^- help: try copying this clause from the trait: `where Self: 'a` diff --git a/src/test/ui/generic-associated-types/issue-91883.stderr b/src/test/ui/generic-associated-types/issue-91883.stderr index ed700876e02..baf4889cc1d 100644 --- a/src/test/ui/generic-associated-types/issue-91883.stderr +++ b/src/test/ui/generic-associated-types/issue-91883.stderr @@ -1,14 +1,11 @@ error[E0478]: lifetime bound not satisfied --> $DIR/issue-91883.rs:32:24 | -LL | / type Cursor<'tx>: Cursor<'tx> -LL | | where -LL | | 'db: 'tx, -LL | | Self: 'tx; - | |__________________- definition of `Cursor` from trait +LL | type Cursor<'tx>: Cursor<'tx> + | ----------------------------- definition of `Cursor` from trait ... -LL | type Cursor<'tx> = CursorImpl<'tx>; - | ^^^^^^^^^^^^^^^- help: try copying these clauses from the trait: `where 'db: 'tx, Self: 'tx` +LL | type Cursor<'tx> = CursorImpl<'tx>; + | ^^^^^^^^^^^^^^^- help: try copying these clauses from the trait: `where 'db: 'tx, Self: 'tx` | note: lifetime parameter instantiated with the lifetime `'db` as defined here --> $DIR/issue-91883.rs:31:6 diff --git a/src/test/ui/generic-associated-types/issue-92033.stderr b/src/test/ui/generic-associated-types/issue-92033.stderr index 5b90199b809..6dd901027d7 100644 --- a/src/test/ui/generic-associated-types/issue-92033.stderr +++ b/src/test/ui/generic-associated-types/issue-92033.stderr @@ -1,13 +1,11 @@ error[E0477]: the type `&'s Texture` does not fulfill the required lifetime --> $DIR/issue-92033.rs:22:28 | -LL | / type TextureIter<'a>: Iterator<Item = &'a Texture> -LL | | where -LL | | Self: 'a; - | |_________________- definition of `TextureIter` from trait +LL | type TextureIter<'a>: Iterator<Item = &'a Texture> + | -------------------------------------------------- definition of `TextureIter` from trait ... -LL | type TextureIter<'a> = std::option::IntoIter<&'a Texture>; - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^- help: try copying this clause from the trait: `where Self: 'a` +LL | type TextureIter<'a> = std::option::IntoIter<&'a Texture>; + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^- help: try copying this clause from the trait: `where Self: 'a` | note: type must outlive the lifetime `'a` as defined here --> $DIR/issue-92033.rs:22:22 diff --git a/src/test/ui/generic-associated-types/method-unsatified-assoc-type-predicate.stderr b/src/test/ui/generic-associated-types/method-unsatified-assoc-type-predicate.stderr index 1322914797b..2804364890f 100644 --- a/src/test/ui/generic-associated-types/method-unsatified-assoc-type-predicate.stderr +++ b/src/test/ui/generic-associated-types/method-unsatified-assoc-type-predicate.stderr @@ -2,7 +2,7 @@ error[E0599]: the method `f` exists for struct `S`, but its trait bounds were no --> $DIR/method-unsatified-assoc-type-predicate.rs:30:7 | LL | struct S; - | --------- + | -------- | | | | | method `f` not found for this struct | doesn't satisfy `<S as X>::Y<i32> = i32` diff --git a/src/test/ui/generic-associated-types/missing-where-clause-on-trait.stderr b/src/test/ui/generic-associated-types/missing-where-clause-on-trait.stderr index 9e0896127a8..0256d2f20fc 100644 --- a/src/test/ui/generic-associated-types/missing-where-clause-on-trait.stderr +++ b/src/test/ui/generic-associated-types/missing-where-clause-on-trait.stderr @@ -2,10 +2,10 @@ error: `impl` associated type signature for `Assoc` doesn't match `trait` associ --> $DIR/missing-where-clause-on-trait.rs:9:5 | LL | type Assoc<'a, 'b>; - | ------------------- expected + | ------------------ expected ... LL | type Assoc<'a, 'b> = () where 'a: 'b; - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ found + | ^^^^^^^^^^^^^^^^^^ found error: aborting due to previous error diff --git a/src/test/ui/impl-trait/hidden-type-is-opaque-2.stderr b/src/test/ui/impl-trait/hidden-type-is-opaque-2.stderr index 11ba5aa7867..957052feba9 100644 --- a/src/test/ui/impl-trait/hidden-type-is-opaque-2.stderr +++ b/src/test/ui/impl-trait/hidden-type-is-opaque-2.stderr @@ -3,16 +3,12 @@ error[E0282]: type annotations needed | LL | cont.reify_as(); | ^^^^ cannot infer type - | - = note: type must be known at this point error[E0282]: type annotations needed --> $DIR/hidden-type-is-opaque-2.rs:18:9 | LL | cont.reify_as(); | ^^^^ cannot infer type - | - = note: type must be known at this point error: aborting due to 2 previous errors diff --git a/src/test/ui/impl-trait/issues/issue-62742.stderr b/src/test/ui/impl-trait/issues/issue-62742.stderr index 44d775b695e..2d14faf7677 100644 --- a/src/test/ui/impl-trait/issues/issue-62742.stderr +++ b/src/test/ui/impl-trait/issues/issue-62742.stderr @@ -18,7 +18,7 @@ LL | WrongImpl::<()>::foo(0i32); | ^^^ function or associated item cannot be called on `SafeImpl<(), RawImpl<()>>` due to unsatisfied trait bounds ... LL | pub struct RawImpl<T>(PhantomData<T>); - | -------------------------------------- doesn't satisfy `RawImpl<()>: Raw<()>` + | --------------------- doesn't satisfy `RawImpl<()>: Raw<()>` ... LL | pub struct SafeImpl<T: ?Sized, A: Raw<T>>(PhantomData<(A, T)>); | -------- function or associated item `foo` not found for this struct @@ -28,10 +28,8 @@ LL | pub struct SafeImpl<T: ?Sized, A: Raw<T>>(PhantomData<(A, T)>); note: the following trait must be implemented --> $DIR/issue-62742.rs:12:1 | -LL | / pub trait Raw<T: ?Sized> { -LL | | type Value; -LL | | } - | |_^ +LL | pub trait Raw<T: ?Sized> { + | ^^^^^^^^^^^^^^^^^^^^^^^^ error[E0277]: the trait bound `RawImpl<()>: Raw<()>` is not satisfied --> $DIR/issue-62742.rs:6:5 diff --git a/src/test/ui/imports/inaccessible_type_aliases.rs b/src/test/ui/imports/inaccessible_type_aliases.rs new file mode 100644 index 00000000000..c3d4214e282 --- /dev/null +++ b/src/test/ui/imports/inaccessible_type_aliases.rs @@ -0,0 +1,14 @@ +mod a { + type Foo = u64; + type Bar = u64; +} + +mod b { + type Foo = u64; +} + +fn main() { + let x: Foo = 100; //~ ERROR: cannot find type `Foo` in this scope + let y: Bar = 100; //~ ERROR: cannot find type `Bar` in this scope + println!("x: {}, y: {}", x, y); +} diff --git a/src/test/ui/imports/inaccessible_type_aliases.stderr b/src/test/ui/imports/inaccessible_type_aliases.stderr new file mode 100644 index 00000000000..ef224246061 --- /dev/null +++ b/src/test/ui/imports/inaccessible_type_aliases.stderr @@ -0,0 +1,30 @@ +error[E0412]: cannot find type `Foo` in this scope + --> $DIR/inaccessible_type_aliases.rs:11:12 + | +LL | let x: Foo = 100; + | ^^^ not found in this scope + | +note: these type aliases exist but are inaccessible + --> $DIR/inaccessible_type_aliases.rs:2:5 + | +LL | type Foo = u64; + | ^^^^^^^^^^^^^^^ `a::Foo`: not accessible +... +LL | type Foo = u64; + | ^^^^^^^^^^^^^^^ `b::Foo`: not accessible + +error[E0412]: cannot find type `Bar` in this scope + --> $DIR/inaccessible_type_aliases.rs:12:12 + | +LL | let y: Bar = 100; + | ^^^ not found in this scope + | +note: type alias `a::Bar` exists but is inaccessible + --> $DIR/inaccessible_type_aliases.rs:3:5 + | +LL | type Bar = u64; + | ^^^^^^^^^^^^^^^ not accessible + +error: aborting due to 2 previous errors + +For more information about this error, try `rustc --explain E0412`. diff --git a/src/test/ui/inference/ambiguous_type_parameter.stderr b/src/test/ui/inference/ambiguous_type_parameter.stderr index a08342371b3..9cbe221de13 100644 --- a/src/test/ui/inference/ambiguous_type_parameter.stderr +++ b/src/test/ui/inference/ambiguous_type_parameter.stderr @@ -2,7 +2,12 @@ error[E0282]: type annotations needed --> $DIR/ambiguous_type_parameter.rs:16:19 | LL | InMemoryStore.get_raw(&String::default()); - | ^^^^^^^ cannot infer type for type parameter `K` + | ^^^^^^^ + | +help: try using a fully qualified path to specify the expected types + | +LL | <InMemoryStore as Store<String, HashMap<K, String>>>::get_raw(&InMemoryStore, &String::default()); + | +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ ~ error: aborting due to previous error diff --git a/src/test/ui/inference/cannot-infer-partial-try-return.rs b/src/test/ui/inference/cannot-infer-partial-try-return.rs index 976827a4478..b555697dc34 100644 --- a/src/test/ui/inference/cannot-infer-partial-try-return.rs +++ b/src/test/ui/inference/cannot-infer-partial-try-return.rs @@ -16,8 +16,8 @@ fn infallible() -> Result<(), std::convert::Infallible> { fn main() { let x = || -> Result<_, QualifiedError<_>> { - //~^ ERROR type annotations needed for `Result<(), QualifiedError<_>>` infallible()?; Ok(()) + //~^ ERROR type annotations needed }; } diff --git a/src/test/ui/inference/cannot-infer-partial-try-return.stderr b/src/test/ui/inference/cannot-infer-partial-try-return.stderr index 220602c124c..2a56aaa44fe 100644 --- a/src/test/ui/inference/cannot-infer-partial-try-return.stderr +++ b/src/test/ui/inference/cannot-infer-partial-try-return.stderr @@ -1,13 +1,15 @@ -error[E0282]: type annotations needed for `Result<(), QualifiedError<_>>` - --> $DIR/cannot-infer-partial-try-return.rs:18:13 +error[E0282]: type annotations needed + --> $DIR/cannot-infer-partial-try-return.rs:20:9 | -LL | let x = || -> Result<_, QualifiedError<_>> { - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ +LL | infallible()?; + | ------------- type must be known at this point +LL | Ok(()) + | ^^ cannot infer type of the type parameter `E` declared on the enum `Result` | -help: try giving this closure an explicit return type +help: consider specifying the generic arguments | -LL | let x = || -> Result<(), QualifiedError<_>> { - | ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +LL | Ok::<(), QualifiedError<_>>(()) + | +++++++++++++++++++++++++ error: aborting due to previous error diff --git a/src/test/ui/inference/erase-type-params-in-label.stderr b/src/test/ui/inference/erase-type-params-in-label.stderr index fd58844c238..7bb281802d2 100644 --- a/src/test/ui/inference/erase-type-params-in-label.stderr +++ b/src/test/ui/inference/erase-type-params-in-label.stderr @@ -2,7 +2,7 @@ error[E0283]: type annotations needed for `Foo<i32, &str, W, Z>` --> $DIR/erase-type-params-in-label.rs:2:9 | LL | let foo = foo(1, ""); - | ^^^ + | ^^^ --- type must be known at this point | = note: cannot satisfy `_: Default` note: required by a bound in `foo` @@ -23,7 +23,7 @@ error[E0283]: type annotations needed for `Bar<i32, &str, Z>` --> $DIR/erase-type-params-in-label.rs:5:9 | LL | let bar = bar(1, ""); - | ^^^ + | ^^^ --- type must be known at this point | = note: cannot satisfy `_: Default` note: required by a bound in `bar` diff --git a/src/test/ui/inference/issue-72616.stderr b/src/test/ui/inference/issue-72616.stderr index 3c53d8126e7..a71ce9a8ef2 100644 --- a/src/test/ui/inference/issue-72616.stderr +++ b/src/test/ui/inference/issue-72616.stderr @@ -2,7 +2,9 @@ error[E0283]: type annotations needed --> $DIR/issue-72616.rs:20:37 | LL | if String::from("a") == "a".try_into().unwrap() {} - | ^^^^^^^^ + | -- ^^^^^^^^ + | | + | type must be known at this point | = note: multiple `impl`s satisfying `String: PartialEq<_>` found in the `alloc` crate: - impl PartialEq for String; diff --git a/src/test/ui/inference/issue-72690.stderr b/src/test/ui/inference/issue-72690.stderr index 9edf14ef291..d4eeda07366 100644 --- a/src/test/ui/inference/issue-72690.stderr +++ b/src/test/ui/inference/issue-72690.stderr @@ -55,7 +55,7 @@ error[E0283]: type annotations needed for `&T` --> $DIR/issue-72690.rs:17:9 | LL | let _ = "x".as_ref(); - | ^ + | ^ ------ type must be known at this point | = note: multiple `impl`s satisfying `str: AsRef<_>` found in the following crates: `core`, `std`: - impl AsRef<OsStr> for str; diff --git a/src/test/ui/inference/issue-86162-1.stderr b/src/test/ui/inference/issue-86162-1.stderr index 6641b29b30b..e395e65fad0 100644 --- a/src/test/ui/inference/issue-86162-1.stderr +++ b/src/test/ui/inference/issue-86162-1.stderr @@ -2,7 +2,9 @@ error[E0283]: type annotations needed --> $DIR/issue-86162-1.rs:7:9 | LL | foo(gen()); //<- Do not suggest `foo::<impl Clone>()`! - | ^^^ cannot infer type of the type parameter `T` declared on the function `gen` + | --- ^^^ cannot infer type of the type parameter `T` declared on the function `gen` + | | + | type must be known at this point | = note: cannot satisfy `_: Clone` note: required by a bound in `foo` diff --git a/src/test/ui/inference/issue-86162-2.stderr b/src/test/ui/inference/issue-86162-2.stderr index d2a026a9269..30e6e10eaa2 100644 --- a/src/test/ui/inference/issue-86162-2.stderr +++ b/src/test/ui/inference/issue-86162-2.stderr @@ -2,7 +2,9 @@ error[E0283]: type annotations needed --> $DIR/issue-86162-2.rs:12:14 | LL | Foo::bar(gen()); //<- Do not suggest `Foo::bar::<impl Clone>()`! - | ^^^ cannot infer type of the type parameter `T` declared on the function `gen` + | -------- ^^^ cannot infer type of the type parameter `T` declared on the function `gen` + | | + | type must be known at this point | = note: cannot satisfy `_: Clone` note: required by a bound in `Foo::bar` diff --git a/src/test/ui/inference/need_type_info/channel.rs b/src/test/ui/inference/need_type_info/channel.rs new file mode 100644 index 00000000000..e2ba5a94171 --- /dev/null +++ b/src/test/ui/inference/need_type_info/channel.rs @@ -0,0 +1,19 @@ +// Test that we suggest specifying the generic argument of `channel` +// instead of the return type of that function, which is a lot more +// complex. +use std::sync::mpsc::channel; + +fn no_tuple() { + let _data = + channel(); //~ ERROR type annotations needed +} + +fn tuple() { + let (_sender, _receiver) = + channel(); //~ ERROR type annotations needed +} + +fn main() { + no_tuple(); + tuple(); +} diff --git a/src/test/ui/inference/need_type_info/channel.stderr b/src/test/ui/inference/need_type_info/channel.stderr new file mode 100644 index 00000000000..e33ace0338d --- /dev/null +++ b/src/test/ui/inference/need_type_info/channel.stderr @@ -0,0 +1,25 @@ +error[E0282]: type annotations needed + --> $DIR/channel.rs:8:9 + | +LL | channel(); + | ^^^^^^^ cannot infer type of the type parameter `T` declared on the function `channel` + | +help: consider specifying the generic argument + | +LL | channel::<T>(); + | +++++ + +error[E0282]: type annotations needed + --> $DIR/channel.rs:13:9 + | +LL | channel(); + | ^^^^^^^ cannot infer type of the type parameter `T` declared on the function `channel` + | +help: consider specifying the generic argument + | +LL | channel::<T>(); + | +++++ + +error: aborting due to 2 previous errors + +For more information about this error, try `rustc --explain E0282`. diff --git a/src/test/ui/inference/need_type_info/expr-struct-type-relative-enum.rs b/src/test/ui/inference/need_type_info/expr-struct-type-relative-enum.rs new file mode 100644 index 00000000000..42af9fa8d11 --- /dev/null +++ b/src/test/ui/inference/need_type_info/expr-struct-type-relative-enum.rs @@ -0,0 +1,21 @@ +trait Foo { + type Output; + + fn baz() -> Self::Output; +} + +fn needs_infer<T>() {} + +enum Bar { + Variant {} +} + +impl Foo for u8 { + type Output = Bar; + fn baz() -> Self::Output { + needs_infer(); //~ ERROR type annotations needed + Self::Output::Variant {} + } +} + +fn main() {} diff --git a/src/test/ui/inference/need_type_info/expr-struct-type-relative-enum.stderr b/src/test/ui/inference/need_type_info/expr-struct-type-relative-enum.stderr new file mode 100644 index 00000000000..68ecb381348 --- /dev/null +++ b/src/test/ui/inference/need_type_info/expr-struct-type-relative-enum.stderr @@ -0,0 +1,14 @@ +error[E0282]: type annotations needed + --> $DIR/expr-struct-type-relative-enum.rs:16:9 + | +LL | needs_infer(); + | ^^^^^^^^^^^ cannot infer type of the type parameter `T` declared on the function `needs_infer` + | +help: consider specifying the generic argument + | +LL | needs_infer::<T>(); + | +++++ + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0282`. diff --git a/src/test/ui/inference/need_type_info/expr-struct-type-relative-gat.rs b/src/test/ui/inference/need_type_info/expr-struct-type-relative-gat.rs new file mode 100644 index 00000000000..bcd29bb4e34 --- /dev/null +++ b/src/test/ui/inference/need_type_info/expr-struct-type-relative-gat.rs @@ -0,0 +1,21 @@ +#![feature(generic_associated_types)] + +trait Foo { + type Output<T>; + + fn baz(); +} + +enum Bar<T> { + Simple {}, + Generic(T), +} + +impl Foo for u8 { + type Output<T> = Bar<T>; + fn baz() { + Self::Output::Simple {}; //~ ERROR type annotations needed + } +} + +fn main() {} diff --git a/src/test/ui/inference/need_type_info/expr-struct-type-relative-gat.stderr b/src/test/ui/inference/need_type_info/expr-struct-type-relative-gat.stderr new file mode 100644 index 00000000000..65a75b68c1f --- /dev/null +++ b/src/test/ui/inference/need_type_info/expr-struct-type-relative-gat.stderr @@ -0,0 +1,9 @@ +error[E0282]: type annotations needed + --> $DIR/expr-struct-type-relative-gat.rs:17:9 + | +LL | Self::Output::Simple {}; + | ^^^^^^^^^^^^ cannot infer type for type parameter `T` declared on the associated type `Output` + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0282`. diff --git a/src/test/ui/inference/need_type_info/expr-struct-type-relative.rs b/src/test/ui/inference/need_type_info/expr-struct-type-relative.rs new file mode 100644 index 00000000000..c3ece2b16cf --- /dev/null +++ b/src/test/ui/inference/need_type_info/expr-struct-type-relative.rs @@ -0,0 +1,21 @@ +// regression test for #98598 + +trait Foo { + type Output; + + fn baz() -> Self::Output; +} + +fn needs_infer<T>() {} + +struct Bar {} + +impl Foo for u8 { + type Output = Bar; + fn baz() -> Self::Output { + needs_infer(); //~ ERROR type annotations needed + Self::Output {} + } +} + +fn main() {} diff --git a/src/test/ui/inference/need_type_info/expr-struct-type-relative.stderr b/src/test/ui/inference/need_type_info/expr-struct-type-relative.stderr new file mode 100644 index 00000000000..397d8e7be04 --- /dev/null +++ b/src/test/ui/inference/need_type_info/expr-struct-type-relative.stderr @@ -0,0 +1,14 @@ +error[E0282]: type annotations needed + --> $DIR/expr-struct-type-relative.rs:16:9 + | +LL | needs_infer(); + | ^^^^^^^^^^^ cannot infer type of the type parameter `T` declared on the function `needs_infer` + | +help: consider specifying the generic argument + | +LL | needs_infer::<T>(); + | +++++ + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0282`. diff --git a/src/test/ui/infinite/infinite-struct.rs b/src/test/ui/infinite/infinite-struct.rs index 70a203ea6e8..74185dc597b 100644 --- a/src/test/ui/infinite/infinite-struct.rs +++ b/src/test/ui/infinite/infinite-struct.rs @@ -1,6 +1,5 @@ struct Take(Take); //~^ ERROR has infinite size -//~| ERROR cycle detected // check that we don't hang trying to find the tail of a recursive struct (#79437) fn foo() -> Take { diff --git a/src/test/ui/infinite/infinite-struct.stderr b/src/test/ui/infinite/infinite-struct.stderr index 383e13fd4b0..5a6d13786d1 100644 --- a/src/test/ui/infinite/infinite-struct.stderr +++ b/src/test/ui/infinite/infinite-struct.stderr @@ -2,9 +2,8 @@ error[E0072]: recursive type `Take` has infinite size --> $DIR/infinite-struct.rs:1:1 | LL | struct Take(Take); - | ^^^^^^^^^^^^----^^ - | | | - | | recursive without indirection + | ^^^^^^^^^^^ ---- recursive without indirection + | | | recursive type has infinite size | help: insert some indirection (e.g., a `Box`, `Rc`, or `&`) to make `Take` representable @@ -12,16 +11,6 @@ help: insert some indirection (e.g., a `Box`, `Rc`, or `&`) to make `Take` repre LL | struct Take(Box<Take>); | ++++ + -error[E0391]: cycle detected when computing drop-check constraints for `Take` - --> $DIR/infinite-struct.rs:1:1 - | -LL | struct Take(Take); - | ^^^^^^^^^^^^^^^^^^ - | - = note: ...which immediately requires computing drop-check constraints for `Take` again - = note: cycle used when computing dropck types for `Canonical { max_universe: U0, variables: [], value: ParamEnvAnd { param_env: ParamEnv { caller_bounds: [], reveal: UserFacing, constness: NotConst }, value: Take } }` - -error: aborting due to 2 previous errors +error: aborting due to previous error -Some errors have detailed explanations: E0072, E0391. -For more information about an error, try `rustc --explain E0072`. +For more information about this error, try `rustc --explain E0072`. diff --git a/src/test/ui/infinite/infinite-tag-type-recursion.rs b/src/test/ui/infinite/infinite-tag-type-recursion.rs index 8578c5545bc..87a9e08dd38 100644 --- a/src/test/ui/infinite/infinite-tag-type-recursion.rs +++ b/src/test/ui/infinite/infinite-tag-type-recursion.rs @@ -1,5 +1,4 @@ enum MList { Cons(isize, MList), Nil } //~^ ERROR recursive type `MList` has infinite size -//~| ERROR cycle detected when computing drop-check constraints for `MList` fn main() { let a = MList::Cons(10, MList::Cons(11, MList::Nil)); } diff --git a/src/test/ui/infinite/infinite-tag-type-recursion.stderr b/src/test/ui/infinite/infinite-tag-type-recursion.stderr index 1802c7599a3..d2dad4b9178 100644 --- a/src/test/ui/infinite/infinite-tag-type-recursion.stderr +++ b/src/test/ui/infinite/infinite-tag-type-recursion.stderr @@ -11,16 +11,6 @@ help: insert some indirection (e.g., a `Box`, `Rc`, or `&`) to make `MList` repr LL | enum MList { Cons(isize, Box<MList>), Nil } | ++++ + -error[E0391]: cycle detected when computing drop-check constraints for `MList` - --> $DIR/infinite-tag-type-recursion.rs:1:1 - | -LL | enum MList { Cons(isize, MList), Nil } - | ^^^^^^^^^^ - | - = note: ...which immediately requires computing drop-check constraints for `MList` again - = note: cycle used when computing dropck types for `Canonical { max_universe: U0, variables: [], value: ParamEnvAnd { param_env: ParamEnv { caller_bounds: [], reveal: UserFacing, constness: NotConst }, value: MList } }` - -error: aborting due to 2 previous errors +error: aborting due to previous error -Some errors have detailed explanations: E0072, E0391. -For more information about an error, try `rustc --explain E0072`. +For more information about this error, try `rustc --explain E0072`. diff --git a/src/test/ui/infinite/infinite-trait-alias-recursion.stderr b/src/test/ui/infinite/infinite-trait-alias-recursion.stderr index 5ecaedb3cb2..b925b3b018c 100644 --- a/src/test/ui/infinite/infinite-trait-alias-recursion.stderr +++ b/src/test/ui/infinite/infinite-trait-alias-recursion.stderr @@ -2,7 +2,7 @@ error[E0391]: cycle detected when computing the super predicates of `T1` --> $DIR/infinite-trait-alias-recursion.rs:3:1 | LL | trait T1 = T2; - | ^^^^^^^^^^^^^^ + | ^^^^^^^^ | note: ...which requires computing the super traits of `T1`... --> $DIR/infinite-trait-alias-recursion.rs:3:12 @@ -13,7 +13,7 @@ note: ...which requires computing the super predicates of `T2`... --> $DIR/infinite-trait-alias-recursion.rs:6:1 | LL | trait T2 = T3; - | ^^^^^^^^^^^^^^ + | ^^^^^^^^ note: ...which requires computing the super traits of `T2`... --> $DIR/infinite-trait-alias-recursion.rs:6:12 | @@ -23,7 +23,7 @@ note: ...which requires computing the super predicates of `T3`... --> $DIR/infinite-trait-alias-recursion.rs:8:1 | LL | trait T3 = T1 + T3; - | ^^^^^^^^^^^^^^^^^^^ + | ^^^^^^^^ note: ...which requires computing the super traits of `T3`... --> $DIR/infinite-trait-alias-recursion.rs:8:12 | diff --git a/src/test/ui/invalid_dispatch_from_dyn_impls.stderr b/src/test/ui/invalid_dispatch_from_dyn_impls.stderr index 6d62d4fd071..b5b32d2f0bd 100644 --- a/src/test/ui/invalid_dispatch_from_dyn_impls.stderr +++ b/src/test/ui/invalid_dispatch_from_dyn_impls.stderr @@ -1,22 +1,16 @@ error[E0378]: the trait `DispatchFromDyn` may only be implemented for structs containing the field being coerced, ZST fields with 1 byte alignment, and nothing else --> $DIR/invalid_dispatch_from_dyn_impls.rs:10:1 | -LL | / impl<T, U> DispatchFromDyn<WrapperWithExtraField<U>> for WrapperWithExtraField<T> -LL | | where -LL | | T: DispatchFromDyn<U>, -LL | | {} - | |__^ +LL | impl<T, U> DispatchFromDyn<WrapperWithExtraField<U>> for WrapperWithExtraField<T> + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ | = note: extra field `1` of type `i32` is not allowed error[E0378]: implementing the `DispatchFromDyn` trait requires multiple coercions --> $DIR/invalid_dispatch_from_dyn_impls.rs:21:1 | -LL | / impl<T: ?Sized, U: ?Sized> DispatchFromDyn<MultiplePointers<U>> for MultiplePointers<T> -LL | | where -LL | | T: Unsize<U>, -LL | | {} - | |__^ +LL | impl<T: ?Sized, U: ?Sized> DispatchFromDyn<MultiplePointers<U>> for MultiplePointers<T> + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ | = note: the trait `DispatchFromDyn` may only be implemented for a coercion between structures with a single field being coerced = note: currently, 2 fields need coercions: `ptr1` (`*const T` to `*const U`), `ptr2` (`*const T` to `*const U`) @@ -25,25 +19,19 @@ error[E0378]: the trait `DispatchFromDyn` may only be implemented for a coercion --> $DIR/invalid_dispatch_from_dyn_impls.rs:31:1 | LL | impl<T: ?Sized, U: ?Sized> DispatchFromDyn<NothingToCoerce<T>> for NothingToCoerce<U> {} - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ error[E0378]: structs implementing `DispatchFromDyn` may not have `#[repr(packed)]` or `#[repr(C)]` --> $DIR/invalid_dispatch_from_dyn_impls.rs:37:1 | -LL | / impl<T: ?Sized, U: ?Sized> DispatchFromDyn<HasReprC<U>> for HasReprC<T> -LL | | where -LL | | T: Unsize<U>, -LL | | {} - | |__^ +LL | impl<T: ?Sized, U: ?Sized> DispatchFromDyn<HasReprC<U>> for HasReprC<T> + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ error[E0378]: the trait `DispatchFromDyn` may only be implemented for structs containing the field being coerced, ZST fields with 1 byte alignment, and nothing else --> $DIR/invalid_dispatch_from_dyn_impls.rs:46:1 | -LL | / impl<T: ?Sized, U: ?Sized> DispatchFromDyn<OverAligned<U>> for OverAligned<T> -LL | | where -LL | | T: Unsize<U>, -LL | | {} - | |__^ +LL | impl<T: ?Sized, U: ?Sized> DispatchFromDyn<OverAligned<U>> for OverAligned<T> + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ | = note: extra field `1` of type `OverAlignedZst` is not allowed diff --git a/src/test/ui/issues/issue-12028.stderr b/src/test/ui/issues/issue-12028.stderr index 30cb7a1df80..8d6b81c24b6 100644 --- a/src/test/ui/issues/issue-12028.stderr +++ b/src/test/ui/issues/issue-12028.stderr @@ -1,8 +1,14 @@ -error[E0284]: type annotations needed: cannot satisfy `<_ as StreamHasher>::S == <H as StreamHasher>::S` +error[E0284]: type annotations needed --> $DIR/issue-12028.rs:27:14 | LL | self.input_stream(&mut stream); - | ^^^^^^^^^^^^ cannot satisfy `<_ as StreamHasher>::S == <H as StreamHasher>::S` + | ^^^^^^^^^^^^ + | + = note: cannot satisfy `<_ as StreamHasher>::S == <H as StreamHasher>::S` +help: try using a fully qualified path to specify the expected types + | +LL | <u8 as StreamHash<H>>::input_stream(self, &mut stream); + | ++++++++++++++++++++++++++++++++++++ ~ error: aborting due to previous error diff --git a/src/test/ui/issues/issue-14091-2.stderr b/src/test/ui/issues/issue-14091-2.stderr index fbfa6e1abb2..a191afd7980 100644 --- a/src/test/ui/issues/issue-14091-2.stderr +++ b/src/test/ui/issues/issue-14091-2.stderr @@ -8,18 +8,12 @@ note: an implementation of `Not` might be missing for `BytePos` --> $DIR/issue-14091-2.rs:6:1 | LL | pub struct BytePos(pub u32); - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ must implement `Not` + | ^^^^^^^^^^^^^^^^^^ must implement `Not` note: the following trait must be implemented --> $SRC_DIR/core/src/ops/bit.rs:LL:COL | -LL | / pub trait Not { -LL | | /// The resulting type after applying the `!` operator. -LL | | #[stable(feature = "rust1", since = "1.0.0")] -LL | | type Output; -... | -LL | | fn not(self) -> Self::Output; -LL | | } - | |_^ +LL | pub trait Not { + | ^^^^^^^^^^^^^ = note: this error originates in the macro `assert` (in Nightly builds, run with -Z macro-backtrace for more info) error: aborting due to previous error diff --git a/src/test/ui/issues/issue-15965.stderr b/src/test/ui/issues/issue-15965.stderr index 90377c19dee..fe06810b8df 100644 --- a/src/test/ui/issues/issue-15965.stderr +++ b/src/test/ui/issues/issue-15965.stderr @@ -5,8 +5,6 @@ LL | / { return () } LL | | LL | | () | |______^ cannot infer type - | - = note: type must be known at this point error: aborting due to previous error diff --git a/src/test/ui/issues/issue-16250.stderr b/src/test/ui/issues/issue-16250.stderr index 45f854f93ec..ae3b7f334c6 100644 --- a/src/test/ui/issues/issue-16250.stderr +++ b/src/test/ui/issues/issue-16250.stderr @@ -16,7 +16,7 @@ note: the type is defined here --> $DIR/issue-16250.rs:3:1 | LL | pub struct Foo; - | ^^^^^^^^^^^^^^^ + | ^^^^^^^^^^^^^^ error: aborting due to previous error diff --git a/src/test/ui/issues/issue-16725.stderr b/src/test/ui/issues/issue-16725.stderr index 84359803bba..5f6eae73e58 100644 --- a/src/test/ui/issues/issue-16725.stderr +++ b/src/test/ui/issues/issue-16725.stderr @@ -8,7 +8,7 @@ note: the function `bar` is defined here --> $DIR/auxiliary/issue-16725.rs:2:5 | LL | fn bar(); - | ^^^^^^^^^ + | ^^^^^^^^ error: aborting due to previous error diff --git a/src/test/ui/issues/issue-17252.stderr b/src/test/ui/issues/issue-17252.stderr index 4856418ed60..3a629e1ebf4 100644 --- a/src/test/ui/issues/issue-17252.stderr +++ b/src/test/ui/issues/issue-17252.stderr @@ -2,7 +2,7 @@ error[E0391]: cycle detected when const-evaluating + checking `FOO` --> $DIR/issue-17252.rs:1:1 | LL | const FOO: usize = FOO; - | ^^^^^^^^^^^^^^^^^^^^^^^ + | ^^^^^^^^^^^^^^^^ | = note: ...which immediately requires const-evaluating + checking `FOO` again note: cycle used when const-evaluating + checking `main::{constant#0}` diff --git a/src/test/ui/issues/issue-17718-const-privacy.stderr b/src/test/ui/issues/issue-17718-const-privacy.stderr index d4595be7490..133a6360bf9 100644 --- a/src/test/ui/issues/issue-17718-const-privacy.stderr +++ b/src/test/ui/issues/issue-17718-const-privacy.stderr @@ -20,7 +20,7 @@ note: the constant `BAR` is defined here --> $DIR/auxiliary/issue-17718-const-privacy.rs:4:1 | LL | const BAR: usize = 3; - | ^^^^^^^^^^^^^^^^^^^^^ + | ^^^^^^^^^^^^^^^^ error: aborting due to 2 previous errors diff --git a/src/test/ui/issues/issue-17959.stderr b/src/test/ui/issues/issue-17959.stderr index f00356f602e..fb795febf79 100644 --- a/src/test/ui/issues/issue-17959.stderr +++ b/src/test/ui/issues/issue-17959.stderr @@ -7,10 +7,8 @@ LL | impl<T> Drop for G<T> { note: the implementor must specify the same requirement --> $DIR/issue-17959.rs:7:1 | -LL | / struct G<T: ?Sized> { -LL | | _ptr: *const T -LL | | } - | |_^ +LL | struct G<T: ?Sized> { + | ^^^^^^^^^^^^^^^^^^^ error: aborting due to previous error diff --git a/src/test/ui/issues/issue-18389.stderr b/src/test/ui/issues/issue-18389.stderr index dc476f5edc7..6ce78c45d6e 100644 --- a/src/test/ui/issues/issue-18389.stderr +++ b/src/test/ui/issues/issue-18389.stderr @@ -8,9 +8,7 @@ LL | / pub trait Public: Private< LL | | LL | | <Self as Public>::P, LL | | <Self as Public>::R -... | -LL | | fn call_inner(&self); -LL | | } +LL | | > { | |_^ can't leak private trait error: aborting due to previous error diff --git a/src/test/ui/issues/issue-19482.stderr b/src/test/ui/issues/issue-19482.stderr index 42a5a015969..d51cc1f081e 100644 --- a/src/test/ui/issues/issue-19482.stderr +++ b/src/test/ui/issues/issue-19482.stderr @@ -2,7 +2,7 @@ error[E0191]: the value of the associated type `A` (from trait `Foo`) must be sp --> $DIR/issue-19482.rs:10:16 | LL | type A; - | ------- `A` defined here + | ------ `A` defined here ... LL | fn bar(x: &dyn Foo) {} | ^^^ help: specify the associated type: `Foo<A = Type>` diff --git a/src/test/ui/issues/issue-20261.stderr b/src/test/ui/issues/issue-20261.stderr index 73468c7ca16..9ac751e4dc4 100644 --- a/src/test/ui/issues/issue-20261.stderr +++ b/src/test/ui/issues/issue-20261.stderr @@ -3,8 +3,6 @@ error[E0282]: type annotations needed | LL | i.clone(); | ^^^^^ cannot infer type - | - = note: type must be known at this point error: aborting due to previous error diff --git a/src/test/ui/issues/issue-20714.stderr b/src/test/ui/issues/issue-20714.stderr index 456aff05750..2d88ce5e511 100644 --- a/src/test/ui/issues/issue-20714.stderr +++ b/src/test/ui/issues/issue-20714.stderr @@ -2,7 +2,7 @@ error[E0618]: expected function, found `G` --> $DIR/issue-20714.rs:4:13 | LL | struct G; - | --------- `G` defined here + | -------- `G` defined here ... LL | let g = G(); | ^-- diff --git a/src/test/ui/issues/issue-20772.stderr b/src/test/ui/issues/issue-20772.stderr index c964dc41dce..22b9f5bd4cb 100644 --- a/src/test/ui/issues/issue-20772.stderr +++ b/src/test/ui/issues/issue-20772.stderr @@ -1,19 +1,15 @@ error[E0391]: cycle detected when computing the super traits of `T` with associated type name `Item` --> $DIR/issue-20772.rs:1:1 | -LL | / trait T : Iterator<Item=Self::Item> -LL | | -LL | | {} - | |__^ +LL | trait T : Iterator<Item=Self::Item> + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ | = note: ...which immediately requires computing the super traits of `T` with associated type name `Item` again note: cycle used when computing the super traits of `T` --> $DIR/issue-20772.rs:1:1 | -LL | / trait T : Iterator<Item=Self::Item> -LL | | -LL | | {} - | |__^ +LL | trait T : Iterator<Item=Self::Item> + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ error: aborting due to previous error diff --git a/src/test/ui/issues/issue-2151.stderr b/src/test/ui/issues/issue-2151.stderr index e0d946205ad..31a8ca5fbfa 100644 --- a/src/test/ui/issues/issue-2151.stderr +++ b/src/test/ui/issues/issue-2151.stderr @@ -3,8 +3,9 @@ error[E0282]: type annotations needed | LL | let x = panic!(); | ^ +LL | x.clone(); + | - type must be known at this point | - = note: type must be known at this point help: consider giving `x` an explicit type | LL | let x: _ = panic!(); diff --git a/src/test/ui/issues/issue-21701.stderr b/src/test/ui/issues/issue-21701.stderr index 0405ce551b0..ada6f44319d 100644 --- a/src/test/ui/issues/issue-21701.stderr +++ b/src/test/ui/issues/issue-21701.stderr @@ -12,7 +12,7 @@ error[E0618]: expected function, found `Bar` --> $DIR/issue-21701.rs:9:13 | LL | struct Bar; - | ----------- `Bar` defined here + | ---------- `Bar` defined here ... LL | let f = Bar(); | ^^^-- diff --git a/src/test/ui/issues/issue-21950.stderr b/src/test/ui/issues/issue-21950.stderr index 93c2444f884..4909398bb84 100644 --- a/src/test/ui/issues/issue-21950.stderr +++ b/src/test/ui/issues/issue-21950.stderr @@ -1,13 +1,11 @@ error[E0393]: the type parameter `Rhs` must be explicitly specified --> $DIR/issue-21950.rs:10:25 | -LL | / trait Add<Rhs=Self> { -LL | | type Output; -LL | | } - | |_- type parameter `Rhs` must be specified for this +LL | trait Add<Rhs=Self> { + | ------------------- type parameter `Rhs` must be specified for this ... -LL | let x = &10 as &dyn Add; - | ^^^ help: set the type parameter to the desired type: `Add<Rhs>` +LL | let x = &10 as &dyn Add; + | ^^^ help: set the type parameter to the desired type: `Add<Rhs>` | = note: because of the default `Self` reference, type parameters must be specified on object types @@ -15,7 +13,7 @@ error[E0191]: the value of the associated type `Output` (from trait `Add`) must --> $DIR/issue-21950.rs:10:25 | LL | type Output; - | ------------ `Output` defined here + | ----------- `Output` defined here ... LL | let x = &10 as &dyn Add; | ^^^ help: specify the associated type: `Add<Output = Type>` diff --git a/src/test/ui/issues/issue-21974.stderr b/src/test/ui/issues/issue-21974.stderr index dfabde9abc9..4e010a13653 100644 --- a/src/test/ui/issues/issue-21974.stderr +++ b/src/test/ui/issues/issue-21974.stderr @@ -1,8 +1,8 @@ -error[E0283]: type annotations needed +error[E0283]: type annotations needed: cannot satisfy `&'a T: Foo` --> $DIR/issue-21974.rs:11:19 | LL | where &'a T : Foo, - | ^^^ cannot infer type for reference `&'a T` + | ^^^ | = note: cannot satisfy `&'a T: Foo` diff --git a/src/test/ui/issues/issue-22370.stderr b/src/test/ui/issues/issue-22370.stderr index 4da346f56ab..cd27c4e4e4e 100644 --- a/src/test/ui/issues/issue-22370.stderr +++ b/src/test/ui/issues/issue-22370.stderr @@ -2,7 +2,7 @@ error[E0393]: the type parameter `T` must be explicitly specified --> $DIR/issue-22370.rs:3:14 | LL | trait A<T=Self> {} - | ------------------ type parameter `T` must be specified for this + | --------------- type parameter `T` must be specified for this LL | LL | fn f(a: &dyn A) {} | ^ help: set the type parameter to the desired type: `A<T>` diff --git a/src/test/ui/issues/issue-22434.stderr b/src/test/ui/issues/issue-22434.stderr index 79b9d85610b..b97fa2503b8 100644 --- a/src/test/ui/issues/issue-22434.stderr +++ b/src/test/ui/issues/issue-22434.stderr @@ -2,7 +2,7 @@ error[E0191]: the value of the associated type `A` (from trait `Foo`) must be sp --> $DIR/issue-22434.rs:5:23 | LL | type A; - | ------- `A` defined here + | ------ `A` defined here ... LL | type I<'a> = &'a (dyn Foo + 'a); | ^^^ help: specify the associated type: `Foo<A = Type>` diff --git a/src/test/ui/issues/issue-23041.stderr b/src/test/ui/issues/issue-23041.stderr index 401086b2044..7b9a1634a0d 100644 --- a/src/test/ui/issues/issue-23041.stderr +++ b/src/test/ui/issues/issue-23041.stderr @@ -1,8 +1,13 @@ error[E0282]: type annotations needed - --> $DIR/issue-23041.rs:6:22 + --> $DIR/issue-23041.rs:6:7 | LL | b.downcast_ref::<fn(_)->_>(); - | ^^^^^^^^ cannot infer type + | ^^^^^^^^^^^^ cannot infer type of the type parameter `T` declared on the associated function `downcast_ref` + | +help: consider specifying the generic arguments + | +LL | b.downcast_ref::<fn(_) -> _>(); + | ~~~~~~~~~~~~~~ error: aborting due to previous error diff --git a/src/test/ui/issues/issue-23302-3.stderr b/src/test/ui/issues/issue-23302-3.stderr index 1a07d4a95bc..dcb99605da0 100644 --- a/src/test/ui/issues/issue-23302-3.stderr +++ b/src/test/ui/issues/issue-23302-3.stderr @@ -2,19 +2,19 @@ error[E0391]: cycle detected when const-evaluating + checking `A` --> $DIR/issue-23302-3.rs:1:1 | LL | const A: i32 = B; - | ^^^^^^^^^^^^^^^^^ + | ^^^^^^^^^^^^ | note: ...which requires const-evaluating + checking `B`... --> $DIR/issue-23302-3.rs:3:1 | LL | const B: i32 = A; - | ^^^^^^^^^^^^^^^^^ + | ^^^^^^^^^^^^ = note: ...which again requires const-evaluating + checking `A`, completing the cycle note: cycle used when simplifying constant for the type system `A` --> $DIR/issue-23302-3.rs:1:1 | LL | const A: i32 = B; - | ^^^^^^^^^^^^^^^^^ + | ^^^^^^^^^^^^ error: aborting due to previous error diff --git a/src/test/ui/issues/issue-24013.stderr b/src/test/ui/issues/issue-24013.stderr index 4e3cb88297d..863993f4509 100644 --- a/src/test/ui/issues/issue-24013.stderr +++ b/src/test/ui/issues/issue-24013.stderr @@ -1,8 +1,13 @@ error[E0282]: type annotations needed - --> $DIR/issue-24013.rs:5:20 + --> $DIR/issue-24013.rs:5:13 | LL | unsafe {swap::<&mut _>(transmute(&a), transmute(&b))}; - | ^^^^^^ cannot infer type + | ^^^^^^^^^^^^^^ cannot infer type of the type parameter `T` declared on the function `swap` + | +help: consider specifying the generic arguments + | +LL | unsafe {swap::<&mut _>(transmute(&a), transmute(&b))}; + | ~~~~~~~~~~ error: aborting due to previous error diff --git a/src/test/ui/issues/issue-24424.stderr b/src/test/ui/issues/issue-24424.stderr index fa59da852f9..8f3b2ac7319 100644 --- a/src/test/ui/issues/issue-24424.stderr +++ b/src/test/ui/issues/issue-24424.stderr @@ -1,8 +1,8 @@ -error[E0283]: type annotations needed +error[E0283]: type annotations needed: cannot satisfy `T0: Trait0<'l0>` --> $DIR/issue-24424.rs:4:57 | LL | impl <'l0, 'l1, T0> Trait1<'l0, T0> for bool where T0 : Trait0<'l0>, T0 : Trait0<'l1> {} - | ^^^^^^^^^^^ cannot infer type for type parameter `T0` + | ^^^^^^^^^^^ | = note: cannot satisfy `T0: Trait0<'l0>` diff --git a/src/test/ui/issues/issue-25368.rs b/src/test/ui/issues/issue-25368.rs index b7f0f613e80..4be83457f7a 100644 --- a/src/test/ui/issues/issue-25368.rs +++ b/src/test/ui/issues/issue-25368.rs @@ -5,10 +5,10 @@ use std::marker::PhantomData; struct Foo<T> {foo: PhantomData<T>} fn main() { - let (tx, rx) = //~ ERROR type annotations needed + let (tx, rx) = channel(); - // FIXME(#89862): Suggest adding a generic argument to `channel` instead spawn(move || { tx.send(Foo{ foo: PhantomData }); + //~^ ERROR type annotations needed }); } diff --git a/src/test/ui/issues/issue-25368.stderr b/src/test/ui/issues/issue-25368.stderr index ffcb7384952..e6ed3aac710 100644 --- a/src/test/ui/issues/issue-25368.stderr +++ b/src/test/ui/issues/issue-25368.stderr @@ -1,13 +1,13 @@ -error[E0282]: type annotations needed for `(Sender<Foo<T>>, std::sync::mpsc::Receiver<Foo<T>>)` - --> $DIR/issue-25368.rs:8:9 +error[E0282]: type annotations needed + --> $DIR/issue-25368.rs:11:27 | -LL | let (tx, rx) = - | ^^^^^^^^ +LL | tx.send(Foo{ foo: PhantomData }); + | ^^^^^^^^^^^ cannot infer type of the type parameter `T` declared on the struct `PhantomData` | -help: consider giving this pattern a type, where the type for type parameter `T` is specified +help: consider specifying the generic argument | -LL | let (tx, rx): (Sender<Foo<T>>, std::sync::mpsc::Receiver<Foo<T>>) = - | +++++++++++++++++++++++++++++++++++++++++++++++++++++ +LL | tx.send(Foo{ foo: PhantomData::<T> }); + | +++++ error: aborting due to previous error diff --git a/src/test/ui/issues/issue-25901.stderr b/src/test/ui/issues/issue-25901.stderr index 5c35250bc3f..e933745c44e 100644 --- a/src/test/ui/issues/issue-25901.stderr +++ b/src/test/ui/issues/issue-25901.stderr @@ -9,7 +9,7 @@ note: deref defined here --> $DIR/issue-25901.rs:10:5 | LL | type Target = B; - | ^^^^^^^^^^^^^^^^ + | ^^^^^^^^^^^ note: impl defined here, but it is not `const` --> $DIR/issue-25901.rs:9:1 | diff --git a/src/test/ui/issues/issue-2718-a.stderr b/src/test/ui/issues/issue-2718-a.stderr index 4aec27f9684..c6e703f4876 100644 --- a/src/test/ui/issues/issue-2718-a.stderr +++ b/src/test/ui/issues/issue-2718-a.stderr @@ -2,9 +2,8 @@ error[E0072]: recursive type `Pong` has infinite size --> $DIR/issue-2718-a.rs:8:5 | LL | pub struct Pong(SendPacket<Ping>); - | ^^^^^^^^^^^^^^^^----------------^^ - | | | - | | recursive without indirection + | ^^^^^^^^^^^^^^^ ---------------- recursive without indirection + | | | recursive type has infinite size | help: insert some indirection (e.g., a `Box`, `Rc`, or `&`) to make `Pong` representable diff --git a/src/test/ui/issues/issue-33504.stderr b/src/test/ui/issues/issue-33504.stderr index ec15525ed06..d9e7c3b16e7 100644 --- a/src/test/ui/issues/issue-33504.stderr +++ b/src/test/ui/issues/issue-33504.stderr @@ -2,7 +2,7 @@ error[E0308]: mismatched types --> $DIR/issue-33504.rs:7:13 | LL | struct Test; - | ------------ unit struct defined here + | ----------- unit struct defined here ... LL | let Test = 1; | ^^^^ - this expression has type `{integer}` diff --git a/src/test/ui/issues/issue-35241.stderr b/src/test/ui/issues/issue-35241.stderr index 319886f8783..a66289a1cf8 100644 --- a/src/test/ui/issues/issue-35241.stderr +++ b/src/test/ui/issues/issue-35241.stderr @@ -2,7 +2,7 @@ error[E0308]: mismatched types --> $DIR/issue-35241.rs:3:20 | LL | struct Foo(u32); - | ---------------- fn(u32) -> Foo {Foo} defined here + | ---------- fn(u32) -> Foo {Foo} defined here LL | LL | fn test() -> Foo { Foo } | --- ^^^ expected struct `Foo`, found fn item diff --git a/src/test/ui/issues/issue-37515.stderr b/src/test/ui/issues/issue-37515.stderr index c9bb4c10010..f1e83ca74d8 100644 --- a/src/test/ui/issues/issue-37515.stderr +++ b/src/test/ui/issues/issue-37515.stderr @@ -1,8 +1,8 @@ warning: type alias `Z` is never used - --> $DIR/issue-37515.rs:5:1 + --> $DIR/issue-37515.rs:5:6 | LL | type Z = dyn for<'x> Send; - | ^^^^^^^^^^^^^^^^^^^^^^^^^^ + | ^ | note: the lint level is defined here --> $DIR/issue-37515.rs:3:9 diff --git a/src/test/ui/issues/issue-38857.stderr b/src/test/ui/issues/issue-38857.stderr index e9d229f74e8..23090c1ed78 100644 --- a/src/test/ui/issues/issue-38857.stderr +++ b/src/test/ui/issues/issue-38857.stderr @@ -14,7 +14,7 @@ note: the module `sys` is defined here --> $SRC_DIR/std/src/lib.rs:LL:COL | LL | mod sys; - | ^^^^^^^^ + | ^^^^^^^ error: aborting due to 2 previous errors diff --git a/src/test/ui/issues/issue-43355.stderr b/src/test/ui/issues/issue-43355.stderr index 23d8ed1848f..531130fecab 100644 --- a/src/test/ui/issues/issue-43355.stderr +++ b/src/test/ui/issues/issue-43355.stderr @@ -2,7 +2,7 @@ error[E0119]: conflicting implementations of trait `Trait1<std::boxed::Box<_>>` --> $DIR/issue-43355.rs:13:1 | LL | impl<X, T> Trait1<X> for T where T: Trait2<X> { - | --------------------------------------------- first implementation here + | -------------------------- first implementation here ... LL | impl<X> Trait1<Box<X>> for A { | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ conflicting implementation for `A` diff --git a/src/test/ui/issues/issue-46771.stderr b/src/test/ui/issues/issue-46771.stderr index a37b5648959..512827b2dbd 100644 --- a/src/test/ui/issues/issue-46771.stderr +++ b/src/test/ui/issues/issue-46771.stderr @@ -2,7 +2,7 @@ error[E0618]: expected function, found `Foo` --> $DIR/issue-46771.rs:3:23 | LL | struct Foo; - | ----------- `Foo` defined here + | ---------- `Foo` defined here LL | (1 .. 2).find(|_| Foo(0) == 0); | ^^^--- | | diff --git a/src/test/ui/issues/issue-4968.stderr b/src/test/ui/issues/issue-4968.stderr index 57ff7fe09e5..bbaca4ed28f 100644 --- a/src/test/ui/issues/issue-4968.stderr +++ b/src/test/ui/issues/issue-4968.stderr @@ -2,7 +2,7 @@ error[E0308]: mismatched types --> $DIR/issue-4968.rs:5:16 | LL | const A: (isize,isize) = (4,2); - | ------------------------------- constant defined here + | ---------------------- constant defined here LL | fn main() { LL | match 42 { A => () } | -- ^ diff --git a/src/test/ui/issues/issue-51116.rs b/src/test/ui/issues/issue-51116.rs index c979c7b2cdd..4c21cbfc61d 100644 --- a/src/test/ui/issues/issue-51116.rs +++ b/src/test/ui/issues/issue-51116.rs @@ -5,7 +5,6 @@ fn main() { *tile = 0; //~^ ERROR type annotations needed //~| NOTE cannot infer type - //~| NOTE type must be known at this point } } diff --git a/src/test/ui/issues/issue-51116.stderr b/src/test/ui/issues/issue-51116.stderr index 399b421ab16..c07f8735eb2 100644 --- a/src/test/ui/issues/issue-51116.stderr +++ b/src/test/ui/issues/issue-51116.stderr @@ -3,8 +3,6 @@ error[E0282]: type annotations needed | LL | *tile = 0; | ^^^^^ cannot infer type - | - = note: type must be known at this point error: aborting due to previous error diff --git a/src/test/ui/issues/issue-67552.rs b/src/test/ui/issues/issue-67552.rs index 98192dae20d..ec1997ccd5d 100644 --- a/src/test/ui/issues/issue-67552.rs +++ b/src/test/ui/issues/issue-67552.rs @@ -1,4 +1,5 @@ // build-fail +// compile-flags: -Copt-level=0 // normalize-stderr-test: ".nll/" -> "/" fn main() { diff --git a/src/test/ui/issues/issue-67552.stderr b/src/test/ui/issues/issue-67552.stderr index cf05a72e921..2968be7c71f 100644 --- a/src/test/ui/issues/issue-67552.stderr +++ b/src/test/ui/issues/issue-67552.stderr @@ -1,11 +1,11 @@ error: reached the recursion limit while instantiating `rec::<&mut &mut &mut &mut &mut &... &mut &mut &mut &mut &mut Empty>` - --> $DIR/issue-67552.rs:28:9 + --> $DIR/issue-67552.rs:29:9 | LL | rec(identity(&mut it)) | ^^^^^^^^^^^^^^^^^^^^^^ | note: `rec` defined here - --> $DIR/issue-67552.rs:21:1 + --> $DIR/issue-67552.rs:22:1 | LL | / fn rec<T>(mut it: T) LL | | where diff --git a/src/test/ui/issues/issue-69455.stderr b/src/test/ui/issues/issue-69455.stderr index 6c4eafbc8b3..9be6c2f8564 100644 --- a/src/test/ui/issues/issue-69455.stderr +++ b/src/test/ui/issues/issue-69455.stderr @@ -14,7 +14,9 @@ error[E0283]: type annotations needed --> $DIR/issue-69455.rs:29:41 | LL | println!("{}", 23u64.test(xs.iter().sum())); - | ^^^ cannot infer type of the type parameter `S` declared on the associated function `sum` + | ---- ^^^ cannot infer type of the type parameter `S` declared on the associated function `sum` + | | + | type must be known at this point | note: multiple `impl`s satisfying `u64: Test<_>` found --> $DIR/issue-69455.rs:11:1 diff --git a/src/test/ui/issues/issue-69602-type-err-during-codegen-ice.stderr b/src/test/ui/issues/issue-69602-type-err-during-codegen-ice.stderr index cb5b397849c..2c2cd5c5244 100644 --- a/src/test/ui/issues/issue-69602-type-err-during-codegen-ice.stderr +++ b/src/test/ui/issues/issue-69602-type-err-during-codegen-ice.stderr @@ -8,7 +8,7 @@ error[E0046]: not all trait items implemented, missing: `MyA` --> $DIR/issue-69602-type-err-during-codegen-ice.rs:16:1 | LL | type MyA: TraitA; - | ----------------- `MyA` from trait + | ---------------- `MyA` from trait ... LL | impl TraitB for B { | ^^^^^^^^^^^^^^^^^ missing `MyA` in implementation diff --git a/src/test/ui/issues/issue-69683.stderr b/src/test/ui/issues/issue-69683.stderr index 9c71ecffa26..193de1a35cf 100644 --- a/src/test/ui/issues/issue-69683.stderr +++ b/src/test/ui/issues/issue-69683.stderr @@ -1,8 +1,14 @@ -error[E0284]: type annotations needed: cannot satisfy `<u8 as Element<_>>::Array == [u8; 3]` +error[E0284]: type annotations needed --> $DIR/issue-69683.rs:30:10 | LL | 0u16.foo(b); - | ^^^ cannot satisfy `<u8 as Element<_>>::Array == [u8; 3]` + | ^^^ + | + = note: cannot satisfy `<u8 as Element<_>>::Array == [u8; 3]` +help: try using a fully qualified path to specify the expected types + | +LL | <u16 as Foo<I>>::foo(0u16, b); + | +++++++++++++++++++++ ~ error[E0283]: type annotations needed --> $DIR/issue-69683.rs:30:10 diff --git a/src/test/ui/issues/issue-71584.stderr b/src/test/ui/issues/issue-71584.stderr index 1c216e64982..6ddb7657301 100644 --- a/src/test/ui/issues/issue-71584.stderr +++ b/src/test/ui/issues/issue-71584.stderr @@ -1,8 +1,16 @@ -error[E0284]: type annotations needed: cannot satisfy `<u64 as Rem<_>>::Output == u64` - --> $DIR/issue-71584.rs:4:11 +error[E0284]: type annotations needed + --> $DIR/issue-71584.rs:4:15 | LL | d = d % n.into(); - | ^ cannot satisfy `<u64 as Rem<_>>::Output == u64` + | - ^^^^ + | | + | type must be known at this point + | + = note: cannot satisfy `<u64 as Rem<_>>::Output == u64` +help: try using a fully qualified path to specify the expected types + | +LL | d = d % <u32 as Into<T>>::into(n); + | +++++++++++++++++++++++ ~ error: aborting due to previous error diff --git a/src/test/ui/issues/issue-73112.stderr b/src/test/ui/issues/issue-73112.stderr index 5a548378c26..4b8b979665c 100644 --- a/src/test/ui/issues/issue-73112.stderr +++ b/src/test/ui/issues/issue-73112.stderr @@ -1,19 +1,14 @@ error[E0588]: packed type cannot transitively contain a `#[repr(align)]` type --> $DIR/issue-73112.rs:9:5 | -LL | / struct SomeStruct { -LL | | -LL | | page_table: PageTable, -LL | | } - | |_____^ +LL | struct SomeStruct { + | ^^^^^^^^^^^^^^^^^ | note: `PageTable` has a `#[repr(align)]` attribute --> $DIR/auxiliary/issue-73112.rs:8:1 | -LL | / pub struct PageTable { -LL | | entries: [PageTableEntry; 512], -LL | | } - | |_^ +LL | pub struct PageTable { + | ^^^^^^^^^^^^^^^^^^^^ error: aborting due to previous error diff --git a/src/test/ui/issues/issue-76191.stderr b/src/test/ui/issues/issue-76191.stderr index fb8ed43674f..13749804796 100644 --- a/src/test/ui/issues/issue-76191.stderr +++ b/src/test/ui/issues/issue-76191.stderr @@ -2,7 +2,7 @@ error[E0308]: mismatched types --> $DIR/issue-76191.rs:13:9 | LL | const RANGE: RangeInclusive<i32> = 0..=255; - | ------------------------------------------- constant defined here + | -------------------------------- constant defined here ... LL | match n { | - this expression has type `i32` @@ -23,7 +23,7 @@ error[E0308]: mismatched types --> $DIR/issue-76191.rs:15:9 | LL | const RANGE2: RangeInclusive<i32> = panic!(); - | --------------------------------------------- constant defined here + | --------------------------------- constant defined here ... LL | match n { | - this expression has type `i32` diff --git a/src/test/ui/issues/issue-77919.stderr b/src/test/ui/issues/issue-77919.stderr index c986e47fb55..a55ac23e3ed 100644 --- a/src/test/ui/issues/issue-77919.stderr +++ b/src/test/ui/issues/issue-77919.stderr @@ -21,7 +21,7 @@ error[E0046]: not all trait items implemented, missing: `VAL` --> $DIR/issue-77919.rs:12:1 | LL | const VAL: T; - | ------------- `VAL` from trait + | ------------ `VAL` from trait ... LL | impl<N, M> TypeVal<usize> for Multiply<N, M> where N: TypeVal<VAL> {} | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ missing `VAL` in implementation diff --git a/src/test/ui/issues/issue-7813.stderr b/src/test/ui/issues/issue-7813.stderr index 3aee61bd5a5..2a747f679a8 100644 --- a/src/test/ui/issues/issue-7813.stderr +++ b/src/test/ui/issues/issue-7813.stderr @@ -2,7 +2,7 @@ error[E0282]: type annotations needed for `&[_; 0]` --> $DIR/issue-7813.rs:2:9 | LL | let v = &[]; - | ^ + | ^ --- type must be known at this point | help: consider giving `v` an explicit type, where the placeholders `_` are specified | diff --git a/src/test/ui/keyword/keyword-self-as-type-param.stderr b/src/test/ui/keyword/keyword-self-as-type-param.stderr index fd101b32b4c..419652e1349 100644 --- a/src/test/ui/keyword/keyword-self-as-type-param.stderr +++ b/src/test/ui/keyword/keyword-self-as-type-param.stderr @@ -18,9 +18,8 @@ error[E0072]: recursive type `Foo` has infinite size --> $DIR/keyword-self-as-type-param.rs:3:1 | LL | struct Foo<Self>(Self); - | ^^^^^^^^^^^^^^^^^----^^ - | | | - | | recursive without indirection + | ^^^^^^^^^^^^^^^^ ---- recursive without indirection + | | | recursive type has infinite size | help: insert some indirection (e.g., a `Box`, `Rc`, or `&`) to make `Foo` representable diff --git a/src/test/ui/layout/debug.stderr b/src/test/ui/layout/debug.stderr index 7dbcc151855..7ba9657fcd6 100644 --- a/src/test/ui/layout/debug.stderr +++ b/src/test/ui/layout/debug.stderr @@ -84,7 +84,7 @@ error: layout_of(E) = Layout { --> $DIR/debug.rs:6:1 | LL | enum E { Foo, Bar(!, i32, i32) } - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | ^^^^^^ error: layout_of(S) = Layout { fields: Arbitrary { @@ -128,7 +128,7 @@ error: layout_of(S) = Layout { --> $DIR/debug.rs:9:1 | LL | struct S { f1: i32, f2: (), f3: i32 } - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | ^^^^^^^^ error: layout_of(U) = Layout { fields: Union( @@ -150,7 +150,7 @@ error: layout_of(U) = Layout { --> $DIR/debug.rs:12:1 | LL | union U { f1: (i32, i32), f3: i32 } - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | ^^^^^^^ error: layout_of(std::result::Result<i32, i32>) = Layout { fields: Arbitrary { @@ -279,7 +279,7 @@ error: layout_of(std::result::Result<i32, i32>) = Layout { --> $DIR/debug.rs:15:1 | LL | type Test = Result<i32, i32>; - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | ^^^^^^^^^ error: layout_of(i32) = Layout { fields: Primitive, @@ -305,7 +305,7 @@ error: layout_of(i32) = Layout { --> $DIR/debug.rs:18:1 | LL | type T = impl std::fmt::Debug; - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | ^^^^^^ error: aborting due to 5 previous errors diff --git a/src/test/ui/layout/hexagon-enum.stderr b/src/test/ui/layout/hexagon-enum.stderr index ba919df771f..f3123cb0ad2 100644 --- a/src/test/ui/layout/hexagon-enum.stderr +++ b/src/test/ui/layout/hexagon-enum.stderr @@ -66,7 +66,7 @@ error: layout_of(A) = Layout { --> $DIR/hexagon-enum.rs:16:1 | LL | enum A { Apple } - | ^^^^^^^^^^^^^^^^ + | ^^^^^^ error: layout_of(B) = Layout { fields: Arbitrary { @@ -136,7 +136,7 @@ error: layout_of(B) = Layout { --> $DIR/hexagon-enum.rs:20:1 | LL | enum B { Banana = 255, } - | ^^^^^^^^^^^^^^^^^^^^^^^^ + | ^^^^^^ error: layout_of(C) = Layout { fields: Arbitrary { @@ -206,7 +206,7 @@ error: layout_of(C) = Layout { --> $DIR/hexagon-enum.rs:24:1 | LL | enum C { Chaenomeles = 256, } - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | ^^^^^^ error: layout_of(P) = Layout { fields: Arbitrary { @@ -276,7 +276,7 @@ error: layout_of(P) = Layout { --> $DIR/hexagon-enum.rs:28:1 | LL | enum P { Peach = 0x1000_0000isize, } - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | ^^^^^^ error: layout_of(T) = Layout { fields: Arbitrary { @@ -346,7 +346,7 @@ error: layout_of(T) = Layout { --> $DIR/hexagon-enum.rs:34:1 | LL | enum T { Tangerine = TANGERINE as isize } - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | ^^^^^^ error: aborting due to 5 previous errors diff --git a/src/test/ui/layout/homogeneous-aggr-zero-sized-c-struct.stderr b/src/test/ui/layout/homogeneous-aggr-zero-sized-c-struct.stderr index 6c97a09b0c6..e19216a99db 100644 --- a/src/test/ui/layout/homogeneous-aggr-zero-sized-c-struct.stderr +++ b/src/test/ui/layout/homogeneous-aggr-zero-sized-c-struct.stderr @@ -2,13 +2,13 @@ error: homogeneous_aggregate: Ok(Homogeneous(Reg { kind: Float, size: Size(4 byt --> $DIR/homogeneous-aggr-zero-sized-c-struct.rs:22:1 | LL | pub type TestMiddle = Middle; - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | ^^^^^^^^^^^^^^^^^^^ error: homogeneous_aggregate: Ok(Homogeneous(Reg { kind: Float, size: Size(4 bytes) })) --> $DIR/homogeneous-aggr-zero-sized-c-struct.rs:33:1 | LL | pub type TestFinal = Final; - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | ^^^^^^^^^^^^^^^^^^ error: aborting due to 2 previous errors diff --git a/src/test/ui/layout/homogeneous-aggr-zero-sized-repr-rust.stderr b/src/test/ui/layout/homogeneous-aggr-zero-sized-repr-rust.stderr index 322948ff783..17d639da024 100644 --- a/src/test/ui/layout/homogeneous-aggr-zero-sized-repr-rust.stderr +++ b/src/test/ui/layout/homogeneous-aggr-zero-sized-repr-rust.stderr @@ -2,31 +2,31 @@ error: homogeneous_aggregate: Ok(Homogeneous(Reg { kind: Float, size: Size(4 byt --> $DIR/homogeneous-aggr-zero-sized-repr-rust.rs:53:1 | LL | pub type Test1 = BaseCase; - | ^^^^^^^^^^^^^^^^^^^^^^^^^^ + | ^^^^^^^^^^^^^^ error: homogeneous_aggregate: Ok(Homogeneous(Reg { kind: Float, size: Size(4 bytes) })) --> $DIR/homogeneous-aggr-zero-sized-repr-rust.rs:57:1 | LL | pub type Test2 = WithPhantomData; - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | ^^^^^^^^^^^^^^ error: homogeneous_aggregate: Ok(Homogeneous(Reg { kind: Float, size: Size(4 bytes) })) --> $DIR/homogeneous-aggr-zero-sized-repr-rust.rs:61:1 | LL | pub type Test3 = WithEmptyRustStruct; - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | ^^^^^^^^^^^^^^ error: homogeneous_aggregate: Ok(Homogeneous(Reg { kind: Float, size: Size(4 bytes) })) --> $DIR/homogeneous-aggr-zero-sized-repr-rust.rs:65:1 | LL | pub type Test4 = WithTransitivelyEmptyRustStruct; - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | ^^^^^^^^^^^^^^ error: homogeneous_aggregate: Ok(Homogeneous(Reg { kind: Float, size: Size(4 bytes) })) --> $DIR/homogeneous-aggr-zero-sized-repr-rust.rs:69:1 | LL | pub type Test5 = WithEmptyRustEnum; - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | ^^^^^^^^^^^^^^ error: aborting due to 5 previous errors diff --git a/src/test/ui/layout/issue-96158-scalarpair-payload-might-be-uninit.stderr b/src/test/ui/layout/issue-96158-scalarpair-payload-might-be-uninit.stderr index 33dfa307c1d..84d8bc799b9 100644 --- a/src/test/ui/layout/issue-96158-scalarpair-payload-might-be-uninit.stderr +++ b/src/test/ui/layout/issue-96158-scalarpair-payload-might-be-uninit.stderr @@ -105,11 +105,8 @@ error: layout_of(MissingPayloadField) = Layout { } --> $DIR/issue-96158-scalarpair-payload-might-be-uninit.rs:16:1 | -LL | / pub enum MissingPayloadField { -LL | | Some(u8), -LL | | None -LL | | } - | |_^ +LL | pub enum MissingPayloadField { + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ error: layout_of(CommonPayloadField) = Layout { fields: Arbitrary { @@ -237,11 +234,8 @@ error: layout_of(CommonPayloadField) = Layout { } --> $DIR/issue-96158-scalarpair-payload-might-be-uninit.rs:25:1 | -LL | / pub enum CommonPayloadField { -LL | | A(u8), -LL | | B(u8), -LL | | } - | |_^ +LL | pub enum CommonPayloadField { + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^ error: layout_of(CommonPayloadFieldIsMaybeUninit) = Layout { fields: Arbitrary { @@ -366,11 +360,8 @@ error: layout_of(CommonPayloadFieldIsMaybeUninit) = Layout { } --> $DIR/issue-96158-scalarpair-payload-might-be-uninit.rs:33:1 | -LL | / pub enum CommonPayloadFieldIsMaybeUninit { -LL | | A(u8), -LL | | B(MaybeUninit<u8>), -LL | | } - | |_^ +LL | pub enum CommonPayloadFieldIsMaybeUninit { + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ error: layout_of(NicheFirst) = Layout { fields: Arbitrary { @@ -513,12 +504,8 @@ error: layout_of(NicheFirst) = Layout { } --> $DIR/issue-96158-scalarpair-payload-might-be-uninit.rs:41:1 | -LL | / pub enum NicheFirst { -LL | | A(HasNiche, u8), -LL | | B, -LL | | C -LL | | } - | |_^ +LL | pub enum NicheFirst { + | ^^^^^^^^^^^^^^^^^^^ error: layout_of(NicheSecond) = Layout { fields: Arbitrary { @@ -661,12 +648,8 @@ error: layout_of(NicheSecond) = Layout { } --> $DIR/issue-96158-scalarpair-payload-might-be-uninit.rs:50:1 | -LL | / pub enum NicheSecond { -LL | | A(u8, HasNiche), -LL | | B, -LL | | C, -LL | | } - | |_^ +LL | pub enum NicheSecond { + | ^^^^^^^^^^^^^^^^^^^^ error: aborting due to 5 previous errors diff --git a/src/test/ui/layout/issue-96185-overaligned-enum.rs b/src/test/ui/layout/issue-96185-overaligned-enum.rs new file mode 100644 index 00000000000..ae1e6b012c3 --- /dev/null +++ b/src/test/ui/layout/issue-96185-overaligned-enum.rs @@ -0,0 +1,19 @@ +// normalize-stderr-test "pref: Align\([1-8] bytes\)" -> "pref: $$PREF_ALIGN" +#![crate_type = "lib"] +#![feature(rustc_attrs)] + +// This cannot use `Scalar` abi since there is padding. +#[rustc_layout(debug)] +#[repr(align(8))] +pub enum Aligned1 { //~ ERROR: layout_of + Zero = 0, + One = 1, +} + +// This should use `Scalar` abi. +#[rustc_layout(debug)] +#[repr(align(1))] +pub enum Aligned2 { //~ ERROR: layout_of + Zero = 0, + One = 1, +} diff --git a/src/test/ui/layout/issue-96185-overaligned-enum.stderr b/src/test/ui/layout/issue-96185-overaligned-enum.stderr new file mode 100644 index 00000000000..8dc364fa7c9 --- /dev/null +++ b/src/test/ui/layout/issue-96185-overaligned-enum.stderr @@ -0,0 +1,172 @@ +error: layout_of(Aligned1) = Layout { + fields: Arbitrary { + offsets: [ + Size(0 bytes), + ], + memory_index: [ + 0, + ], + }, + variants: Multiple { + tag: Initialized { + value: Int( + I8, + false, + ), + valid_range: 0..=1, + }, + tag_encoding: Direct, + tag_field: 0, + variants: [ + Layout { + fields: Arbitrary { + offsets: [], + memory_index: [], + }, + variants: Single { + index: 0, + }, + abi: Aggregate { + sized: true, + }, + largest_niche: None, + align: AbiAndPrefAlign { + abi: Align(8 bytes), + pref: $PREF_ALIGN, + }, + size: Size(8 bytes), + }, + Layout { + fields: Arbitrary { + offsets: [], + memory_index: [], + }, + variants: Single { + index: 1, + }, + abi: Aggregate { + sized: true, + }, + largest_niche: None, + align: AbiAndPrefAlign { + abi: Align(8 bytes), + pref: $PREF_ALIGN, + }, + size: Size(8 bytes), + }, + ], + }, + abi: Aggregate { + sized: true, + }, + largest_niche: Some( + Niche { + offset: Size(0 bytes), + value: Int( + I8, + false, + ), + valid_range: 0..=1, + }, + ), + align: AbiAndPrefAlign { + abi: Align(8 bytes), + pref: $PREF_ALIGN, + }, + size: Size(8 bytes), + } + --> $DIR/issue-96185-overaligned-enum.rs:8:1 + | +LL | pub enum Aligned1 { + | ^^^^^^^^^^^^^^^^^ + +error: layout_of(Aligned2) = Layout { + fields: Arbitrary { + offsets: [ + Size(0 bytes), + ], + memory_index: [ + 0, + ], + }, + variants: Multiple { + tag: Initialized { + value: Int( + I8, + false, + ), + valid_range: 0..=1, + }, + tag_encoding: Direct, + tag_field: 0, + variants: [ + Layout { + fields: Arbitrary { + offsets: [], + memory_index: [], + }, + variants: Single { + index: 0, + }, + abi: Aggregate { + sized: true, + }, + largest_niche: None, + align: AbiAndPrefAlign { + abi: Align(1 bytes), + pref: $PREF_ALIGN, + }, + size: Size(1 bytes), + }, + Layout { + fields: Arbitrary { + offsets: [], + memory_index: [], + }, + variants: Single { + index: 1, + }, + abi: Aggregate { + sized: true, + }, + largest_niche: None, + align: AbiAndPrefAlign { + abi: Align(1 bytes), + pref: $PREF_ALIGN, + }, + size: Size(1 bytes), + }, + ], + }, + abi: Scalar( + Initialized { + value: Int( + I8, + false, + ), + valid_range: 0..=1, + }, + ), + largest_niche: Some( + Niche { + offset: Size(0 bytes), + value: Int( + I8, + false, + ), + valid_range: 0..=1, + }, + ), + align: AbiAndPrefAlign { + abi: Align(1 bytes), + pref: $PREF_ALIGN, + }, + size: Size(1 bytes), + } + --> $DIR/issue-96185-overaligned-enum.rs:16:1 + | +LL | pub enum Aligned2 { + | ^^^^^^^^^^^^^^^^^ + +error: aborting due to 2 previous errors + diff --git a/src/test/ui/layout/thumb-enum.stderr b/src/test/ui/layout/thumb-enum.stderr index 9db9ad5a784..e6ed626d5f1 100644 --- a/src/test/ui/layout/thumb-enum.stderr +++ b/src/test/ui/layout/thumb-enum.stderr @@ -66,7 +66,7 @@ error: layout_of(A) = Layout { --> $DIR/thumb-enum.rs:16:1 | LL | enum A { Apple } - | ^^^^^^^^^^^^^^^^ + | ^^^^^^ error: layout_of(B) = Layout { fields: Arbitrary { @@ -136,7 +136,7 @@ error: layout_of(B) = Layout { --> $DIR/thumb-enum.rs:20:1 | LL | enum B { Banana = 255, } - | ^^^^^^^^^^^^^^^^^^^^^^^^ + | ^^^^^^ error: layout_of(C) = Layout { fields: Arbitrary { @@ -206,7 +206,7 @@ error: layout_of(C) = Layout { --> $DIR/thumb-enum.rs:24:1 | LL | enum C { Chaenomeles = 256, } - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | ^^^^^^ error: layout_of(P) = Layout { fields: Arbitrary { @@ -276,7 +276,7 @@ error: layout_of(P) = Layout { --> $DIR/thumb-enum.rs:28:1 | LL | enum P { Peach = 0x1000_0000isize, } - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | ^^^^^^ error: layout_of(T) = Layout { fields: Arbitrary { @@ -346,7 +346,7 @@ error: layout_of(T) = Layout { --> $DIR/thumb-enum.rs:34:1 | LL | enum T { Tangerine = TANGERINE as isize } - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | ^^^^^^ error: aborting due to 5 previous errors diff --git a/src/test/ui/layout/zero-sized-array-union.stderr b/src/test/ui/layout/zero-sized-array-union.stderr index 8faf8593294..de2b863e4ca 100644 --- a/src/test/ui/layout/zero-sized-array-union.stderr +++ b/src/test/ui/layout/zero-sized-array-union.stderr @@ -2,25 +2,25 @@ error: homogeneous_aggregate: Ok(Homogeneous(Reg { kind: Float, size: Size(4 byt --> $DIR/zero-sized-array-union.rs:59:1 | LL | type TestBaz1 = Baz1; - | ^^^^^^^^^^^^^^^^^^^^^ + | ^^^^^^^^^^^^^ error: homogeneous_aggregate: Ok(Homogeneous(Reg { kind: Float, size: Size(4 bytes) })) --> $DIR/zero-sized-array-union.rs:70:1 | LL | type TestBaz2 = Baz2; - | ^^^^^^^^^^^^^^^^^^^^^ + | ^^^^^^^^^^^^^ error: homogeneous_aggregate: Ok(Homogeneous(Reg { kind: Float, size: Size(4 bytes) })) --> $DIR/zero-sized-array-union.rs:81:1 | LL | type TestBaz3 = Baz3; - | ^^^^^^^^^^^^^^^^^^^^^ + | ^^^^^^^^^^^^^ error: homogeneous_aggregate: Ok(Homogeneous(Reg { kind: Float, size: Size(4 bytes) })) --> $DIR/zero-sized-array-union.rs:92:1 | LL | type TestBaz4 = Baz4; - | ^^^^^^^^^^^^^^^^^^^^^ + | ^^^^^^^^^^^^^ error: aborting due to 4 previous errors diff --git a/src/test/ui/lazy-type-alias-impl-trait/branches3.stderr b/src/test/ui/lazy-type-alias-impl-trait/branches3.stderr index 77ce1d48480..420104e526d 100644 --- a/src/test/ui/lazy-type-alias-impl-trait/branches3.stderr +++ b/src/test/ui/lazy-type-alias-impl-trait/branches3.stderr @@ -2,9 +2,8 @@ error[E0282]: type annotations needed --> $DIR/branches3.rs:8:10 | LL | |s| s.len() - | ^ + | ^ - type must be known at this point | - = note: type must be known at this point help: consider giving this closure parameter an explicit type | LL | |s: _| s.len() @@ -14,9 +13,8 @@ error[E0282]: type annotations needed --> $DIR/branches3.rs:15:10 | LL | |s| s.len() - | ^ + | ^ - type must be known at this point | - = note: type must be known at this point help: consider giving this closure parameter an explicit type | LL | |s: _| s.len() @@ -26,9 +24,8 @@ error[E0282]: type annotations needed --> $DIR/branches3.rs:23:10 | LL | |s| s.len() - | ^ + | ^ - type must be known at this point | - = note: type must be known at this point help: consider giving this closure parameter an explicit type | LL | |s: _| s.len() @@ -38,9 +35,8 @@ error[E0282]: type annotations needed --> $DIR/branches3.rs:30:10 | LL | |s| s.len() - | ^ + | ^ - type must be known at this point | - = note: type must be known at this point help: consider giving this closure parameter an explicit type | LL | |s: _| s.len() diff --git a/src/test/ui/lifetimes/issue-34979.stderr b/src/test/ui/lifetimes/issue-34979.stderr index 1b97f8d818a..5832c4d173c 100644 --- a/src/test/ui/lifetimes/issue-34979.stderr +++ b/src/test/ui/lifetimes/issue-34979.stderr @@ -1,8 +1,8 @@ -error[E0283]: type annotations needed +error[E0283]: type annotations needed: cannot satisfy `&'a (): Foo` --> $DIR/issue-34979.rs:6:13 | LL | &'a (): Foo, - | ^^^ cannot infer type for reference `&'a ()` + | ^^^ | = note: cannot satisfy `&'a (): Foo` diff --git a/src/test/ui/limits/issue-56762.stderr b/src/test/ui/limits/issue-56762.stderr index f26ef280b20..e6b9c676278 100644 --- a/src/test/ui/limits/issue-56762.stderr +++ b/src/test/ui/limits/issue-56762.stderr @@ -2,13 +2,13 @@ error[E0080]: values of the type `[u8; 2305843009213693951]` are too big for the --> $DIR/issue-56762.rs:19:1 | LL | static MY_TOO_BIG_ARRAY_1: TooBigArray = TooBigArray::new(); - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ error[E0080]: values of the type `[u8; 2305843009213693951]` are too big for the current architecture --> $DIR/issue-56762.rs:21:1 | LL | static MY_TOO_BIG_ARRAY_2: [u8; HUGE_SIZE] = [0x00; HUGE_SIZE]; - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ error: aborting due to 2 previous errors diff --git a/src/test/ui/linkage-attr/linkage-detect-extern-generated-name-collision.stderr b/src/test/ui/linkage-attr/linkage-detect-extern-generated-name-collision.stderr index dcb954a4bc0..06a07082263 100644 --- a/src/test/ui/linkage-attr/linkage-detect-extern-generated-name-collision.stderr +++ b/src/test/ui/linkage-attr/linkage-detect-extern-generated-name-collision.stderr @@ -2,7 +2,7 @@ error: symbol `collision` is already defined --> $DIR/auxiliary/def_colliding_external.rs:6:5 | LL | pub static collision: *const i32; - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ error: aborting due to previous error diff --git a/src/test/ui/linkage-attr/linkage-detect-local-generated-name-collision.stderr b/src/test/ui/linkage-attr/linkage-detect-local-generated-name-collision.stderr index 7e395e67378..e0be1ac2117 100644 --- a/src/test/ui/linkage-attr/linkage-detect-local-generated-name-collision.stderr +++ b/src/test/ui/linkage-attr/linkage-detect-local-generated-name-collision.stderr @@ -2,7 +2,7 @@ error: symbol `collision` is already defined --> $DIR/linkage-detect-local-generated-name-collision.rs:10:9 | LL | pub static collision: *const i32; - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ error: aborting due to previous error diff --git a/src/test/ui/linkage-attr/linkage-requires-raw-ptr.stderr b/src/test/ui/linkage-attr/linkage-requires-raw-ptr.stderr index a80b495f97f..5abbe745c6a 100644 --- a/src/test/ui/linkage-attr/linkage-requires-raw-ptr.stderr +++ b/src/test/ui/linkage-attr/linkage-requires-raw-ptr.stderr @@ -2,7 +2,7 @@ error: must have type `*const T` or `*mut T` due to `#[linkage]` attribute --> $DIR/auxiliary/def_illtyped_external.rs:5:1 | LL | pub static EXTERN: u32 = 0; - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | ^^^^^^^^^^^^^^^^^^^^^^ error: aborting due to previous error diff --git a/src/test/ui/linkage-attr/linkage2.stderr b/src/test/ui/linkage-attr/linkage2.stderr index 6ffe07170ed..a6ac0aad077 100644 --- a/src/test/ui/linkage-attr/linkage2.stderr +++ b/src/test/ui/linkage-attr/linkage2.stderr @@ -2,7 +2,7 @@ error: must have type `*const T` or `*mut T` due to `#[linkage]` attribute --> $DIR/linkage2.rs:12:5 | LL | static foo: i32; - | ^^^^^^^^^^^^^^^^ + | ^^^^^^^^^^^^^^^ error: aborting due to previous error diff --git a/src/test/ui/linkage-attr/linkage3.stderr b/src/test/ui/linkage-attr/linkage3.stderr index 0cbac28349d..f2579c6e850 100644 --- a/src/test/ui/linkage-attr/linkage3.stderr +++ b/src/test/ui/linkage-attr/linkage3.stderr @@ -2,7 +2,7 @@ error: invalid linkage specified --> $DIR/linkage3.rs:11:5 | LL | static foo: *const i32; - | ^^^^^^^^^^^^^^^^^^^^^^^ + | ^^^^^^^^^^^^^^^^^^^^^^ error: aborting due to previous error diff --git a/src/test/ui/lint/dead-code/impl-trait.stderr b/src/test/ui/lint/dead-code/impl-trait.stderr index 9c47c1b5355..e35e13a9ec6 100644 --- a/src/test/ui/lint/dead-code/impl-trait.stderr +++ b/src/test/ui/lint/dead-code/impl-trait.stderr @@ -1,8 +1,8 @@ error: type alias `Unused` is never used - --> $DIR/impl-trait.rs:12:1 + --> $DIR/impl-trait.rs:12:6 | LL | type Unused = (); - | ^^^^^^^^^^^^^^^^^ + | ^^^^^^ | note: the lint level is defined here --> $DIR/impl-trait.rs:1:9 diff --git a/src/test/ui/lint/dead-code/issue-85255.stderr b/src/test/ui/lint/dead-code/issue-85255.stderr index 7ebbebb1aba..3497b952fdd 100644 --- a/src/test/ui/lint/dead-code/issue-85255.stderr +++ b/src/test/ui/lint/dead-code/issue-85255.stderr @@ -4,9 +4,9 @@ warning: fields `a` and `b` are never read LL | struct Foo { | --- fields in this struct LL | a: i32, - | ^^^^^^ + | ^ LL | pub b: i32, - | ^^^^^^^^^^ + | ^ | note: the lint level is defined here --> $DIR/issue-85255.rs:4:9 @@ -14,6 +14,26 @@ note: the lint level is defined here LL | #![warn(dead_code)] | ^^^^^^^^^ +warning: fields `a` and `b` are never read + --> $DIR/issue-85255.rs:19:5 + | +LL | pub(crate) struct Foo1 { + | ---- fields in this struct +LL | a: i32, + | ^ +LL | pub b: i32, + | ^ + +warning: fields `a` and `b` are never read + --> $DIR/issue-85255.rs:31:5 + | +LL | pub(crate) struct Foo2 { + | ---- fields in this struct +LL | a: i32, + | ^ +LL | pub b: i32, + | ^ + warning: associated function `a` is never used --> $DIR/issue-85255.rs:14:8 | @@ -26,16 +46,6 @@ warning: associated function `b` is never used LL | pub fn b(&self) -> i32 { 6 } | ^ -warning: fields `a` and `b` are never read - --> $DIR/issue-85255.rs:19:5 - | -LL | pub(crate) struct Foo1 { - | ---- fields in this struct -LL | a: i32, - | ^^^^^^ -LL | pub b: i32, - | ^^^^^^^^^^ - warning: associated function `a` is never used --> $DIR/issue-85255.rs:26:8 | @@ -48,16 +58,6 @@ warning: associated function `b` is never used LL | pub fn b(&self) -> i32 { 6 } | ^ -warning: fields `a` and `b` are never read - --> $DIR/issue-85255.rs:31:5 - | -LL | pub(crate) struct Foo2 { - | ---- fields in this struct -LL | a: i32, - | ^^^^^^ -LL | pub b: i32, - | ^^^^^^^^^^ - warning: associated function `a` is never used --> $DIR/issue-85255.rs:38:8 | diff --git a/src/test/ui/lint/dead-code/lint-dead-code-1.stderr b/src/test/ui/lint/dead-code/lint-dead-code-1.stderr index 2eddc4ce21c..eb728b5b930 100644 --- a/src/test/ui/lint/dead-code/lint-dead-code-1.stderr +++ b/src/test/ui/lint/dead-code/lint-dead-code-1.stderr @@ -1,8 +1,8 @@ error: static `priv_static` is never used - --> $DIR/lint-dead-code-1.rs:20:1 + --> $DIR/lint-dead-code-1.rs:20:8 | LL | static priv_static: isize = 0; - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | ^^^^^^^^^^^ | note: the lint level is defined here --> $DIR/lint-dead-code-1.rs:5:9 @@ -11,10 +11,10 @@ LL | #![deny(dead_code)] | ^^^^^^^^^ error: constant `priv_const` is never used - --> $DIR/lint-dead-code-1.rs:27:1 + --> $DIR/lint-dead-code-1.rs:27:7 | LL | const priv_const: isize = 0; - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | ^^^^^^^^^^ error: struct `PrivStruct` is never constructed --> $DIR/lint-dead-code-1.rs:35:8 diff --git a/src/test/ui/lint/dead-code/lint-dead-code-3.rs b/src/test/ui/lint/dead-code/lint-dead-code-3.rs index c3e56063dc3..293fcdbc5ee 100644 --- a/src/test/ui/lint/dead-code/lint-dead-code-3.rs +++ b/src/test/ui/lint/dead-code/lint-dead-code-3.rs @@ -73,7 +73,18 @@ mod inner { fn f() {} } +fn anon_const() -> [(); { + fn blah() {} //~ ERROR: function `blah` is never used + 1 +}] { + [(); { + fn blah() {} //~ ERROR: function `blah` is never used + 1 + }] +} + pub fn foo() { let a: &dyn inner::Trait = &1_isize; a.f(); + anon_const(); } diff --git a/src/test/ui/lint/dead-code/lint-dead-code-3.stderr b/src/test/ui/lint/dead-code/lint-dead-code-3.stderr index af59c6fec1f..26fc13bae08 100644 --- a/src/test/ui/lint/dead-code/lint-dead-code-3.stderr +++ b/src/test/ui/lint/dead-code/lint-dead-code-3.stderr @@ -10,12 +10,6 @@ note: the lint level is defined here LL | #![deny(dead_code)] | ^^^^^^^^^ -error: associated function `foo` is never used - --> $DIR/lint-dead-code-3.rs:16:8 - | -LL | fn foo(&self) { - | ^^^ - error: function `bar` is never used --> $DIR/lint-dead-code-3.rs:21:4 | @@ -28,11 +22,29 @@ error: enum `c_void` is never used LL | enum c_void {} | ^^^^^^ +error: function `blah` is never used + --> $DIR/lint-dead-code-3.rs:77:8 + | +LL | fn blah() {} + | ^^^^ + +error: function `blah` is never used + --> $DIR/lint-dead-code-3.rs:81:12 + | +LL | fn blah() {} + | ^^^^ + +error: associated function `foo` is never used + --> $DIR/lint-dead-code-3.rs:16:8 + | +LL | fn foo(&self) { + | ^^^ + error: function `free` is never used - --> $DIR/lint-dead-code-3.rs:62:5 + --> $DIR/lint-dead-code-3.rs:62:8 | LL | fn free(p: *const c_void); - | ^^^^^^^^^^^^^^^^^^^^^^^^^^ + | ^^^^ -error: aborting due to 5 previous errors +error: aborting due to 7 previous errors diff --git a/src/test/ui/lint/dead-code/lint-dead-code-4.stderr b/src/test/ui/lint/dead-code/lint-dead-code-4.stderr index dcd810b3e48..668c1dacf95 100644 --- a/src/test/ui/lint/dead-code/lint-dead-code-4.stderr +++ b/src/test/ui/lint/dead-code/lint-dead-code-4.stderr @@ -5,7 +5,7 @@ LL | struct Foo { | --- field in this struct LL | x: usize, LL | b: bool, - | ^^^^^^^ + | ^ | note: the lint level is defined here --> $DIR/lint-dead-code-4.rs:3:9 @@ -16,16 +16,12 @@ LL | #![deny(dead_code)] error: variants `X` and `Y` are never constructed --> $DIR/lint-dead-code-4.rs:15:5 | -LL | enum XYZ { - | --- variants in this enum -LL | X, - | ^ -LL | / Y { -LL | | a: String, -LL | | b: i32, -LL | | c: i32, -LL | | }, - | |_____^ +LL | enum XYZ { + | --- variants in this enum +LL | X, + | ^ +LL | Y { + | ^ error: enum `ABC` is never used --> $DIR/lint-dead-code-4.rs:24:6 @@ -36,13 +32,13 @@ LL | enum ABC { error: fields `b` and `c` are never read --> $DIR/lint-dead-code-4.rs:39:9 | -LL | enum IJK { - | --- fields in this enum -... +LL | J { + | - fields in this variant +LL | a: String, LL | b: i32, - | ^^^^^^ + | ^ LL | c: i32, - | ^^^^^^ + | ^ error: variants `I` and `K` are never constructed --> $DIR/lint-dead-code-4.rs:36:5 @@ -61,10 +57,10 @@ error: fields `x` and `c` are never read LL | struct Bar { | --- fields in this struct LL | x: usize, - | ^^^^^^^^ + | ^ LL | b: bool, LL | c: bool, - | ^^^^^^^ + | ^ error: aborting due to 6 previous errors diff --git a/src/test/ui/lint/dead-code/lint-dead-code-5.stderr b/src/test/ui/lint/dead-code/lint-dead-code-5.stderr index 037a9be22ad..eaf43e45361 100644 --- a/src/test/ui/lint/dead-code/lint-dead-code-5.stderr +++ b/src/test/ui/lint/dead-code/lint-dead-code-5.stderr @@ -20,9 +20,9 @@ LL | enum Enum2 { | ----- variants in this enum ... LL | Variant5 { _x: isize }, - | ^^^^^^^^^^^^^^^^^^^^^^ + | ^^^^^^^^ LL | Variant6(isize), - | ^^^^^^^^^^^^^^^ + | ^^^^^^^^ error: enum `Enum3` is never used --> $DIR/lint-dead-code-5.rs:35:6 diff --git a/src/test/ui/lint/dead-code/multiple-dead-codes-in-the-same-struct.stderr b/src/test/ui/lint/dead-code/multiple-dead-codes-in-the-same-struct.stderr index 5cc8e06c09d..c0f1ed38f6d 100644 --- a/src/test/ui/lint/dead-code/multiple-dead-codes-in-the-same-struct.stderr +++ b/src/test/ui/lint/dead-code/multiple-dead-codes-in-the-same-struct.stderr @@ -5,12 +5,12 @@ LL | struct Bar { | --- fields in this struct ... LL | d: usize, - | ^^^^^^^^ + | ^ ... LL | f: usize, - | ^^^^^^^^ + | ^ LL | g: usize, - | ^^^^^^^^ + | ^ | note: the lint level is defined here --> $DIR/multiple-dead-codes-in-the-same-struct.rs:1:9 @@ -25,10 +25,10 @@ LL | struct Bar { | --- fields in this struct ... LL | c: usize, - | ^^^^^^^^ + | ^ ... LL | e: usize, - | ^^^^^^^^ + | ^ | note: the lint level is defined here --> $DIR/multiple-dead-codes-in-the-same-struct.rs:8:12 @@ -43,7 +43,7 @@ LL | struct Bar { | --- field in this struct ... LL | b: usize, - | ^^^^^^^^ + | ^ | note: the lint level is defined here --> $DIR/multiple-dead-codes-in-the-same-struct.rs:6:14 diff --git a/src/test/ui/lint/dead-code/type-alias.stderr b/src/test/ui/lint/dead-code/type-alias.stderr index 80c6ba962b8..446447d974a 100644 --- a/src/test/ui/lint/dead-code/type-alias.stderr +++ b/src/test/ui/lint/dead-code/type-alias.stderr @@ -1,8 +1,8 @@ error: type alias `Unused` is never used - --> $DIR/type-alias.rs:4:1 + --> $DIR/type-alias.rs:4:6 | LL | type Unused = u8; - | ^^^^^^^^^^^^^^^^^ + | ^^^^^^ | note: the lint level is defined here --> $DIR/type-alias.rs:1:9 diff --git a/src/test/ui/lint/dead-code/unused-struct-variant.stderr b/src/test/ui/lint/dead-code/unused-struct-variant.stderr index b08402b671b..d26dd3aff95 100644 --- a/src/test/ui/lint/dead-code/unused-struct-variant.stderr +++ b/src/test/ui/lint/dead-code/unused-struct-variant.stderr @@ -5,7 +5,7 @@ LL | enum E { | - variant in this enum LL | Foo(F), LL | Bar(B), - | ^^^^^^ + | ^^^ | note: the lint level is defined here --> $DIR/unused-struct-variant.rs:1:9 diff --git a/src/test/ui/lint/force-warn/allowed-cli-deny-by-default-lint.stderr b/src/test/ui/lint/force-warn/allowed-cli-deny-by-default-lint.stderr index c14529a7d09..915b3b86fe8 100644 --- a/src/test/ui/lint/force-warn/allowed-cli-deny-by-default-lint.stderr +++ b/src/test/ui/lint/force-warn/allowed-cli-deny-by-default-lint.stderr @@ -2,9 +2,7 @@ warning: any use of this value will cause an error --> $DIR/allowed-cli-deny-by-default-lint.rs:6:16 | LL | const C: i32 = 1 / 0; - | ---------------^^^^^- - | | - | attempt to divide `1_i32` by zero + | ------------ ^^^^^ attempt to divide `1_i32` by zero | = note: requested on the command line with `--force-warn const-err` = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release! @@ -17,9 +15,7 @@ warning: any use of this value will cause an error --> $DIR/allowed-cli-deny-by-default-lint.rs:6:16 | LL | const C: i32 = 1 / 0; - | ---------------^^^^^- - | | - | attempt to divide `1_i32` by zero + | ------------ ^^^^^ attempt to divide `1_i32` by zero | = note: requested on the command line with `--force-warn const-err` = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release! diff --git a/src/test/ui/lint/force-warn/allowed-deny-by-default-lint.stderr b/src/test/ui/lint/force-warn/allowed-deny-by-default-lint.stderr index dd71a168960..3b36d1d0227 100644 --- a/src/test/ui/lint/force-warn/allowed-deny-by-default-lint.stderr +++ b/src/test/ui/lint/force-warn/allowed-deny-by-default-lint.stderr @@ -2,9 +2,7 @@ warning: any use of this value will cause an error --> $DIR/allowed-deny-by-default-lint.rs:7:16 | LL | const C: i32 = 1 / 0; - | ---------------^^^^^- - | | - | attempt to divide `1_i32` by zero + | ------------ ^^^^^ attempt to divide `1_i32` by zero | = note: requested on the command line with `--force-warn const-err` = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release! @@ -17,9 +15,7 @@ warning: any use of this value will cause an error --> $DIR/allowed-deny-by-default-lint.rs:7:16 | LL | const C: i32 = 1 / 0; - | ---------------^^^^^- - | | - | attempt to divide `1_i32` by zero + | ------------ ^^^^^ attempt to divide `1_i32` by zero | = note: requested on the command line with `--force-warn const-err` = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release! diff --git a/src/test/ui/lint/force-warn/deny-by-default-lint.stderr b/src/test/ui/lint/force-warn/deny-by-default-lint.stderr index d4e80584669..a2e5baa8b9d 100644 --- a/src/test/ui/lint/force-warn/deny-by-default-lint.stderr +++ b/src/test/ui/lint/force-warn/deny-by-default-lint.stderr @@ -2,9 +2,7 @@ warning: any use of this value will cause an error --> $DIR/deny-by-default-lint.rs:5:16 | LL | const C: i32 = 1 / 0; - | ---------------^^^^^- - | | - | attempt to divide `1_i32` by zero + | ------------ ^^^^^ attempt to divide `1_i32` by zero | = note: requested on the command line with `--force-warn const-err` = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release! @@ -17,9 +15,7 @@ warning: any use of this value will cause an error --> $DIR/deny-by-default-lint.rs:5:16 | LL | const C: i32 = 1 / 0; - | ---------------^^^^^- - | | - | attempt to divide `1_i32` by zero + | ------------ ^^^^^ attempt to divide `1_i32` by zero | = note: requested on the command line with `--force-warn const-err` = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release! diff --git a/src/test/ui/lint/issue-14309.stderr b/src/test/ui/lint/issue-14309.stderr index 799991f7ee4..a9538b5e3a4 100644 --- a/src/test/ui/lint/issue-14309.stderr +++ b/src/test/ui/lint/issue-14309.stderr @@ -14,10 +14,8 @@ LL | #![deny(improper_ctypes)] note: the type is defined here --> $DIR/issue-14309.rs:4:1 | -LL | / struct A { -LL | | x: i32 -LL | | } - | |_^ +LL | struct A { + | ^^^^^^^^ error: `extern` block uses type `A`, which is not FFI-safe --> $DIR/issue-14309.rs:31:15 @@ -30,10 +28,8 @@ LL | fn bar(x: B); note: the type is defined here --> $DIR/issue-14309.rs:4:1 | -LL | / struct A { -LL | | x: i32 -LL | | } - | |_^ +LL | struct A { + | ^^^^^^^^ error: `extern` block uses type `A`, which is not FFI-safe --> $DIR/issue-14309.rs:33:15 @@ -46,10 +42,8 @@ LL | fn qux(x: A2); note: the type is defined here --> $DIR/issue-14309.rs:4:1 | -LL | / struct A { -LL | | x: i32 -LL | | } - | |_^ +LL | struct A { + | ^^^^^^^^ error: `extern` block uses type `A`, which is not FFI-safe --> $DIR/issue-14309.rs:34:16 @@ -62,10 +56,8 @@ LL | fn quux(x: B2); note: the type is defined here --> $DIR/issue-14309.rs:4:1 | -LL | / struct A { -LL | | x: i32 -LL | | } - | |_^ +LL | struct A { + | ^^^^^^^^ error: `extern` block uses type `A`, which is not FFI-safe --> $DIR/issue-14309.rs:36:16 @@ -78,10 +70,8 @@ LL | fn fred(x: D); note: the type is defined here --> $DIR/issue-14309.rs:4:1 | -LL | / struct A { -LL | | x: i32 -LL | | } - | |_^ +LL | struct A { + | ^^^^^^^^ error: aborting due to 5 previous errors diff --git a/src/test/ui/lint/issue-17718-const-naming.stderr b/src/test/ui/lint/issue-17718-const-naming.stderr index 4c97f6d63d4..7d2aadd5f80 100644 --- a/src/test/ui/lint/issue-17718-const-naming.stderr +++ b/src/test/ui/lint/issue-17718-const-naming.stderr @@ -1,8 +1,8 @@ error: constant `foo` is never used - --> $DIR/issue-17718-const-naming.rs:4:1 + --> $DIR/issue-17718-const-naming.rs:4:7 | LL | const foo: isize = 3; - | ^^^^^^^^^^^^^^^^^^^^^ + | ^^^ | note: the lint level is defined here --> $DIR/issue-17718-const-naming.rs:2:9 diff --git a/src/test/ui/lint/lint-const-item-mutation.stderr b/src/test/ui/lint/lint-const-item-mutation.stderr index 540e076c7e4..94d876423e7 100644 --- a/src/test/ui/lint/lint-const-item-mutation.stderr +++ b/src/test/ui/lint/lint-const-item-mutation.stderr @@ -10,7 +10,7 @@ note: `const` item defined here --> $DIR/lint-const-item-mutation.rs:26:1 | LL | const ARRAY: [u8; 1] = [25]; - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | ^^^^^^^^^^^^^^^^^^^^ warning: attempting to modify a `const` item --> $DIR/lint-const-item-mutation.rs:38:5 @@ -23,7 +23,7 @@ note: `const` item defined here --> $DIR/lint-const-item-mutation.rs:27:1 | LL | const MY_STRUCT: MyStruct = MyStruct { field: true, inner_array: ['a'], raw_ptr: 2 as *mut u8 }; - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | ^^^^^^^^^^^^^^^^^^^^^^^^^ warning: attempting to modify a `const` item --> $DIR/lint-const-item-mutation.rs:39:5 @@ -36,7 +36,7 @@ note: `const` item defined here --> $DIR/lint-const-item-mutation.rs:27:1 | LL | const MY_STRUCT: MyStruct = MyStruct { field: true, inner_array: ['a'], raw_ptr: 2 as *mut u8 }; - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | ^^^^^^^^^^^^^^^^^^^^^^^^^ warning: taking a mutable reference to a `const` item --> $DIR/lint-const-item-mutation.rs:40:5 @@ -55,7 +55,7 @@ note: `const` item defined here --> $DIR/lint-const-item-mutation.rs:27:1 | LL | const MY_STRUCT: MyStruct = MyStruct { field: true, inner_array: ['a'], raw_ptr: 2 as *mut u8 }; - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | ^^^^^^^^^^^^^^^^^^^^^^^^^ warning: taking a mutable reference to a `const` item --> $DIR/lint-const-item-mutation.rs:41:5 @@ -69,7 +69,7 @@ note: `const` item defined here --> $DIR/lint-const-item-mutation.rs:27:1 | LL | const MY_STRUCT: MyStruct = MyStruct { field: true, inner_array: ['a'], raw_ptr: 2 as *mut u8 }; - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | ^^^^^^^^^^^^^^^^^^^^^^^^^ warning: taking a mutable reference to a `const` item --> $DIR/lint-const-item-mutation.rs:42:5 @@ -83,7 +83,7 @@ note: `const` item defined here --> $DIR/lint-const-item-mutation.rs:27:1 | LL | const MY_STRUCT: MyStruct = MyStruct { field: true, inner_array: ['a'], raw_ptr: 2 as *mut u8 }; - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | ^^^^^^^^^^^^^^^^^^^^^^^^^ warning: attempting to modify a `const` item --> $DIR/lint-const-item-mutation.rs:54:5 @@ -96,7 +96,7 @@ note: `const` item defined here --> $DIR/lint-const-item-mutation.rs:30:1 | LL | const MUTABLE2: Mutable2 = Mutable2 { msg: "", other: String::new() }; - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | ^^^^^^^^^^^^^^^^^^^^^^^^ warning: taking a mutable reference to a `const` item --> $DIR/lint-const-item-mutation.rs:55:5 @@ -115,7 +115,7 @@ note: `const` item defined here --> $DIR/lint-const-item-mutation.rs:31:1 | LL | const VEC: Vec<i32> = Vec::new(); - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | ^^^^^^^^^^^^^^^^^^^ warning: 8 warnings emitted diff --git a/src/test/ui/lint/lint-ctypes-enum.stderr b/src/test/ui/lint/lint-ctypes-enum.stderr index 1601bd9d629..de532f69ac0 100644 --- a/src/test/ui/lint/lint-ctypes-enum.stderr +++ b/src/test/ui/lint/lint-ctypes-enum.stderr @@ -14,10 +14,8 @@ LL | #![deny(improper_ctypes)] note: the type is defined here --> $DIR/lint-ctypes-enum.rs:9:1 | -LL | / enum U { -LL | | A, -LL | | } - | |_^ +LL | enum U { + | ^^^^^^ error: `extern` block uses type `B`, which is not FFI-safe --> $DIR/lint-ctypes-enum.rs:61:13 @@ -30,11 +28,8 @@ LL | fn bf(x: B); note: the type is defined here --> $DIR/lint-ctypes-enum.rs:12:1 | -LL | / enum B { -LL | | C, -LL | | D, -LL | | } - | |_^ +LL | enum B { + | ^^^^^^ error: `extern` block uses type `T`, which is not FFI-safe --> $DIR/lint-ctypes-enum.rs:62:13 @@ -47,12 +42,8 @@ LL | fn tf(x: T); note: the type is defined here --> $DIR/lint-ctypes-enum.rs:16:1 | -LL | / enum T { -LL | | E, -LL | | F, -LL | | G, -LL | | } - | |_^ +LL | enum T { + | ^^^^^^ error: `extern` block uses type `u128`, which is not FFI-safe --> $DIR/lint-ctypes-enum.rs:74:23 diff --git a/src/test/ui/lint/lint-ctypes-fn.stderr b/src/test/ui/lint/lint-ctypes-fn.stderr index 740075ca7df..6f8d76411aa 100644 --- a/src/test/ui/lint/lint-ctypes-fn.stderr +++ b/src/test/ui/lint/lint-ctypes-fn.stderr @@ -100,7 +100,7 @@ note: the type is defined here --> $DIR/lint-ctypes-fn.rs:28:1 | LL | pub struct ZeroSize; - | ^^^^^^^^^^^^^^^^^^^^ + | ^^^^^^^^^^^^^^^^^^^ error: `extern` fn uses type `ZeroSizeWithPhantomData`, which is not FFI-safe --> $DIR/lint-ctypes-fn.rs:110:40 @@ -113,7 +113,7 @@ note: the type is defined here --> $DIR/lint-ctypes-fn.rs:63:1 | LL | pub struct ZeroSizeWithPhantomData(PhantomData<i32>); - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ error: `extern` fn uses type `PhantomData<bool>`, which is not FFI-safe --> $DIR/lint-ctypes-fn.rs:113:51 diff --git a/src/test/ui/lint/lint-ctypes.stderr b/src/test/ui/lint/lint-ctypes.stderr index 342b6bfc6f8..bfec40e1955 100644 --- a/src/test/ui/lint/lint-ctypes.stderr +++ b/src/test/ui/lint/lint-ctypes.stderr @@ -15,7 +15,7 @@ note: the type is defined here --> $DIR/lint-ctypes.rs:26:1 | LL | pub struct Foo; - | ^^^^^^^^^^^^^^^ + | ^^^^^^^^^^^^^^ error: `extern` block uses type `Foo`, which is not FFI-safe --> $DIR/lint-ctypes.rs:49:28 @@ -29,7 +29,7 @@ note: the type is defined here --> $DIR/lint-ctypes.rs:26:1 | LL | pub struct Foo; - | ^^^^^^^^^^^^^^^ + | ^^^^^^^^^^^^^^ error: `extern` block uses type `((),)`, which is not FFI-safe --> $DIR/lint-ctypes.rs:51:25 @@ -139,7 +139,7 @@ note: the type is defined here --> $DIR/lint-ctypes.rs:22:1 | LL | pub struct ZeroSize; - | ^^^^^^^^^^^^^^^^^^^^ + | ^^^^^^^^^^^^^^^^^^^ error: `extern` block uses type `ZeroSizeWithPhantomData`, which is not FFI-safe --> $DIR/lint-ctypes.rs:64:33 @@ -152,7 +152,7 @@ note: the type is defined here --> $DIR/lint-ctypes.rs:45:1 | LL | pub struct ZeroSizeWithPhantomData(::std::marker::PhantomData<i32>); - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ error: `extern` block uses type `PhantomData<bool>`, which is not FFI-safe --> $DIR/lint-ctypes.rs:67:12 diff --git a/src/test/ui/lint/recommend-literal.rs b/src/test/ui/lint/recommend-literal.rs index f60d3d10dce..453cbf28569 100644 --- a/src/test/ui/lint/recommend-literal.rs +++ b/src/test/ui/lint/recommend-literal.rs @@ -7,6 +7,13 @@ fn main() { let y: long = 74802374902374923; //~^ ERROR cannot find type `long` in this scope //~| HELP perhaps you intended to use this type + let v1: Boolean = true; + //~^ ERROR: cannot find type `Boolean` in this scope [E0412] + //~| HELP perhaps you intended to use this type + let v2: Bool = true; + //~^ ERROR: cannot find type `Bool` in this scope [E0412] + //~| HELP a builtin type with a similar name exists + //~| HELP perhaps you intended to use this type } fn z(a: boolean) { diff --git a/src/test/ui/lint/recommend-literal.stderr b/src/test/ui/lint/recommend-literal.stderr index 0ebcfb40dc3..424ecadd4b8 100644 --- a/src/test/ui/lint/recommend-literal.stderr +++ b/src/test/ui/lint/recommend-literal.stderr @@ -16,8 +16,32 @@ LL | let y: long = 74802374902374923; | not found in this scope | help: perhaps you intended to use this type: `i64` +error[E0412]: cannot find type `Boolean` in this scope + --> $DIR/recommend-literal.rs:10:13 + | +LL | let v1: Boolean = true; + | ^^^^^^^ + | | + | not found in this scope + | help: perhaps you intended to use this type: `bool` + +error[E0412]: cannot find type `Bool` in this scope + --> $DIR/recommend-literal.rs:13:13 + | +LL | let v2: Bool = true; + | ^^^^ + | +help: a builtin type with a similar name exists + | +LL | let v2: bool = true; + | ~~~~ +help: perhaps you intended to use this type + | +LL | let v2: bool = true; + | ~~~~ + error[E0412]: cannot find type `boolean` in this scope - --> $DIR/recommend-literal.rs:12:9 + --> $DIR/recommend-literal.rs:19:9 | LL | fn z(a: boolean) { | ^^^^^^^ @@ -26,7 +50,7 @@ LL | fn z(a: boolean) { | help: perhaps you intended to use this type: `bool` error[E0412]: cannot find type `byte` in this scope - --> $DIR/recommend-literal.rs:17:11 + --> $DIR/recommend-literal.rs:24:11 | LL | fn a() -> byte { | ^^^^ @@ -35,7 +59,7 @@ LL | fn a() -> byte { | help: perhaps you intended to use this type: `u8` error[E0412]: cannot find type `float` in this scope - --> $DIR/recommend-literal.rs:24:12 + --> $DIR/recommend-literal.rs:31:12 | LL | width: float, | ^^^^^ @@ -44,7 +68,7 @@ LL | width: float, | help: perhaps you intended to use this type: `f32` error[E0412]: cannot find type `int` in this scope - --> $DIR/recommend-literal.rs:27:19 + --> $DIR/recommend-literal.rs:34:19 | LL | depth: Option<int>, | ^^^ not found in this scope @@ -59,7 +83,7 @@ LL | struct Data<int> { | +++++ error[E0412]: cannot find type `short` in this scope - --> $DIR/recommend-literal.rs:33:16 + --> $DIR/recommend-literal.rs:40:16 | LL | impl Stuff for short {} | ^^^^^ @@ -67,6 +91,6 @@ LL | impl Stuff for short {} | not found in this scope | help: perhaps you intended to use this type: `i16` -error: aborting due to 7 previous errors +error: aborting due to 9 previous errors For more information about this error, try `rustc --explain E0412`. diff --git a/src/test/ui/lint/uninitialized-zeroed.stderr b/src/test/ui/lint/uninitialized-zeroed.stderr index b6a66f0a95a..88121a1836d 100644 --- a/src/test/ui/lint/uninitialized-zeroed.stderr +++ b/src/test/ui/lint/uninitialized-zeroed.stderr @@ -400,11 +400,8 @@ LL | let _val: Fruit = mem::uninitialized(); note: enums have to be initialized to a variant --> $DIR/uninitialized-zeroed.rs:26:1 | -LL | / enum Fruit { -LL | | Apple, -LL | | Banana, -LL | | } - | |_^ +LL | enum Fruit { + | ^^^^^^^^^^ error: the type `[bool; 2]` does not permit being left uninitialized --> $DIR/uninitialized-zeroed.rs:101:31 diff --git a/src/test/ui/lint/unused/unused-doc-comments-edge-cases.stderr b/src/test/ui/lint/unused/unused-doc-comments-edge-cases.stderr index 30a96af583a..1a022c30938 100644 --- a/src/test/ui/lint/unused/unused-doc-comments-edge-cases.stderr +++ b/src/test/ui/lint/unused/unused-doc-comments-edge-cases.stderr @@ -71,7 +71,7 @@ LL | LL | / extern "C" { LL | | fn foo(); LL | | } - | |_- rustdoc does not generate documentation for extern block + | |_- rustdoc does not generate documentation for extern blocks | = help: use `//` for a plain comment diff --git a/src/test/ui/macro_backtrace/main.-Zmacro-backtrace.stderr b/src/test/ui/macro_backtrace/main.-Zmacro-backtrace.stderr index 1d57b32d47e..bf85a2d75db 100644 --- a/src/test/ui/macro_backtrace/main.-Zmacro-backtrace.stderr +++ b/src/test/ui/macro_backtrace/main.-Zmacro-backtrace.stderr @@ -13,70 +13,60 @@ LL | pong!(); error: expected one of `!`, `.`, `::`, `;`, `?`, `{`, `}`, or an operator, found `error` --> $DIR/main.rs:10:20 | -LL | / macro_rules! pong { -LL | | () => { syntax error }; - | | ^^^^^ expected one of 8 possible tokens -LL | | } - | |__- in this expansion of `pong!` (#2) +LL | / macro_rules! pong { +LL | | () => { syntax error }; + | | ^^^^^ expected one of 8 possible tokens +LL | | } + | |_- in this expansion of `pong!` (#2) ... -LL | ping!(); - | ------- in this macro invocation (#1) +LL | ping!(); + | ------- in this macro invocation (#1) | ::: $DIR/auxiliary/ping.rs:5:1 | -LL | / macro_rules! ping { -LL | | () => { -LL | | pong!(); - | | ------- in this macro invocation (#2) -LL | | } -LL | | } - | |_- in this expansion of `ping!` (#1) +LL | macro_rules! ping { + | ----------------- in this expansion of `ping!` (#1) +LL | () => { +LL | pong!(); + | ------- in this macro invocation (#2) error: expected one of `!`, `.`, `::`, `;`, `?`, `{`, `}`, or an operator, found `error` --> $DIR/main.rs:10:20 | -LL | / macro_rules! pong { -LL | | () => { syntax error }; - | | ^^^^^ expected one of 8 possible tokens -LL | | } - | |__- in this expansion of `pong!` (#5) +LL | / macro_rules! pong { +LL | | () => { syntax error }; + | | ^^^^^ expected one of 8 possible tokens +LL | | } + | |_- in this expansion of `pong!` (#5) ... -LL | deep!(); - | ------- in this macro invocation (#1) +LL | deep!(); + | ------- in this macro invocation (#1) | ::: $DIR/auxiliary/ping.rs:5:1 | -LL | / macro_rules! ping { -LL | | () => { -LL | | pong!(); - | | ------- in this macro invocation (#5) -LL | | } -LL | | } - | |_- in this expansion of `ping!` (#4) +LL | macro_rules! ping { + | ----------------- in this expansion of `ping!` (#4) +LL | () => { +LL | pong!(); + | ------- in this macro invocation (#5) ... -LL | / macro_rules! deep { -LL | | () => { -LL | | foo!(); - | | ------ in this macro invocation (#2) -LL | | } -LL | | } - | |__- in this expansion of `deep!` (#1) +LL | macro_rules! deep { + | ----------------- in this expansion of `deep!` (#1) +LL | () => { +LL | foo!(); + | ------ in this macro invocation (#2) ... -LL | / macro_rules! foo { -LL | | () => { -LL | | bar!(); - | | ------ in this macro invocation (#3) -LL | | } -LL | | } - | |__- in this expansion of `foo!` (#2) +LL | macro_rules! foo { + | ---------------- in this expansion of `foo!` (#2) +LL | () => { +LL | bar!(); + | ------ in this macro invocation (#3) ... -LL | / macro_rules! bar { -LL | | () => { -LL | | ping!(); - | | ------- in this macro invocation (#4) -LL | | } -LL | | } - | |__- in this expansion of `bar!` (#3) +LL | macro_rules! bar { + | ---------------- in this expansion of `bar!` (#3) +LL | () => { +LL | ping!(); + | ------- in this macro invocation (#4) error: aborting due to 3 previous errors diff --git a/src/test/ui/macros/unknown-builtin.stderr b/src/test/ui/macros/unknown-builtin.stderr index 7b04e05293e..8f9dba16578 100644 --- a/src/test/ui/macros/unknown-builtin.stderr +++ b/src/test/ui/macros/unknown-builtin.stderr @@ -7,12 +7,8 @@ LL | macro_rules! unknown { () => () } error[E0773]: attempted to define built-in macro more than once --> $SRC_DIR/core/src/macros/mod.rs:LL:COL | -LL | / macro_rules! line { -LL | | () => { -LL | | /* compiler built-in */ -LL | | }; -LL | | } - | |_____^ +LL | macro_rules! line { + | ^^^^^^^^^^^^^^^^^ | note: previously defined here --> $DIR/unknown-builtin.rs:9:1 diff --git a/src/test/ui/marker_trait_attr/marker-trait-with-associated-items.stderr b/src/test/ui/marker_trait_attr/marker-trait-with-associated-items.stderr index ae7d5a98b08..ac218e30b9b 100644 --- a/src/test/ui/marker_trait_attr/marker-trait-with-associated-items.stderr +++ b/src/test/ui/marker_trait_attr/marker-trait-with-associated-items.stderr @@ -2,13 +2,13 @@ error[E0714]: marker traits cannot have associated items --> $DIR/marker-trait-with-associated-items.rs:6:5 | LL | const N: usize; - | ^^^^^^^^^^^^^^^ + | ^^^^^^^^^^^^^^ error[E0714]: marker traits cannot have associated items --> $DIR/marker-trait-with-associated-items.rs:12:5 | LL | type Output; - | ^^^^^^^^^^^^ + | ^^^^^^^^^^^ error[E0714]: marker traits cannot have associated items --> $DIR/marker-trait-with-associated-items.rs:18:5 @@ -20,13 +20,13 @@ error[E0714]: marker traits cannot have associated items --> $DIR/marker-trait-with-associated-items.rs:24:5 | LL | const N: usize = 43; - | ^^^^^^^^^^^^^^^^^^^^ + | ^^^^^^^^^^^^^^ error[E0714]: marker traits cannot have associated items --> $DIR/marker-trait-with-associated-items.rs:30:5 | LL | type Output = (); - | ^^^^^^^^^^^^^^^^^ + | ^^^^^^^^^^^ error[E0714]: marker traits cannot have associated items --> $DIR/marker-trait-with-associated-items.rs:36:5 diff --git a/src/test/ui/marker_trait_attr/region-overlap.stderr b/src/test/ui/marker_trait_attr/region-overlap.stderr index 2eeab801e3d..6631fe987e2 100644 --- a/src/test/ui/marker_trait_attr/region-overlap.stderr +++ b/src/test/ui/marker_trait_attr/region-overlap.stderr @@ -1,8 +1,8 @@ -error[E0283]: type annotations needed +error[E0283]: type annotations needed: cannot satisfy `(&'static (), &'a ()): A` --> $DIR/region-overlap.rs:5:10 | LL | impl<'a> A for (&'static (), &'a ()) {} - | ^ cannot infer type for tuple `(&'static (), &'a ())` + | ^ | note: multiple `impl`s satisfying `(&'static (), &'a ()): A` found --> $DIR/region-overlap.rs:5:1 @@ -12,11 +12,11 @@ LL | impl<'a> A for (&'static (), &'a ()) {} LL | impl<'a> A for (&'a (), &'static ()) {} | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ -error[E0283]: type annotations needed +error[E0283]: type annotations needed: cannot satisfy `(&'a (), &'static ()): A` --> $DIR/region-overlap.rs:6:10 | LL | impl<'a> A for (&'a (), &'static ()) {} - | ^ cannot infer type for tuple `(&'a (), &'static ())` + | ^ | note: multiple `impl`s satisfying `(&'a (), &'static ()): A` found --> $DIR/region-overlap.rs:5:1 diff --git a/src/test/ui/match/match_non_exhaustive.stderr b/src/test/ui/match/match_non_exhaustive.stderr index 6206dc85ea0..9d92f8fdbb4 100644 --- a/src/test/ui/match/match_non_exhaustive.stderr +++ b/src/test/ui/match/match_non_exhaustive.stderr @@ -25,7 +25,7 @@ note: `E1` defined here --> $DIR/auxiliary/match_non_exhaustive_lib.rs:2:1 | LL | pub enum E1 {} - | ^^^^^^^^^^^^^^ + | ^^^^^^^^^^^ = note: the matched value is of type `E1`, which is marked as non-exhaustive help: ensure that all possible cases are being handled by adding a match arm with a wildcard pattern as shown | @@ -44,7 +44,7 @@ note: `E2` defined here --> $DIR/auxiliary/match_non_exhaustive_lib.rs:5:1 | LL | pub enum E2 { A, B } - | ^^^^^^^^^^^^^^^^^^^^ + | ^^^^^^^^^^^ = note: the matched value is of type `E2`, which is marked as non-exhaustive help: ensure that all possible cases are being handled by adding a match arm with a wildcard pattern or an explicit pattern as shown | diff --git a/src/test/ui/methods/method-ambig-one-trait-unknown-int-type.stderr b/src/test/ui/methods/method-ambig-one-trait-unknown-int-type.stderr index 66e7ada3ac5..e0f8a5447b0 100644 --- a/src/test/ui/methods/method-ambig-one-trait-unknown-int-type.stderr +++ b/src/test/ui/methods/method-ambig-one-trait-unknown-int-type.stderr @@ -13,7 +13,7 @@ error[E0283]: type annotations needed --> $DIR/method-ambig-one-trait-unknown-int-type.rs:26:7 | LL | x.foo(); - | ^^^ cannot infer type for struct `Vec<_>` + | ^^^ | note: multiple `impl`s satisfying `Vec<_>: Foo` found --> $DIR/method-ambig-one-trait-unknown-int-type.rs:9:1 @@ -23,6 +23,10 @@ LL | impl Foo for Vec<usize> { ... LL | impl Foo for Vec<isize> { | ^^^^^^^^^^^^^^^^^^^^^^^ +help: try using a fully qualified path to specify the expected types + | +LL | <Vec<T> as Foo>::foo(&x); + | ++++++++++++++++++++++ ~ error[E0308]: mismatched types --> $DIR/method-ambig-one-trait-unknown-int-type.rs:33:20 diff --git a/src/test/ui/methods/method-call-err-msg.stderr b/src/test/ui/methods/method-call-err-msg.stderr index 57662e1e265..4be588fe7f9 100644 --- a/src/test/ui/methods/method-call-err-msg.stderr +++ b/src/test/ui/methods/method-call-err-msg.stderr @@ -50,7 +50,7 @@ error[E0599]: `Foo` is not an iterator --> $DIR/method-call-err-msg.rs:19:7 | LL | pub struct Foo; - | --------------- + | -------------- | | | | | method `take` not found for this struct | doesn't satisfy `Foo: Iterator` @@ -64,14 +64,8 @@ LL | .take() note: the following trait must be implemented --> $SRC_DIR/core/src/iter/traits/iterator.rs:LL:COL | -LL | / pub trait Iterator { -LL | | /// The type of the elements being iterated over. -LL | | #[stable(feature = "rust1", since = "1.0.0")] -LL | | type Item; -... | -LL | | } -LL | | } - | |_^ +LL | pub trait Iterator { + | ^^^^^^^^^^^^^^^^^^ = help: items from traits can only be used if the trait is implemented and in scope = note: the following trait defines an item `take`, perhaps you need to implement it: candidate #1: `Iterator` diff --git a/src/test/ui/mismatched_types/assignment-operator-unimplemented.stderr b/src/test/ui/mismatched_types/assignment-operator-unimplemented.stderr index 73c9f86e002..ffd95b48ac2 100644 --- a/src/test/ui/mismatched_types/assignment-operator-unimplemented.stderr +++ b/src/test/ui/mismatched_types/assignment-operator-unimplemented.stderr @@ -10,18 +10,12 @@ note: an implementation of `AddAssign<_>` might be missing for `Foo` --> $DIR/assignment-operator-unimplemented.rs:1:1 | LL | struct Foo; - | ^^^^^^^^^^^ must implement `AddAssign<_>` + | ^^^^^^^^^^ must implement `AddAssign<_>` note: the following trait must be implemented --> $SRC_DIR/core/src/ops/arith.rs:LL:COL | -LL | / pub trait AddAssign<Rhs = Self> { -LL | | /// Performs the `+=` operation. -LL | | /// -LL | | /// # Example -... | -LL | | fn add_assign(&mut self, rhs: Rhs); -LL | | } - | |_^ +LL | pub trait AddAssign<Rhs = Self> { + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ error: aborting due to previous error diff --git a/src/test/ui/mismatched_types/closure-arg-count.stderr b/src/test/ui/mismatched_types/closure-arg-count.stderr index fed47e0f174..3968774e357 100644 --- a/src/test/ui/mismatched_types/closure-arg-count.stderr +++ b/src/test/ui/mismatched_types/closure-arg-count.stderr @@ -188,7 +188,7 @@ LL | call(Foo); | required by a bound introduced by this call ... LL | struct Foo(u8); - | --------------- takes 1 argument + | ---------- takes 1 argument | note: required by a bound in `call` --> $DIR/closure-arg-count.rs:42:30 diff --git a/src/test/ui/missing-trait-bounds/issue-69725.stderr b/src/test/ui/missing-trait-bounds/issue-69725.stderr index 6395bca300c..980d9dd167d 100644 --- a/src/test/ui/missing-trait-bounds/issue-69725.stderr +++ b/src/test/ui/missing-trait-bounds/issue-69725.stderr @@ -7,7 +7,7 @@ LL | let _ = Struct::<A>::new().clone(); ::: $DIR/auxiliary/issue-69725.rs:2:1 | LL | pub struct Struct<A>(A); - | ------------------------ doesn't satisfy `Struct<A>: Clone` + | -------------------- doesn't satisfy `Struct<A>: Clone` | = note: the following trait bounds were not satisfied: `A: Clone` diff --git a/src/test/ui/missing-trait-bounds/missing-trait-bounds-for-method-call.stderr b/src/test/ui/missing-trait-bounds/missing-trait-bounds-for-method-call.stderr index f3c6b39e62e..9e94aa2c7b3 100644 --- a/src/test/ui/missing-trait-bounds/missing-trait-bounds-for-method-call.stderr +++ b/src/test/ui/missing-trait-bounds/missing-trait-bounds-for-method-call.stderr @@ -30,7 +30,7 @@ error[E0599]: the method `foo` exists for reference `&Fin<T>`, but its trait bou --> $DIR/missing-trait-bounds-for-method-call.rs:27:14 | LL | struct Fin<T> where T: Bar { - | -------------------------- doesn't satisfy `Fin<T>: Bar` + | ------------- doesn't satisfy `Fin<T>: Bar` ... LL | self.foo(); | ^^^ method cannot be called on `&Fin<T>` due to unsatisfied trait bounds diff --git a/src/test/ui/moves/move-deref-coercion.stderr b/src/test/ui/moves/move-deref-coercion.stderr index e3bdf6d7832..5760f4a7fdc 100644 --- a/src/test/ui/moves/move-deref-coercion.stderr +++ b/src/test/ui/moves/move-deref-coercion.stderr @@ -12,7 +12,7 @@ note: deref defined here --> $DIR/move-deref-coercion.rs:17:5 | LL | type Target = NotCopy; - | ^^^^^^^^^^^^^^^^^^^^^^ + | ^^^^^^^^^^^ error[E0382]: borrow of partially moved value: `val` --> $DIR/move-deref-coercion.rs:30:5 @@ -28,7 +28,7 @@ note: deref defined here --> $DIR/move-deref-coercion.rs:17:5 | LL | type Target = NotCopy; - | ^^^^^^^^^^^^^^^^^^^^^^ + | ^^^^^^^^^^^ error: aborting due to 2 previous errors diff --git a/src/test/ui/namespace/namespace-mix.stderr b/src/test/ui/namespace/namespace-mix.stderr index ccdd4dd272e..fbd86bdb661 100644 --- a/src/test/ui/namespace/namespace-mix.stderr +++ b/src/test/ui/namespace/namespace-mix.stderr @@ -33,7 +33,7 @@ LL | check(xm1::S); ::: $DIR/auxiliary/namespace-mix.rs:3:5 | LL | pub struct TS(); - | ---------------- similarly named tuple struct `TS` defined here + | ------------- similarly named tuple struct `TS` defined here | = note: can't use a type alias as a constructor help: a tuple struct with a similar name exists diff --git a/src/test/ui/never_type/never-from-impl-is-reserved.stderr b/src/test/ui/never_type/never-from-impl-is-reserved.stderr index 871c5120528..f9f7c787ecb 100644 --- a/src/test/ui/never_type/never-from-impl-is-reserved.stderr +++ b/src/test/ui/never_type/never-from-impl-is-reserved.stderr @@ -5,7 +5,7 @@ LL | impl MyTrait for MyFoo {} | ---------------------- first implementation here LL | // This will conflict with the first impl if we impl `for<T> T: From<!>`. LL | impl<T> MyTrait for T where T: From<!> {} - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ conflicting implementation for `MyFoo` + | ^^^^^^^^^^^^^^^^^^^^^ conflicting implementation for `MyFoo` | = note: permitting this impl would forbid us from adding `impl<T> From<!> for T` later; see rust-lang/rust#64715 for details diff --git a/src/test/ui/no-capture-arc.stderr b/src/test/ui/no-capture-arc.stderr index 7fa2090e3e6..9ae41e78c22 100644 --- a/src/test/ui/no-capture-arc.stderr +++ b/src/test/ui/no-capture-arc.stderr @@ -17,7 +17,7 @@ note: deref defined here --> $SRC_DIR/alloc/src/sync.rs:LL:COL | LL | type Target = T; - | ^^^^^^^^^^^^^^^^ + | ^^^^^^^^^^^ error: aborting due to previous error diff --git a/src/test/ui/no-reuse-move-arc.stderr b/src/test/ui/no-reuse-move-arc.stderr index bcc4506dc8d..564b0585474 100644 --- a/src/test/ui/no-reuse-move-arc.stderr +++ b/src/test/ui/no-reuse-move-arc.stderr @@ -17,7 +17,7 @@ note: deref defined here --> $SRC_DIR/alloc/src/sync.rs:LL:COL | LL | type Target = T; - | ^^^^^^^^^^^^^^^^ + | ^^^^^^^^^^^ error: aborting due to previous error diff --git a/src/test/ui/non-fmt-panic.stderr b/src/test/ui/non-fmt-panic.stderr index 4da97ed5d60..6e4434e6f33 100644 --- a/src/test/ui/non-fmt-panic.stderr +++ b/src/test/ui/non-fmt-panic.stderr @@ -73,9 +73,9 @@ warning: panic message is not a string literal LL | assert!(false, S); | ^ | - = note: this usage of assert!() is deprecated; it will be a hard error in Rust 2021 + = note: this usage of `assert!()` is deprecated; it will be a hard error in Rust 2021 = note: for more information, see <https://doc.rust-lang.org/nightly/edition-guide/rust-2021/panic-macro-consistency.html> -help: add a "{}" format string to Display the message +help: add a "{}" format string to `Display` the message | LL | assert!(false, "{}", S); | +++++ @@ -86,9 +86,9 @@ warning: panic message is not a string literal LL | assert!(false, 123); | ^^^ | - = note: this usage of assert!() is deprecated; it will be a hard error in Rust 2021 + = note: this usage of `assert!()` is deprecated; it will be a hard error in Rust 2021 = note: for more information, see <https://doc.rust-lang.org/nightly/edition-guide/rust-2021/panic-macro-consistency.html> -help: add a "{}" format string to Display the message +help: add a "{}" format string to `Display` the message | LL | assert!(false, "{}", 123); | +++++ @@ -99,9 +99,9 @@ warning: panic message is not a string literal LL | assert!(false, Some(123)); | ^^^^^^^^^ | - = note: this usage of assert!() is deprecated; it will be a hard error in Rust 2021 + = note: this usage of `assert!()` is deprecated; it will be a hard error in Rust 2021 = note: for more information, see <https://doc.rust-lang.org/nightly/edition-guide/rust-2021/panic-macro-consistency.html> -help: add a "{:?}" format string to use the Debug implementation of `Option<i32>` +help: add a "{:?}" format string to use the `Debug` implementation of `Option<i32>` | LL | assert!(false, "{:?}", Some(123)); | +++++++ @@ -124,9 +124,9 @@ warning: panic message is not a string literal LL | panic!(C); | ^ | - = note: this usage of panic!() is deprecated; it will be a hard error in Rust 2021 + = note: this usage of `panic!()` is deprecated; it will be a hard error in Rust 2021 = note: for more information, see <https://doc.rust-lang.org/nightly/edition-guide/rust-2021/panic-macro-consistency.html> -help: add a "{}" format string to Display the message +help: add a "{}" format string to `Display` the message | LL | panic!("{}", C); | +++++ @@ -137,9 +137,9 @@ warning: panic message is not a string literal LL | panic!(S); | ^ | - = note: this usage of panic!() is deprecated; it will be a hard error in Rust 2021 + = note: this usage of `panic!()` is deprecated; it will be a hard error in Rust 2021 = note: for more information, see <https://doc.rust-lang.org/nightly/edition-guide/rust-2021/panic-macro-consistency.html> -help: add a "{}" format string to Display the message +help: add a "{}" format string to `Display` the message | LL | panic!("{}", S); | +++++ @@ -150,9 +150,9 @@ warning: panic message is not a string literal LL | unreachable!(S); | ^ | - = note: this usage of unreachable!() is deprecated; it will be a hard error in Rust 2021 + = note: this usage of `unreachable!()` is deprecated; it will be a hard error in Rust 2021 = note: for more information, see <https://doc.rust-lang.org/nightly/edition-guide/rust-2021/panic-macro-consistency.html> -help: add a "{}" format string to Display the message +help: add a "{}" format string to `Display` the message | LL | unreachable!("{}", S); | +++++ @@ -163,9 +163,9 @@ warning: panic message is not a string literal LL | unreachable!(S); | ^ | - = note: this usage of unreachable!() is deprecated; it will be a hard error in Rust 2021 + = note: this usage of `unreachable!()` is deprecated; it will be a hard error in Rust 2021 = note: for more information, see <https://doc.rust-lang.org/nightly/edition-guide/rust-2021/panic-macro-consistency.html> -help: add a "{}" format string to Display the message +help: add a "{}" format string to `Display` the message | LL | unreachable!("{}", S); | +++++ @@ -176,9 +176,9 @@ warning: panic message is not a string literal LL | std::panic!(123); | ^^^ | - = note: this usage of std::panic!() is deprecated; it will be a hard error in Rust 2021 + = note: this usage of `std::panic!()` is deprecated; it will be a hard error in Rust 2021 = note: for more information, see <https://doc.rust-lang.org/nightly/edition-guide/rust-2021/panic-macro-consistency.html> -help: add a "{}" format string to Display the message +help: add a "{}" format string to `Display` the message | LL | std::panic!("{}", 123); | +++++ @@ -193,9 +193,9 @@ warning: panic message is not a string literal LL | core::panic!(&*"abc"); | ^^^^^^^ | - = note: this usage of core::panic!() is deprecated; it will be a hard error in Rust 2021 + = note: this usage of `core::panic!()` is deprecated; it will be a hard error in Rust 2021 = note: for more information, see <https://doc.rust-lang.org/nightly/edition-guide/rust-2021/panic-macro-consistency.html> -help: add a "{}" format string to Display the message +help: add a "{}" format string to `Display` the message | LL | core::panic!("{}", &*"abc"); | +++++ @@ -206,9 +206,9 @@ warning: panic message is not a string literal LL | panic!(Some(123)); | ^^^^^^^^^ | - = note: this usage of panic!() is deprecated; it will be a hard error in Rust 2021 + = note: this usage of `panic!()` is deprecated; it will be a hard error in Rust 2021 = note: for more information, see <https://doc.rust-lang.org/nightly/edition-guide/rust-2021/panic-macro-consistency.html> -help: add a "{:?}" format string to use the Debug implementation of `Option<i32>` +help: add a "{:?}" format string to use the `Debug` implementation of `Option<i32>` | LL | panic!("{:?}", Some(123)); | +++++++ @@ -259,9 +259,9 @@ warning: panic message is not a string literal LL | panic!(a!()); | ^^^^ | - = note: this usage of panic!() is deprecated; it will be a hard error in Rust 2021 + = note: this usage of `panic!()` is deprecated; it will be a hard error in Rust 2021 = note: for more information, see <https://doc.rust-lang.org/nightly/edition-guide/rust-2021/panic-macro-consistency.html> -help: add a "{}" format string to Display the message +help: add a "{}" format string to `Display` the message | LL | panic!("{}", a!()); | +++++ @@ -276,9 +276,9 @@ warning: panic message is not a string literal LL | unreachable!(a!()); | ^^^^ | - = note: this usage of unreachable!() is deprecated; it will be a hard error in Rust 2021 + = note: this usage of `unreachable!()` is deprecated; it will be a hard error in Rust 2021 = note: for more information, see <https://doc.rust-lang.org/nightly/edition-guide/rust-2021/panic-macro-consistency.html> -help: add a "{}" format string to Display the message +help: add a "{}" format string to `Display` the message | LL | unreachable!("{}", a!()); | +++++ @@ -289,9 +289,9 @@ warning: panic message is not a string literal LL | panic!(format!("{}", 1)); | ^^^^^^^^^^^^^^^^ | - = note: this usage of panic!() is deprecated; it will be a hard error in Rust 2021 + = note: this usage of `panic!()` is deprecated; it will be a hard error in Rust 2021 = note: for more information, see <https://doc.rust-lang.org/nightly/edition-guide/rust-2021/panic-macro-consistency.html> - = note: the panic!() macro supports formatting, so there's no need for the format!() macro here + = note: the `panic!()` macro supports formatting, so there's no need for the `format!()` macro here help: remove the `format!(..)` macro call | LL - panic!(format!("{}", 1)); @@ -304,9 +304,9 @@ warning: panic message is not a string literal LL | unreachable!(format!("{}", 1)); | ^^^^^^^^^^^^^^^^ | - = note: this usage of unreachable!() is deprecated; it will be a hard error in Rust 2021 + = note: this usage of `unreachable!()` is deprecated; it will be a hard error in Rust 2021 = note: for more information, see <https://doc.rust-lang.org/nightly/edition-guide/rust-2021/panic-macro-consistency.html> - = note: the unreachable!() macro supports formatting, so there's no need for the format!() macro here + = note: the `unreachable!()` macro supports formatting, so there's no need for the `format!()` macro here help: remove the `format!(..)` macro call | LL - unreachable!(format!("{}", 1)); @@ -319,9 +319,9 @@ warning: panic message is not a string literal LL | assert!(false, format!("{}", 1)); | ^^^^^^^^^^^^^^^^ | - = note: this usage of assert!() is deprecated; it will be a hard error in Rust 2021 + = note: this usage of `assert!()` is deprecated; it will be a hard error in Rust 2021 = note: for more information, see <https://doc.rust-lang.org/nightly/edition-guide/rust-2021/panic-macro-consistency.html> - = note: the assert!() macro supports formatting, so there's no need for the format!() macro here + = note: the `assert!()` macro supports formatting, so there's no need for the `format!()` macro here help: remove the `format!(..)` macro call | LL - assert!(false, format!("{}", 1)); @@ -334,9 +334,9 @@ warning: panic message is not a string literal LL | debug_assert!(false, format!("{}", 1)); | ^^^^^^^^^^^^^^^^ | - = note: this usage of debug_assert!() is deprecated; it will be a hard error in Rust 2021 + = note: this usage of `debug_assert!()` is deprecated; it will be a hard error in Rust 2021 = note: for more information, see <https://doc.rust-lang.org/nightly/edition-guide/rust-2021/panic-macro-consistency.html> - = note: the debug_assert!() macro supports formatting, so there's no need for the format!() macro here + = note: the `debug_assert!()` macro supports formatting, so there's no need for the `format!()` macro here help: remove the `format!(..)` macro call | LL - debug_assert!(false, format!("{}", 1)); @@ -349,9 +349,9 @@ warning: panic message is not a string literal LL | panic![123]; | ^^^ | - = note: this usage of panic!() is deprecated; it will be a hard error in Rust 2021 + = note: this usage of `panic!()` is deprecated; it will be a hard error in Rust 2021 = note: for more information, see <https://doc.rust-lang.org/nightly/edition-guide/rust-2021/panic-macro-consistency.html> -help: add a "{}" format string to Display the message +help: add a "{}" format string to `Display` the message | LL | panic!["{}", 123]; | +++++ @@ -366,9 +366,9 @@ warning: panic message is not a string literal LL | panic!{123}; | ^^^ | - = note: this usage of panic!() is deprecated; it will be a hard error in Rust 2021 + = note: this usage of `panic!()` is deprecated; it will be a hard error in Rust 2021 = note: for more information, see <https://doc.rust-lang.org/nightly/edition-guide/rust-2021/panic-macro-consistency.html> -help: add a "{}" format string to Display the message +help: add a "{}" format string to `Display` the message | LL | panic!{"{}", 123}; | +++++ @@ -385,7 +385,7 @@ LL | panic!(v); | | | help: use std::panic::panic_any instead: `std::panic::panic_any` | - = note: this usage of panic!() is deprecated; it will be a hard error in Rust 2021 + = note: this usage of `panic!()` is deprecated; it will be a hard error in Rust 2021 = note: for more information, see <https://doc.rust-lang.org/nightly/edition-guide/rust-2021/panic-macro-consistency.html> warning: panic message is not a string literal @@ -394,7 +394,7 @@ warning: panic message is not a string literal LL | assert!(false, v); | ^ | - = note: this usage of assert!() is deprecated; it will be a hard error in Rust 2021 + = note: this usage of `assert!()` is deprecated; it will be a hard error in Rust 2021 = note: for more information, see <https://doc.rust-lang.org/nightly/edition-guide/rust-2021/panic-macro-consistency.html> warning: panic message is not a string literal @@ -403,9 +403,9 @@ warning: panic message is not a string literal LL | panic!(v); | ^ | - = note: this usage of panic!() is deprecated; it will be a hard error in Rust 2021 + = note: this usage of `panic!()` is deprecated; it will be a hard error in Rust 2021 = note: for more information, see <https://doc.rust-lang.org/nightly/edition-guide/rust-2021/panic-macro-consistency.html> -help: add a "{:?}" format string to use the Debug implementation of `T` +help: add a "{:?}" format string to use the `Debug` implementation of `T` | LL | panic!("{:?}", v); | +++++++ @@ -420,9 +420,9 @@ warning: panic message is not a string literal LL | assert!(false, v); | ^ | - = note: this usage of assert!() is deprecated; it will be a hard error in Rust 2021 + = note: this usage of `assert!()` is deprecated; it will be a hard error in Rust 2021 = note: for more information, see <https://doc.rust-lang.org/nightly/edition-guide/rust-2021/panic-macro-consistency.html> -help: add a "{:?}" format string to use the Debug implementation of `T` +help: add a "{:?}" format string to use the `Debug` implementation of `T` | LL | assert!(false, "{:?}", v); | +++++++ @@ -433,9 +433,9 @@ warning: panic message is not a string literal LL | panic!(v); | ^ | - = note: this usage of panic!() is deprecated; it will be a hard error in Rust 2021 + = note: this usage of `panic!()` is deprecated; it will be a hard error in Rust 2021 = note: for more information, see <https://doc.rust-lang.org/nightly/edition-guide/rust-2021/panic-macro-consistency.html> -help: add a "{}" format string to Display the message +help: add a "{}" format string to `Display` the message | LL | panic!("{}", v); | +++++ @@ -450,9 +450,9 @@ warning: panic message is not a string literal LL | assert!(false, v); | ^ | - = note: this usage of assert!() is deprecated; it will be a hard error in Rust 2021 + = note: this usage of `assert!()` is deprecated; it will be a hard error in Rust 2021 = note: for more information, see <https://doc.rust-lang.org/nightly/edition-guide/rust-2021/panic-macro-consistency.html> -help: add a "{}" format string to Display the message +help: add a "{}" format string to `Display` the message | LL | assert!(false, "{}", v); | +++++ @@ -463,9 +463,9 @@ warning: panic message is not a string literal LL | panic!(v); | ^ | - = note: this usage of panic!() is deprecated; it will be a hard error in Rust 2021 + = note: this usage of `panic!()` is deprecated; it will be a hard error in Rust 2021 = note: for more information, see <https://doc.rust-lang.org/nightly/edition-guide/rust-2021/panic-macro-consistency.html> -help: add a "{}" format string to Display the message +help: add a "{}" format string to `Display` the message | LL | panic!("{}", v); | +++++ @@ -480,9 +480,9 @@ warning: panic message is not a string literal LL | assert!(false, v); | ^ | - = note: this usage of assert!() is deprecated; it will be a hard error in Rust 2021 + = note: this usage of `assert!()` is deprecated; it will be a hard error in Rust 2021 = note: for more information, see <https://doc.rust-lang.org/nightly/edition-guide/rust-2021/panic-macro-consistency.html> -help: add a "{}" format string to Display the message +help: add a "{}" format string to `Display` the message | LL | assert!(false, "{}", v); | +++++ diff --git a/src/test/ui/or-patterns/or-patterns-syntactic-fail.stderr b/src/test/ui/or-patterns/or-patterns-syntactic-fail.stderr index c94adfe4ab3..920720a4f53 100644 --- a/src/test/ui/or-patterns/or-patterns-syntactic-fail.stderr +++ b/src/test/ui/or-patterns/or-patterns-syntactic-fail.stderr @@ -38,14 +38,8 @@ LL | enum E { A, B } note: the following trait must be implemented --> $SRC_DIR/core/src/ops/bit.rs:LL:COL | -LL | / pub trait BitOr<Rhs = Self> { -LL | | /// The resulting type after applying the `|` operator. -LL | | #[stable(feature = "rust1", since = "1.0.0")] -LL | | type Output; -... | -LL | | fn bitor(self, rhs: Rhs) -> Self::Output; -LL | | } - | |_^ +LL | pub trait BitOr<Rhs = Self> { + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^ error: aborting due to 5 previous errors diff --git a/src/test/ui/panic-runtime/auxiliary/needs-abort.rs b/src/test/ui/panic-runtime/auxiliary/needs-abort.rs new file mode 100644 index 00000000000..8fad49b5e9d --- /dev/null +++ b/src/test/ui/panic-runtime/auxiliary/needs-abort.rs @@ -0,0 +1,5 @@ +// compile-flags:-C panic=abort +// no-prefer-dynamic + +#![crate_type = "rlib"] +#![no_std] diff --git a/src/test/ui/panic-runtime/auxiliary/needs-unwind.rs b/src/test/ui/panic-runtime/auxiliary/needs-unwind.rs new file mode 100644 index 00000000000..d555b531986 --- /dev/null +++ b/src/test/ui/panic-runtime/auxiliary/needs-unwind.rs @@ -0,0 +1,13 @@ +// compile-flags:-C panic=unwind +// no-prefer-dynamic + +#![crate_type = "rlib"] +#![no_std] +#![feature(c_unwind)] + +extern "C-unwind" fn foo() {} + +fn bar() { + let ptr: extern "C-unwind" fn() = foo; + ptr(); +} diff --git a/src/test/ui/panic-runtime/need-abort-got-unwind.rs b/src/test/ui/panic-runtime/need-abort-got-unwind.rs new file mode 100644 index 00000000000..c72fb96e357 --- /dev/null +++ b/src/test/ui/panic-runtime/need-abort-got-unwind.rs @@ -0,0 +1,9 @@ +// build-fail +// needs-unwind +// error-pattern:is incompatible with this crate's strategy of `unwind` +// aux-build:needs-abort.rs +// ignore-wasm32-bare compiled with panic=abort by default + +extern crate needs_abort; + +fn main() {} diff --git a/src/test/ui/panic-runtime/need-abort-got-unwind.stderr b/src/test/ui/panic-runtime/need-abort-got-unwind.stderr new file mode 100644 index 00000000000..d29c7875fd0 --- /dev/null +++ b/src/test/ui/panic-runtime/need-abort-got-unwind.stderr @@ -0,0 +1,4 @@ +error: the crate `needs_abort` requires panic strategy `abort` which is incompatible with this crate's strategy of `unwind` + +error: aborting due to previous error + diff --git a/src/test/ui/panic-runtime/need-unwind-got-abort.rs b/src/test/ui/panic-runtime/need-unwind-got-abort.rs new file mode 100644 index 00000000000..6752ecf90d2 --- /dev/null +++ b/src/test/ui/panic-runtime/need-unwind-got-abort.rs @@ -0,0 +1,9 @@ +// build-fail +// error-pattern:is incompatible with this crate's strategy of `abort` +// aux-build:needs-unwind.rs +// compile-flags:-C panic=abort +// no-prefer-dynamic + +extern crate needs_unwind; + +fn main() {} diff --git a/src/test/ui/panic-runtime/need-unwind-got-abort.stderr b/src/test/ui/panic-runtime/need-unwind-got-abort.stderr new file mode 100644 index 00000000000..4c71df3ebc1 --- /dev/null +++ b/src/test/ui/panic-runtime/need-unwind-got-abort.stderr @@ -0,0 +1,4 @@ +error: the crate `needs_unwind` requires panic strategy `unwind` which is incompatible with this crate's strategy of `abort` + +error: aborting due to previous error + diff --git a/src/test/ui/panic-runtime/transitive-link-a-bunch.stderr b/src/test/ui/panic-runtime/transitive-link-a-bunch.stderr index 4af754c81f9..7f4a8ed290e 100644 --- a/src/test/ui/panic-runtime/transitive-link-a-bunch.stderr +++ b/src/test/ui/panic-runtime/transitive-link-a-bunch.stderr @@ -2,9 +2,7 @@ error: cannot link together two panic runtimes: panic_runtime_unwind and panic_r error: the linked panic runtime `panic_runtime_abort` is not compiled with this crate's panic strategy `unwind` -error: the crate `wants_panic_runtime_abort` is compiled with the panic strategy `abort` which is incompatible with this crate's strategy of `unwind` +error: the crate `wants_panic_runtime_abort` requires panic strategy `abort` which is incompatible with this crate's strategy of `unwind` -error: the crate `panic_runtime_abort` is compiled with the panic strategy `abort` which is incompatible with this crate's strategy of `unwind` - -error: aborting due to 4 previous errors +error: aborting due to 3 previous errors diff --git a/src/test/ui/panic-runtime/want-unwind-got-abort.rs b/src/test/ui/panic-runtime/want-unwind-got-abort.rs index c48caaf0790..23bfea6af15 100644 --- a/src/test/ui/panic-runtime/want-unwind-got-abort.rs +++ b/src/test/ui/panic-runtime/want-unwind-got-abort.rs @@ -1,6 +1,6 @@ // build-fail // needs-unwind -// error-pattern:is incompatible with this crate's strategy of `unwind` +// error-pattern:is not compiled with this crate's panic strategy `unwind` // aux-build:panic-runtime-abort.rs // aux-build:panic-runtime-lang-items.rs // ignore-wasm32-bare compiled with panic=abort by default diff --git a/src/test/ui/panic-runtime/want-unwind-got-abort.stderr b/src/test/ui/panic-runtime/want-unwind-got-abort.stderr index d4fd2cca81f..d306ce6c5ea 100644 --- a/src/test/ui/panic-runtime/want-unwind-got-abort.stderr +++ b/src/test/ui/panic-runtime/want-unwind-got-abort.stderr @@ -1,6 +1,4 @@ error: the linked panic runtime `panic_runtime_abort` is not compiled with this crate's panic strategy `unwind` -error: the crate `panic_runtime_abort` is compiled with the panic strategy `abort` which is incompatible with this crate's strategy of `unwind` - -error: aborting due to 2 previous errors +error: aborting due to previous error diff --git a/src/test/ui/panic-runtime/want-unwind-got-abort2.stderr b/src/test/ui/panic-runtime/want-unwind-got-abort2.stderr index 364a27a24eb..014437b7f1b 100644 --- a/src/test/ui/panic-runtime/want-unwind-got-abort2.stderr +++ b/src/test/ui/panic-runtime/want-unwind-got-abort2.stderr @@ -1,8 +1,6 @@ error: the linked panic runtime `panic_runtime_abort` is not compiled with this crate's panic strategy `unwind` -error: the crate `wants_panic_runtime_abort` is compiled with the panic strategy `abort` which is incompatible with this crate's strategy of `unwind` +error: the crate `wants_panic_runtime_abort` requires panic strategy `abort` which is incompatible with this crate's strategy of `unwind` -error: the crate `panic_runtime_abort` is compiled with the panic strategy `abort` which is incompatible with this crate's strategy of `unwind` - -error: aborting due to 3 previous errors +error: aborting due to 2 previous errors diff --git a/src/test/ui/panics/location-detail-unwrap-no-file.rs b/src/test/ui/panics/location-detail-unwrap-no-file.rs index 16cf8a17ff1..5955d9a25ae 100644 --- a/src/test/ui/panics/location-detail-unwrap-no-file.rs +++ b/src/test/ui/panics/location-detail-unwrap-no-file.rs @@ -1,6 +1,6 @@ // run-fail // check-run-results -// compile-flags: -Zlocation-detail=line,column +// compile-flags: -Copt-level=0 -Zlocation-detail=line,column // exec-env:RUST_BACKTRACE=0 fn main() { diff --git a/src/test/ui/parser/fn-header-semantic-fail.stderr b/src/test/ui/parser/fn-header-semantic-fail.stderr index bd3b9181123..75d27c614e2 100644 --- a/src/test/ui/parser/fn-header-semantic-fail.stderr +++ b/src/test/ui/parser/fn-header-semantic-fail.stderr @@ -234,30 +234,30 @@ LL | const async unsafe extern "C" fn ft5(); LL | const async unsafe extern "C" fn ft5() {} | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ impl has extra requirement `(): Future` -error[E0391]: cycle detected when computing type of `main::<impl at $DIR/fn-header-semantic-fail.rs:28:5: 40:6>::ft5::{opaque#0}` +error[E0391]: cycle detected when computing type of `main::<impl at $DIR/fn-header-semantic-fail.rs:28:5: 28:17>::ft5::{opaque#0}` --> $DIR/fn-header-semantic-fail.rs:34:48 | LL | const async unsafe extern "C" fn ft5() {} | ^ | -note: ...which requires borrow-checking `main::<impl at $DIR/fn-header-semantic-fail.rs:28:5: 40:6>::ft5`... +note: ...which requires borrow-checking `main::<impl at $DIR/fn-header-semantic-fail.rs:28:5: 28:17>::ft5`... --> $DIR/fn-header-semantic-fail.rs:34:9 | LL | const async unsafe extern "C" fn ft5() {} | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ -note: ...which requires processing `main::<impl at $DIR/fn-header-semantic-fail.rs:28:5: 40:6>::ft5`... +note: ...which requires processing `main::<impl at $DIR/fn-header-semantic-fail.rs:28:5: 28:17>::ft5`... --> $DIR/fn-header-semantic-fail.rs:34:9 | LL | const async unsafe extern "C" fn ft5() {} | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ -note: ...which requires const checking `main::<impl at $DIR/fn-header-semantic-fail.rs:28:5: 40:6>::ft5`... +note: ...which requires const checking `main::<impl at $DIR/fn-header-semantic-fail.rs:28:5: 28:17>::ft5`... --> $DIR/fn-header-semantic-fail.rs:34:9 | LL | const async unsafe extern "C" fn ft5() {} | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ = note: ...which requires computing whether `impl core::future::future::Future<Output = ()>` is freeze... = note: ...which requires evaluating trait selection obligation `impl core::future::future::Future<Output = ()>: core::marker::Freeze`... - = note: ...which again requires computing type of `main::<impl at $DIR/fn-header-semantic-fail.rs:28:5: 40:6>::ft5::{opaque#0}`, completing the cycle + = note: ...which again requires computing type of `main::<impl at $DIR/fn-header-semantic-fail.rs:28:5: 28:17>::ft5::{opaque#0}`, completing the cycle note: cycle used when checking item types in top-level module --> $DIR/fn-header-semantic-fail.rs:5:1 | @@ -270,30 +270,30 @@ LL | | } LL | | } | |_^ -error[E0391]: cycle detected when computing type of `main::<impl at $DIR/fn-header-semantic-fail.rs:42:5: 50:6>::fi5::{opaque#0}` +error[E0391]: cycle detected when computing type of `main::<impl at $DIR/fn-header-semantic-fail.rs:42:5: 42:11>::fi5::{opaque#0}` --> $DIR/fn-header-semantic-fail.rs:47:48 | LL | const async unsafe extern "C" fn fi5() {} | ^ | -note: ...which requires borrow-checking `main::<impl at $DIR/fn-header-semantic-fail.rs:42:5: 50:6>::fi5`... +note: ...which requires borrow-checking `main::<impl at $DIR/fn-header-semantic-fail.rs:42:5: 42:11>::fi5`... --> $DIR/fn-header-semantic-fail.rs:47:9 | LL | const async unsafe extern "C" fn fi5() {} | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ -note: ...which requires processing `main::<impl at $DIR/fn-header-semantic-fail.rs:42:5: 50:6>::fi5`... +note: ...which requires processing `main::<impl at $DIR/fn-header-semantic-fail.rs:42:5: 42:11>::fi5`... --> $DIR/fn-header-semantic-fail.rs:47:9 | LL | const async unsafe extern "C" fn fi5() {} | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ -note: ...which requires const checking `main::<impl at $DIR/fn-header-semantic-fail.rs:42:5: 50:6>::fi5`... +note: ...which requires const checking `main::<impl at $DIR/fn-header-semantic-fail.rs:42:5: 42:11>::fi5`... --> $DIR/fn-header-semantic-fail.rs:47:9 | LL | const async unsafe extern "C" fn fi5() {} | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ = note: ...which requires computing whether `impl core::future::future::Future<Output = ()>` is freeze... = note: ...which requires evaluating trait selection obligation `impl core::future::future::Future<Output = ()>: core::marker::Freeze`... - = note: ...which again requires computing type of `main::<impl at $DIR/fn-header-semantic-fail.rs:42:5: 50:6>::fi5::{opaque#0}`, completing the cycle + = note: ...which again requires computing type of `main::<impl at $DIR/fn-header-semantic-fail.rs:42:5: 42:11>::fi5::{opaque#0}`, completing the cycle note: cycle used when checking item types in top-level module --> $DIR/fn-header-semantic-fail.rs:5:1 | diff --git a/src/test/ui/pattern/issue-88074-pat-range-type-inference-err.stderr b/src/test/ui/pattern/issue-88074-pat-range-type-inference-err.stderr index 06a279925ed..8e528f8c1db 100644 --- a/src/test/ui/pattern/issue-88074-pat-range-type-inference-err.stderr +++ b/src/test/ui/pattern/issue-88074-pat-range-type-inference-err.stderr @@ -12,8 +12,6 @@ error[E0282]: type annotations needed | LL | Zero::ZERO ..= Zero::ZERO => {}, | ^^^^^^^^^^^^^^^^^^^^^^^^^ cannot infer type - | - = note: type must be known at this point error: aborting due to 2 previous errors diff --git a/src/test/ui/pattern/pat-tuple-bad-type.stderr b/src/test/ui/pattern/pat-tuple-bad-type.stderr index 11b28987848..3342b8e4002 100644 --- a/src/test/ui/pattern/pat-tuple-bad-type.stderr +++ b/src/test/ui/pattern/pat-tuple-bad-type.stderr @@ -3,8 +3,10 @@ error[E0282]: type annotations needed | LL | let x; | ^ +... +LL | (..) => {} + | ---- type must be known at this point | - = note: type must be known at this point help: consider giving `x` an explicit type | LL | let x: _; diff --git a/src/test/ui/pattern/pat-tuple-field-count-cross.stderr b/src/test/ui/pattern/pat-tuple-field-count-cross.stderr index 07b678bc873..019cd414d2e 100644 --- a/src/test/ui/pattern/pat-tuple-field-count-cross.stderr +++ b/src/test/ui/pattern/pat-tuple-field-count-cross.stderr @@ -16,9 +16,9 @@ LL | Z0() => {} ::: $DIR/auxiliary/declarations-for-tuple-field-count-errors.rs:1:1 | LL | pub struct Z0; - | -------------- `Z0` defined here + | ------------- `Z0` defined here LL | pub struct Z1(); - | ---------------- similarly named tuple struct `Z1` defined here + | ------------- similarly named tuple struct `Z1` defined here | help: use this syntax instead | @@ -38,9 +38,9 @@ LL | Z0(x) => {} ::: $DIR/auxiliary/declarations-for-tuple-field-count-errors.rs:1:1 | LL | pub struct Z0; - | -------------- `Z0` defined here + | ------------- `Z0` defined here LL | pub struct Z1(); - | ---------------- similarly named tuple struct `Z1` defined here + | ------------- similarly named tuple struct `Z1` defined here | help: use this syntax instead | @@ -126,7 +126,7 @@ LL | Z1(x) => {} ::: $DIR/auxiliary/declarations-for-tuple-field-count-errors.rs:2:1 | LL | pub struct Z1(); - | ---------------- tuple struct has 0 fields + | ------------- tuple struct has 0 fields error[E0023]: this pattern has 0 fields, but the corresponding tuple struct has 3 fields --> $DIR/pat-tuple-field-count-cross.rs:18:9 diff --git a/src/test/ui/pattern/pat-tuple-overfield.stderr b/src/test/ui/pattern/pat-tuple-overfield.stderr index 1c44f7e5f6f..9e13a2dc9fb 100644 --- a/src/test/ui/pattern/pat-tuple-overfield.stderr +++ b/src/test/ui/pattern/pat-tuple-overfield.stderr @@ -271,7 +271,7 @@ error[E0023]: this pattern has 1 field, but the corresponding tuple struct has 0 --> $DIR/pat-tuple-overfield.rs:59:12 | LL | struct Z1(); - | ------------ tuple struct has 0 fields + | --------- tuple struct has 0 fields ... LL | Z1(_) => {} | ^ expected 0 fields, found 1 @@ -280,7 +280,7 @@ error[E0023]: this pattern has 2 fields, but the corresponding tuple struct has --> $DIR/pat-tuple-overfield.rs:60:12 | LL | struct Z1(); - | ------------ tuple struct has 0 fields + | --------- tuple struct has 0 fields ... LL | Z1(_, _) => {} | ^ ^ expected 0 fields, found 2 diff --git a/src/test/ui/pattern/usefulness/doc-hidden-non-exhaustive.stderr b/src/test/ui/pattern/usefulness/doc-hidden-non-exhaustive.stderr index 296465eb818..643e734f9d4 100644 --- a/src/test/ui/pattern/usefulness/doc-hidden-non-exhaustive.stderr +++ b/src/test/ui/pattern/usefulness/doc-hidden-non-exhaustive.stderr @@ -7,13 +7,8 @@ LL | match HiddenEnum::A { note: `HiddenEnum` defined here --> $DIR/auxiliary/hidden.rs:1:1 | -LL | / pub enum HiddenEnum { -LL | | A, -LL | | B, -LL | | #[doc(hidden)] -LL | | C, -LL | | } - | |_^ +LL | pub enum HiddenEnum { + | ^^^^^^^^^^^^^^^^^^^ = note: the matched value is of type `HiddenEnum` help: ensure that all possible cases are being handled by adding a match arm with a wildcard pattern or an explicit pattern as shown | @@ -30,14 +25,11 @@ LL | match HiddenEnum::A { note: `HiddenEnum` defined here --> $DIR/auxiliary/hidden.rs:3:5 | -LL | / pub enum HiddenEnum { -LL | | A, -LL | | B, - | | ^ not covered -LL | | #[doc(hidden)] -LL | | C, -LL | | } - | |_- +LL | pub enum HiddenEnum { + | ------------------- +LL | A, +LL | B, + | ^ not covered = note: the matched value is of type `HiddenEnum` help: ensure that all possible cases are being handled by adding a match arm with a wildcard pattern or an explicit pattern as shown | @@ -54,14 +46,11 @@ LL | match HiddenEnum::A { note: `HiddenEnum` defined here --> $DIR/auxiliary/hidden.rs:3:5 | -LL | / pub enum HiddenEnum { -LL | | A, -LL | | B, - | | ^ not covered -LL | | #[doc(hidden)] -LL | | C, -LL | | } - | |_- +LL | pub enum HiddenEnum { + | ------------------- +LL | A, +LL | B, + | ^ not covered = note: the matched value is of type `HiddenEnum` help: ensure that all possible cases are being handled by adding a match arm with a wildcard pattern, a match arm with multiple or-patterns as shown, or multiple match arms | @@ -78,15 +67,11 @@ LL | match None { note: `Option<HiddenEnum>` defined here --> $SRC_DIR/core/src/option.rs:LL:COL | -LL | / pub enum Option<T> { -LL | | /// No value. -LL | | #[lang = "None"] -LL | | #[stable(feature = "rust1", since = "1.0.0")] -... | -LL | | Some(#[stable(feature = "rust1", since = "1.0.0")] T), - | | ^^^^ not covered -LL | | } - | |_- +LL | pub enum Option<T> { + | ------------------ +... +LL | Some(#[stable(feature = "rust1", since = "1.0.0")] T), + | ^^^^ not covered = note: the matched value is of type `Option<HiddenEnum>` help: ensure that all possible cases are being handled by adding a match arm with a wildcard pattern, a match arm with multiple or-patterns as shown, or multiple match arms | diff --git a/src/test/ui/pattern/usefulness/issue-35609.stderr b/src/test/ui/pattern/usefulness/issue-35609.stderr index 717bb53c327..2247b818d43 100644 --- a/src/test/ui/pattern/usefulness/issue-35609.stderr +++ b/src/test/ui/pattern/usefulness/issue-35609.stderr @@ -108,14 +108,8 @@ LL | match Some(A) { note: `Option<Enum>` defined here --> $SRC_DIR/core/src/option.rs:LL:COL | -LL | / pub enum Option<T> { -LL | | /// No value. -LL | | #[lang = "None"] -LL | | #[stable(feature = "rust1", since = "1.0.0")] -... | -LL | | Some(#[stable(feature = "rust1", since = "1.0.0")] T), -LL | | } - | |_^ +LL | pub enum Option<T> { + | ^^^^^^^^^^^^^^^^^^ = note: the matched value is of type `Option<Enum>` help: ensure that all possible cases are being handled by adding a match arm with a wildcard pattern as shown, or multiple match arms | diff --git a/src/test/ui/pattern/usefulness/issue-3601.stderr b/src/test/ui/pattern/usefulness/issue-3601.stderr index 4e0adcc1ba2..eb8c63919b6 100644 --- a/src/test/ui/pattern/usefulness/issue-3601.stderr +++ b/src/test/ui/pattern/usefulness/issue-3601.stderr @@ -11,7 +11,7 @@ LL | / pub struct Box< LL | | T: ?Sized, LL | | #[unstable(feature = "allocator_api", issue = "32838")] A: Allocator = Global, LL | | >(Unique<T>, A); - | |________________^ + | |_^ = note: the matched value is of type `Box<ElementKind>` help: ensure that all possible cases are being handled by adding a match arm with a wildcard pattern or an explicit pattern as shown | diff --git a/src/test/ui/pattern/usefulness/match-arm-statics-2.stderr b/src/test/ui/pattern/usefulness/match-arm-statics-2.stderr index 3326e6b85a4..a2b66f5ed67 100644 --- a/src/test/ui/pattern/usefulness/match-arm-statics-2.stderr +++ b/src/test/ui/pattern/usefulness/match-arm-statics-2.stderr @@ -20,18 +20,14 @@ LL | match Some(Some(North)) { note: `Option<Option<Direction>>` defined here --> $SRC_DIR/core/src/option.rs:LL:COL | -LL | / pub enum Option<T> { -LL | | /// No value. -LL | | #[lang = "None"] -LL | | #[stable(feature = "rust1", since = "1.0.0")] -... | -LL | | Some(#[stable(feature = "rust1", since = "1.0.0")] T), - | | ^^^^ - | | | - | | not covered - | | not covered -LL | | } - | |_- +LL | pub enum Option<T> { + | ------------------ +... +LL | Some(#[stable(feature = "rust1", since = "1.0.0")] T), + | ^^^^ + | | + | not covered + | not covered = note: the matched value is of type `Option<Option<Direction>>` help: ensure that all possible cases are being handled by adding a match arm with a wildcard pattern or an explicit pattern as shown | diff --git a/src/test/ui/pattern/usefulness/match-privately-empty.stderr b/src/test/ui/pattern/usefulness/match-privately-empty.stderr index 88178d64291..4607cfaae17 100644 --- a/src/test/ui/pattern/usefulness/match-privately-empty.stderr +++ b/src/test/ui/pattern/usefulness/match-privately-empty.stderr @@ -7,15 +7,11 @@ LL | match private::DATA { note: `Option<Private>` defined here --> $SRC_DIR/core/src/option.rs:LL:COL | -LL | / pub enum Option<T> { -LL | | /// No value. -LL | | #[lang = "None"] -LL | | #[stable(feature = "rust1", since = "1.0.0")] -... | -LL | | Some(#[stable(feature = "rust1", since = "1.0.0")] T), - | | ^^^^ not covered -LL | | } - | |_- +LL | pub enum Option<T> { + | ------------------ +... +LL | Some(#[stable(feature = "rust1", since = "1.0.0")] T), + | ^^^^ not covered = note: the matched value is of type `Option<Private>` help: ensure that all possible cases are being handled by adding a match arm with a wildcard pattern or an explicit pattern as shown | diff --git a/src/test/ui/pattern/usefulness/non-exhaustive-match.stderr b/src/test/ui/pattern/usefulness/non-exhaustive-match.stderr index 89b4e06efda..f2362c316df 100644 --- a/src/test/ui/pattern/usefulness/non-exhaustive-match.stderr +++ b/src/test/ui/pattern/usefulness/non-exhaustive-match.stderr @@ -37,15 +37,11 @@ LL | match Some(10) { note: `Option<i32>` defined here --> $SRC_DIR/core/src/option.rs:LL:COL | -LL | / pub enum Option<T> { -LL | | /// No value. -LL | | #[lang = "None"] -LL | | #[stable(feature = "rust1", since = "1.0.0")] -... | -LL | | Some(#[stable(feature = "rust1", since = "1.0.0")] T), - | | ^^^^ not covered -LL | | } - | |_- +LL | pub enum Option<T> { + | ------------------ +... +LL | Some(#[stable(feature = "rust1", since = "1.0.0")] T), + | ^^^^ not covered = note: the matched value is of type `Option<i32>` help: ensure that all possible cases are being handled by adding a match arm with a wildcard pattern or an explicit pattern as shown | diff --git a/src/test/ui/pattern/usefulness/stable-gated-patterns.stderr b/src/test/ui/pattern/usefulness/stable-gated-patterns.stderr index 559539178cb..98c75953add 100644 --- a/src/test/ui/pattern/usefulness/stable-gated-patterns.stderr +++ b/src/test/ui/pattern/usefulness/stable-gated-patterns.stderr @@ -7,16 +7,11 @@ LL | match UnstableEnum::Stable { note: `UnstableEnum` defined here --> $DIR/auxiliary/unstable.rs:9:5 | -LL | / pub enum UnstableEnum { -LL | | #[stable(feature = "stable_test_feature", since = "1.0.0")] -LL | | Stable, -LL | | #[stable(feature = "stable_test_feature", since = "1.0.0")] -LL | | Stable2, - | | ^^^^^^^ not covered -LL | | #[unstable(feature = "unstable_test_feature", issue = "none")] -LL | | Unstable, -LL | | } - | |_- +LL | pub enum UnstableEnum { + | --------------------- +... +LL | Stable2, + | ^^^^^^^ not covered = note: the matched value is of type `UnstableEnum` help: ensure that all possible cases are being handled by adding a match arm with a wildcard pattern, a match arm with multiple or-patterns as shown, or multiple match arms | @@ -33,14 +28,8 @@ LL | match UnstableEnum::Stable { note: `UnstableEnum` defined here --> $DIR/auxiliary/unstable.rs:5:1 | -LL | / pub enum UnstableEnum { -LL | | #[stable(feature = "stable_test_feature", since = "1.0.0")] -LL | | Stable, -LL | | #[stable(feature = "stable_test_feature", since = "1.0.0")] -... | -LL | | Unstable, -LL | | } - | |_^ +LL | pub enum UnstableEnum { + | ^^^^^^^^^^^^^^^^^^^^^ = note: the matched value is of type `UnstableEnum` help: ensure that all possible cases are being handled by adding a match arm with a wildcard pattern or an explicit pattern as shown | diff --git a/src/test/ui/pattern/usefulness/unstable-gated-patterns.stderr b/src/test/ui/pattern/usefulness/unstable-gated-patterns.stderr index b5f1805deef..f07a25ca89b 100644 --- a/src/test/ui/pattern/usefulness/unstable-gated-patterns.stderr +++ b/src/test/ui/pattern/usefulness/unstable-gated-patterns.stderr @@ -7,15 +7,11 @@ LL | match UnstableEnum::Stable { note: `UnstableEnum` defined here --> $DIR/auxiliary/unstable.rs:11:5 | -LL | / pub enum UnstableEnum { -LL | | #[stable(feature = "stable_test_feature", since = "1.0.0")] -LL | | Stable, -LL | | #[stable(feature = "stable_test_feature", since = "1.0.0")] -... | -LL | | Unstable, - | | ^^^^^^^^ not covered -LL | | } - | |_- +LL | pub enum UnstableEnum { + | --------------------- +... +LL | Unstable, + | ^^^^^^^^ not covered = note: the matched value is of type `UnstableEnum` help: ensure that all possible cases are being handled by adding a match arm with a wildcard pattern or an explicit pattern as shown | diff --git a/src/test/ui/polymorphization/generators.rs b/src/test/ui/polymorphization/generators.rs index 68ea4a026d7..779bac0ace2 100644 --- a/src/test/ui/polymorphization/generators.rs +++ b/src/test/ui/polymorphization/generators.rs @@ -1,5 +1,5 @@ // build-fail -// compile-flags:-Zpolymorphize=on +// compile-flags:-Zpolymorphize=on -Zinline-mir=off #![feature(generic_const_exprs, generators, generator_trait, rustc_attrs)] //~^ WARN the feature `generic_const_exprs` is incomplete diff --git a/src/test/ui/polymorphization/predicates.rs b/src/test/ui/polymorphization/predicates.rs index dea1e21e77f..6a5fc2e33de 100644 --- a/src/test/ui/polymorphization/predicates.rs +++ b/src/test/ui/polymorphization/predicates.rs @@ -1,5 +1,6 @@ // build-fail -// compile-flags:-Zpolymorphize=on +// compile-flags: -Copt-level=0 -Zpolymorphize=on + #![feature(rustc_attrs)] // This test checks that `T` is considered used in `foo`, because it is used in a predicate for diff --git a/src/test/ui/polymorphization/predicates.stderr b/src/test/ui/polymorphization/predicates.stderr index dc6ebceae21..6a74e63fdfe 100644 --- a/src/test/ui/polymorphization/predicates.stderr +++ b/src/test/ui/polymorphization/predicates.stderr @@ -1,17 +1,17 @@ error: item has unused generic parameters - --> $DIR/predicates.rs:14:4 + --> $DIR/predicates.rs:15:4 | LL | fn foo<I, T>(_: I) | ^^^ - generic parameter `T` is unused error: item has unused generic parameters - --> $DIR/predicates.rs:23:4 + --> $DIR/predicates.rs:24:4 | LL | fn baz<I, T>(_: I) | ^^^ - generic parameter `T` is unused error: item has unused generic parameters - --> $DIR/predicates.rs:44:19 + --> $DIR/predicates.rs:45:19 | LL | impl<'a, I, T: 'a, E> Iterator for Foo<'a, I, E> | - - generic parameter `E` is unused @@ -22,7 +22,7 @@ LL | self.find(|_| true) | ^^^^^^^^ error: item has unused generic parameters - --> $DIR/predicates.rs:58:4 + --> $DIR/predicates.rs:59:4 | LL | fn quux<A, B, C: Default>() -> usize | ^^^^ - - generic parameter `B` is unused @@ -30,19 +30,19 @@ LL | fn quux<A, B, C: Default>() -> usize | generic parameter `A` is unused error: item has unused generic parameters - --> $DIR/predicates.rs:75:4 + --> $DIR/predicates.rs:76:4 | LL | fn foobar<F, G>() -> usize | ^^^^^^ - generic parameter `F` is unused error: item has unused generic parameters - --> $DIR/predicates.rs:9:4 + --> $DIR/predicates.rs:10:4 | LL | fn bar<I>() { | ^^^ - generic parameter `I` is unused note: the above error was encountered while instantiating `fn foo::<std::slice::Iter<u32>, T>` - --> $DIR/predicates.rs:85:5 + --> $DIR/predicates.rs:86:5 | LL | foo(x.iter()); | ^^^^^^^^^^^^^ diff --git a/src/test/ui/privacy/issue-30079.stderr b/src/test/ui/privacy/issue-30079.stderr index e40b1942059..dc98cfe3bb6 100644 --- a/src/test/ui/privacy/issue-30079.stderr +++ b/src/test/ui/privacy/issue-30079.stderr @@ -12,19 +12,19 @@ error[E0446]: private type `m2::Priv` in public interface --> $DIR/issue-30079.rs:18:9 | LL | struct Priv; - | ------------ `m2::Priv` declared as private + | ----------- `m2::Priv` declared as private LL | impl ::std::ops::Deref for ::SemiPriv { LL | type Target = Priv; - | ^^^^^^^^^^^^^^^^^^^ can't leak private type + | ^^^^^^^^^^^ can't leak private type error[E0446]: private type `m3::Priv` in public interface --> $DIR/issue-30079.rs:35:9 | LL | struct Priv; - | ------------ `m3::Priv` declared as private + | ----------- `m3::Priv` declared as private LL | impl ::SemiPrivTrait for () { LL | type Assoc = Priv; - | ^^^^^^^^^^^^^^^^^^ can't leak private type + | ^^^^^^^^^^ can't leak private type error: aborting due to 2 previous errors; 1 warning emitted diff --git a/src/test/ui/privacy/privacy5.stderr b/src/test/ui/privacy/privacy5.stderr index d0c0c6b8bb5..680161272ce 100644 --- a/src/test/ui/privacy/privacy5.stderr +++ b/src/test/ui/privacy/privacy5.stderr @@ -373,7 +373,7 @@ note: the tuple struct constructor `A` is defined here --> $DIR/auxiliary/privacy_tuple_struct.rs:1:1 | LL | pub struct A(()); - | ^^^^^^^^^^^^^^^^^ + | ^^^^^^^^^^^^ error[E0603]: tuple struct constructor `B` is private --> $DIR/privacy5.rs:91:20 @@ -390,7 +390,7 @@ note: the tuple struct constructor `B` is defined here --> $DIR/auxiliary/privacy_tuple_struct.rs:2:1 | LL | pub struct B(isize); - | ^^^^^^^^^^^^^^^^^^^^ + | ^^^^^^^^^^^^ error[E0603]: tuple struct constructor `C` is private --> $DIR/privacy5.rs:92:20 @@ -407,7 +407,7 @@ note: the tuple struct constructor `C` is defined here --> $DIR/auxiliary/privacy_tuple_struct.rs:3:1 | LL | pub struct C(pub isize, isize); - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | ^^^^^^^^^^^^ error[E0603]: tuple struct constructor `A` is private --> $DIR/privacy5.rs:95:16 @@ -424,7 +424,7 @@ note: the tuple struct constructor `A` is defined here --> $DIR/auxiliary/privacy_tuple_struct.rs:1:1 | LL | pub struct A(()); - | ^^^^^^^^^^^^^^^^^ + | ^^^^^^^^^^^^ error[E0603]: tuple struct constructor `A` is private --> $DIR/privacy5.rs:96:16 @@ -441,7 +441,7 @@ note: the tuple struct constructor `A` is defined here --> $DIR/auxiliary/privacy_tuple_struct.rs:1:1 | LL | pub struct A(()); - | ^^^^^^^^^^^^^^^^^ + | ^^^^^^^^^^^^ error[E0603]: tuple struct constructor `A` is private --> $DIR/privacy5.rs:97:22 @@ -458,7 +458,7 @@ note: the tuple struct constructor `A` is defined here --> $DIR/auxiliary/privacy_tuple_struct.rs:1:1 | LL | pub struct A(()); - | ^^^^^^^^^^^^^^^^^ + | ^^^^^^^^^^^^ error[E0603]: tuple struct constructor `A` is private --> $DIR/privacy5.rs:98:22 @@ -475,7 +475,7 @@ note: the tuple struct constructor `A` is defined here --> $DIR/auxiliary/privacy_tuple_struct.rs:1:1 | LL | pub struct A(()); - | ^^^^^^^^^^^^^^^^^ + | ^^^^^^^^^^^^ error[E0603]: tuple struct constructor `B` is private --> $DIR/privacy5.rs:100:16 @@ -492,7 +492,7 @@ note: the tuple struct constructor `B` is defined here --> $DIR/auxiliary/privacy_tuple_struct.rs:2:1 | LL | pub struct B(isize); - | ^^^^^^^^^^^^^^^^^^^^ + | ^^^^^^^^^^^^ error[E0603]: tuple struct constructor `B` is private --> $DIR/privacy5.rs:101:16 @@ -509,7 +509,7 @@ note: the tuple struct constructor `B` is defined here --> $DIR/auxiliary/privacy_tuple_struct.rs:2:1 | LL | pub struct B(isize); - | ^^^^^^^^^^^^^^^^^^^^ + | ^^^^^^^^^^^^ error[E0603]: tuple struct constructor `B` is private --> $DIR/privacy5.rs:102:22 @@ -526,7 +526,7 @@ note: the tuple struct constructor `B` is defined here --> $DIR/auxiliary/privacy_tuple_struct.rs:2:1 | LL | pub struct B(isize); - | ^^^^^^^^^^^^^^^^^^^^ + | ^^^^^^^^^^^^ error[E0603]: tuple struct constructor `B` is private --> $DIR/privacy5.rs:103:22 @@ -543,7 +543,7 @@ note: the tuple struct constructor `B` is defined here --> $DIR/auxiliary/privacy_tuple_struct.rs:2:1 | LL | pub struct B(isize); - | ^^^^^^^^^^^^^^^^^^^^ + | ^^^^^^^^^^^^ error[E0603]: tuple struct constructor `B` is private --> $DIR/privacy5.rs:104:22 @@ -560,7 +560,7 @@ note: the tuple struct constructor `B` is defined here --> $DIR/auxiliary/privacy_tuple_struct.rs:2:1 | LL | pub struct B(isize); - | ^^^^^^^^^^^^^^^^^^^^ + | ^^^^^^^^^^^^ error[E0603]: tuple struct constructor `B` is private --> $DIR/privacy5.rs:105:16 @@ -577,7 +577,7 @@ note: the tuple struct constructor `B` is defined here --> $DIR/auxiliary/privacy_tuple_struct.rs:2:1 | LL | pub struct B(isize); - | ^^^^^^^^^^^^^^^^^^^^ + | ^^^^^^^^^^^^ error[E0603]: tuple struct constructor `C` is private --> $DIR/privacy5.rs:107:16 @@ -594,7 +594,7 @@ note: the tuple struct constructor `C` is defined here --> $DIR/auxiliary/privacy_tuple_struct.rs:3:1 | LL | pub struct C(pub isize, isize); - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | ^^^^^^^^^^^^ error[E0603]: tuple struct constructor `C` is private --> $DIR/privacy5.rs:108:16 @@ -611,7 +611,7 @@ note: the tuple struct constructor `C` is defined here --> $DIR/auxiliary/privacy_tuple_struct.rs:3:1 | LL | pub struct C(pub isize, isize); - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | ^^^^^^^^^^^^ error[E0603]: tuple struct constructor `C` is private --> $DIR/privacy5.rs:109:16 @@ -628,7 +628,7 @@ note: the tuple struct constructor `C` is defined here --> $DIR/auxiliary/privacy_tuple_struct.rs:3:1 | LL | pub struct C(pub isize, isize); - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | ^^^^^^^^^^^^ error[E0603]: tuple struct constructor `C` is private --> $DIR/privacy5.rs:110:16 @@ -645,7 +645,7 @@ note: the tuple struct constructor `C` is defined here --> $DIR/auxiliary/privacy_tuple_struct.rs:3:1 | LL | pub struct C(pub isize, isize); - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | ^^^^^^^^^^^^ error[E0603]: tuple struct constructor `C` is private --> $DIR/privacy5.rs:111:22 @@ -662,7 +662,7 @@ note: the tuple struct constructor `C` is defined here --> $DIR/auxiliary/privacy_tuple_struct.rs:3:1 | LL | pub struct C(pub isize, isize); - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | ^^^^^^^^^^^^ error[E0603]: tuple struct constructor `C` is private --> $DIR/privacy5.rs:112:22 @@ -679,7 +679,7 @@ note: the tuple struct constructor `C` is defined here --> $DIR/auxiliary/privacy_tuple_struct.rs:3:1 | LL | pub struct C(pub isize, isize); - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | ^^^^^^^^^^^^ error[E0603]: tuple struct constructor `C` is private --> $DIR/privacy5.rs:113:22 @@ -696,7 +696,7 @@ note: the tuple struct constructor `C` is defined here --> $DIR/auxiliary/privacy_tuple_struct.rs:3:1 | LL | pub struct C(pub isize, isize); - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | ^^^^^^^^^^^^ error[E0603]: tuple struct constructor `C` is private --> $DIR/privacy5.rs:114:22 @@ -713,7 +713,7 @@ note: the tuple struct constructor `C` is defined here --> $DIR/auxiliary/privacy_tuple_struct.rs:3:1 | LL | pub struct C(pub isize, isize); - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | ^^^^^^^^^^^^ error[E0603]: tuple struct constructor `A` is private --> $DIR/privacy5.rs:122:21 @@ -730,7 +730,7 @@ note: the tuple struct constructor `A` is defined here --> $DIR/auxiliary/privacy_tuple_struct.rs:1:1 | LL | pub struct A(()); - | ^^^^^^^^^^^^^^^^^ + | ^^^^^^^^^^^^ error[E0603]: tuple struct constructor `B` is private --> $DIR/privacy5.rs:123:21 @@ -747,7 +747,7 @@ note: the tuple struct constructor `B` is defined here --> $DIR/auxiliary/privacy_tuple_struct.rs:2:1 | LL | pub struct B(isize); - | ^^^^^^^^^^^^^^^^^^^^ + | ^^^^^^^^^^^^ error[E0603]: tuple struct constructor `C` is private --> $DIR/privacy5.rs:124:21 @@ -764,7 +764,7 @@ note: the tuple struct constructor `C` is defined here --> $DIR/auxiliary/privacy_tuple_struct.rs:3:1 | LL | pub struct C(pub isize, isize); - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | ^^^^^^^^^^^^ error: aborting due to 48 previous errors diff --git a/src/test/ui/privacy/private-in-public-assoc-ty.stderr b/src/test/ui/privacy/private-in-public-assoc-ty.stderr index ba62a228b09..1abeafe398f 100644 --- a/src/test/ui/privacy/private-in-public-assoc-ty.stderr +++ b/src/test/ui/privacy/private-in-public-assoc-ty.stderr @@ -2,16 +2,16 @@ error[E0446]: private type `Priv` in public interface --> $DIR/private-in-public-assoc-ty.rs:17:9 | LL | struct Priv; - | ------------ `Priv` declared as private + | ----------- `Priv` declared as private ... LL | type A = Priv; - | ^^^^^^^^^^^^^^ can't leak private type + | ^^^^^^ can't leak private type warning: private trait `PrivTr` in public interface (error E0445) --> $DIR/private-in-public-assoc-ty.rs:24:9 | LL | type Alias1: PrivTr; - | ^^^^^^^^^^^^^^^^^^^^ + | ^^^^^^^^^^^^^^^^^^^ | = note: `#[warn(private_in_public)]` on by default = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release! @@ -21,7 +21,7 @@ warning: private type `Priv` in public interface (error E0446) --> $DIR/private-in-public-assoc-ty.rs:27:9 | LL | type Alias2: PubTrAux1<Priv> = u8; - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ | = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release! = note: for more information, see issue #34537 <https://github.com/rust-lang/rust/issues/34537> @@ -30,7 +30,7 @@ warning: private type `Priv` in public interface (error E0446) --> $DIR/private-in-public-assoc-ty.rs:30:9 | LL | type Alias3: PubTrAux2<A = Priv> = u8; - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ | = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release! = note: for more information, see issue #34537 <https://github.com/rust-lang/rust/issues/34537> @@ -39,19 +39,19 @@ error[E0446]: private type `Priv` in public interface --> $DIR/private-in-public-assoc-ty.rs:34:9 | LL | struct Priv; - | ------------ `Priv` declared as private + | ----------- `Priv` declared as private ... LL | type Alias4 = Priv; - | ^^^^^^^^^^^^^^^^^^^ can't leak private type + | ^^^^^^^^^^^ can't leak private type error[E0446]: private type `Priv` in public interface --> $DIR/private-in-public-assoc-ty.rs:41:9 | LL | struct Priv; - | ------------ `Priv` declared as private + | ----------- `Priv` declared as private ... LL | type Alias1 = Priv; - | ^^^^^^^^^^^^^^^^^^^ can't leak private type + | ^^^^^^^^^^^ can't leak private type error[E0445]: private trait `PrivTr` in public interface --> $DIR/private-in-public-assoc-ty.rs:44:9 @@ -60,7 +60,7 @@ LL | trait PrivTr {} | ------------ `PrivTr` declared as private ... LL | type Exist = impl PrivTr; - | ^^^^^^^^^^^^^^^^^^^^^^^^^ can't leak private trait + | ^^^^^^^^^^ can't leak private trait error: aborting due to 4 previous errors; 3 warnings emitted diff --git a/src/test/ui/privacy/private-in-public-lint.stderr b/src/test/ui/privacy/private-in-public-lint.stderr index dd5f5b6f8f8..1e98e3bed14 100644 --- a/src/test/ui/privacy/private-in-public-lint.stderr +++ b/src/test/ui/privacy/private-in-public-lint.stderr @@ -2,7 +2,7 @@ error[E0446]: private type `m1::Priv` in public interface --> $DIR/private-in-public-lint.rs:6:9 | LL | struct Priv; - | ------------ `m1::Priv` declared as private + | ----------- `m1::Priv` declared as private ... LL | pub fn f() -> Priv {Priv} | ^^^^^^^^^^^^^^^^^^ can't leak private type @@ -11,7 +11,7 @@ error[E0446]: private type `m2::Priv` in public interface --> $DIR/private-in-public-lint.rs:15:9 | LL | struct Priv; - | ------------ `m2::Priv` declared as private + | ----------- `m2::Priv` declared as private ... LL | pub fn f() -> Priv {Priv} | ^^^^^^^^^^^^^^^^^^ can't leak private type diff --git a/src/test/ui/privacy/private-in-public-warn.stderr b/src/test/ui/privacy/private-in-public-warn.stderr index 5f2c4935bad..f2ff6cf2fdb 100644 --- a/src/test/ui/privacy/private-in-public-warn.stderr +++ b/src/test/ui/privacy/private-in-public-warn.stderr @@ -2,7 +2,7 @@ error: private type `types::Priv` in public interface (error E0446) --> $DIR/private-in-public-warn.rs:15:5 | LL | pub type Alias = Priv; - | ^^^^^^^^^^^^^^^^^^^^^^ + | ^^^^^^^^^^^^^^ | note: the lint level is defined here --> $DIR/private-in-public-warn.rs:5:9 @@ -34,7 +34,7 @@ error: private type `types::Priv` in public interface (error E0446) --> $DIR/private-in-public-warn.rs:24:9 | LL | const C: Priv = Priv; - | ^^^^^^^^^^^^^^^^^^^^^ + | ^^^^^^^^^^^^^ | = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release! = note: for more information, see issue #34537 <https://github.com/rust-lang/rust/issues/34537> @@ -43,10 +43,10 @@ error[E0446]: private type `types::Priv` in public interface --> $DIR/private-in-public-warn.rs:26:9 | LL | struct Priv; - | ------------ `types::Priv` declared as private + | ----------- `types::Priv` declared as private ... LL | type Alias = Priv; - | ^^^^^^^^^^^^^^^^^^ can't leak private type + | ^^^^^^^^^^ can't leak private type error: private type `types::Priv` in public interface (error E0446) --> $DIR/private-in-public-warn.rs:27:9 @@ -70,7 +70,7 @@ error: private type `types::Priv` in public interface (error E0446) --> $DIR/private-in-public-warn.rs:33:9 | LL | pub static ES: Priv; - | ^^^^^^^^^^^^^^^^^^^^ + | ^^^^^^^^^^^^^^^^^^^ | = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release! = note: for more information, see issue #34537 <https://github.com/rust-lang/rust/issues/34537> @@ -79,7 +79,7 @@ error: private type `types::Priv` in public interface (error E0446) --> $DIR/private-in-public-warn.rs:35:9 | LL | pub fn ef1(arg: Priv); - | ^^^^^^^^^^^^^^^^^^^^^^ + | ^^^^^^^^^^^^^^^^^^^^^ | = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release! = note: for more information, see issue #34537 <https://github.com/rust-lang/rust/issues/34537> @@ -88,7 +88,7 @@ error: private type `types::Priv` in public interface (error E0446) --> $DIR/private-in-public-warn.rs:37:9 | LL | pub fn ef2() -> Priv; - | ^^^^^^^^^^^^^^^^^^^^^ + | ^^^^^^^^^^^^^^^^^^^^ | = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release! = note: for more information, see issue #34537 <https://github.com/rust-lang/rust/issues/34537> @@ -97,16 +97,16 @@ error[E0446]: private type `types::Priv` in public interface --> $DIR/private-in-public-warn.rs:41:9 | LL | struct Priv; - | ------------ `types::Priv` declared as private + | ----------- `types::Priv` declared as private ... LL | type Alias = Priv; - | ^^^^^^^^^^^^^^^^^^ can't leak private type + | ^^^^^^^^^^ can't leak private type error: private trait `traits::PrivTr` in public interface (error E0445) --> $DIR/private-in-public-warn.rs:50:5 | LL | pub type Alias<T: PrivTr> = T; - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | ^^^^^^^^^^^^^^^^^^^^^^^^^ | = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release! = note: for more information, see issue #34537 <https://github.com/rust-lang/rust/issues/34537> @@ -115,7 +115,7 @@ error: private trait `traits::PrivTr` in public interface (error E0445) --> $DIR/private-in-public-warn.rs:53:5 | LL | pub trait Tr1: PrivTr {} - | ^^^^^^^^^^^^^^^^^^^^^^^^ + | ^^^^^^^^^^^^^^^^^^^^^ | = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release! = note: for more information, see issue #34537 <https://github.com/rust-lang/rust/issues/34537> @@ -124,7 +124,7 @@ error: private trait `traits::PrivTr` in public interface (error E0445) --> $DIR/private-in-public-warn.rs:55:5 | LL | pub trait Tr2<T: PrivTr> {} - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | ^^^^^^^^^^^^^^^^^^^^^^^^ | = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release! = note: for more information, see issue #34537 <https://github.com/rust-lang/rust/issues/34537> @@ -133,7 +133,7 @@ error: private trait `traits::PrivTr` in public interface (error E0445) --> $DIR/private-in-public-warn.rs:58:9 | LL | type Alias: PrivTr; - | ^^^^^^^^^^^^^^^^^^^ + | ^^^^^^^^^^^^^^^^^^ | = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release! = note: for more information, see issue #34537 <https://github.com/rust-lang/rust/issues/34537> @@ -151,7 +151,7 @@ error: private trait `traits::PrivTr` in public interface (error E0445) --> $DIR/private-in-public-warn.rs:64:5 | LL | impl<T: PrivTr> Pub<T> {} - | ^^^^^^^^^^^^^^^^^^^^^^^^^ + | ^^^^^^^^^^^^^^^^^^^^^^ | = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release! = note: for more information, see issue #34537 <https://github.com/rust-lang/rust/issues/34537> @@ -160,7 +160,7 @@ error: private trait `traits_where::PrivTr` in public interface (error E0445) --> $DIR/private-in-public-warn.rs:74:5 | LL | pub type Alias<T> where T: PrivTr = T; - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | ^^^^^^^^^^^^^^^^^ | = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release! = note: for more information, see issue #34537 <https://github.com/rust-lang/rust/issues/34537> @@ -169,7 +169,7 @@ error: private trait `traits_where::PrivTr` in public interface (error E0445) --> $DIR/private-in-public-warn.rs:78:5 | LL | pub trait Tr2<T> where T: PrivTr {} - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | ^^^^^^^^^^^^^^^^ | = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release! = note: for more information, see issue #34537 <https://github.com/rust-lang/rust/issues/34537> @@ -187,7 +187,7 @@ error: private trait `traits_where::PrivTr` in public interface (error E0445) --> $DIR/private-in-public-warn.rs:86:5 | LL | impl<T> Pub<T> where T: PrivTr {} - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | ^^^^^^^^^^^^^^ | = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release! = note: for more information, see issue #34537 <https://github.com/rust-lang/rust/issues/34537> @@ -196,7 +196,7 @@ error: private trait `generics::PrivTr<generics::Pub>` in public interface (erro --> $DIR/private-in-public-warn.rs:98:5 | LL | pub trait Tr1: PrivTr<Pub> {} - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | ^^^^^^^^^^^^^^^^^^^^^^^^^^ | = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release! = note: for more information, see issue #34537 <https://github.com/rust-lang/rust/issues/34537> @@ -205,7 +205,7 @@ error: private type `generics::Priv` in public interface (error E0446) --> $DIR/private-in-public-warn.rs:101:5 | LL | pub trait Tr2: PubTr<Priv> {} - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | ^^^^^^^^^^^^^^^^^^^^^^^^^^ | = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release! = note: for more information, see issue #34537 <https://github.com/rust-lang/rust/issues/34537> @@ -214,7 +214,7 @@ error: private type `generics::Priv` in public interface (error E0446) --> $DIR/private-in-public-warn.rs:103:5 | LL | pub trait Tr3: PubTr<[Priv; 1]> {} - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ | = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release! = note: for more information, see issue #34537 <https://github.com/rust-lang/rust/issues/34537> @@ -223,7 +223,7 @@ error: private type `generics::Priv` in public interface (error E0446) --> $DIR/private-in-public-warn.rs:105:5 | LL | pub trait Tr4: PubTr<Pub<Priv>> {} - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ | = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release! = note: for more information, see issue #34537 <https://github.com/rust-lang/rust/issues/34537> @@ -232,10 +232,10 @@ error[E0446]: private type `impls::Priv` in public interface --> $DIR/private-in-public-warn.rs:132:9 | LL | struct Priv; - | ------------ `impls::Priv` declared as private + | ----------- `impls::Priv` declared as private ... LL | type Alias = Priv; - | ^^^^^^^^^^^^^^^^^^ can't leak private type + | ^^^^^^^^^^ can't leak private type error: private type `aliases_pub::Priv` in public interface (error E0446) --> $DIR/private-in-public-warn.rs:203:9 @@ -250,43 +250,43 @@ error[E0446]: private type `aliases_pub::Priv` in public interface --> $DIR/private-in-public-warn.rs:207:9 | LL | struct Priv; - | ------------ `aliases_pub::Priv` declared as private + | ----------- `aliases_pub::Priv` declared as private ... LL | type Check = Priv; - | ^^^^^^^^^^^^^^^^^^ can't leak private type + | ^^^^^^^^^^ can't leak private type error[E0446]: private type `aliases_pub::Priv` in public interface --> $DIR/private-in-public-warn.rs:210:9 | LL | struct Priv; - | ------------ `aliases_pub::Priv` declared as private + | ----------- `aliases_pub::Priv` declared as private ... LL | type Check = Priv; - | ^^^^^^^^^^^^^^^^^^ can't leak private type + | ^^^^^^^^^^ can't leak private type error[E0446]: private type `aliases_pub::Priv` in public interface --> $DIR/private-in-public-warn.rs:213:9 | LL | struct Priv; - | ------------ `aliases_pub::Priv` declared as private + | ----------- `aliases_pub::Priv` declared as private ... LL | type Check = Priv; - | ^^^^^^^^^^^^^^^^^^ can't leak private type + | ^^^^^^^^^^ can't leak private type error[E0446]: private type `aliases_pub::Priv` in public interface --> $DIR/private-in-public-warn.rs:216:9 | LL | struct Priv; - | ------------ `aliases_pub::Priv` declared as private + | ----------- `aliases_pub::Priv` declared as private ... LL | type Check = Priv; - | ^^^^^^^^^^^^^^^^^^ can't leak private type + | ^^^^^^^^^^ can't leak private type error: private trait `PrivTr1` in public interface (error E0445) --> $DIR/private-in-public-warn.rs:246:5 | LL | pub trait Tr1: PrivUseAliasTr {} - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ | = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release! = note: for more information, see issue #34537 <https://github.com/rust-lang/rust/issues/34537> @@ -295,7 +295,7 @@ error: private trait `PrivTr1<Priv2>` in public interface (error E0445) --> $DIR/private-in-public-warn.rs:249:5 | LL | pub trait Tr2: PrivUseAliasTr<PrivAlias> {} - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ | = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release! = note: for more information, see issue #34537 <https://github.com/rust-lang/rust/issues/34537> @@ -304,7 +304,7 @@ error: private type `Priv2` in public interface (error E0446) --> $DIR/private-in-public-warn.rs:249:5 | LL | pub trait Tr2: PrivUseAliasTr<PrivAlias> {} - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ | = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release! = note: for more information, see issue #34537 <https://github.com/rust-lang/rust/issues/34537> diff --git a/src/test/ui/privacy/private-in-public.stderr b/src/test/ui/privacy/private-in-public.stderr index e8bb2cde4be..887eebf53ef 100644 --- a/src/test/ui/privacy/private-in-public.stderr +++ b/src/test/ui/privacy/private-in-public.stderr @@ -2,25 +2,25 @@ error[E0446]: private type `types::Priv` in public interface --> $DIR/private-in-public.rs:13:5 | LL | struct Priv; - | ------------ `types::Priv` declared as private + | ----------- `types::Priv` declared as private ... LL | pub const C: Priv = Priv; - | ^^^^^^^^^^^^^^^^^^^^^^^^^ can't leak private type + | ^^^^^^^^^^^^^^^^^ can't leak private type error[E0446]: private type `types::Priv` in public interface --> $DIR/private-in-public.rs:14:5 | LL | struct Priv; - | ------------ `types::Priv` declared as private + | ----------- `types::Priv` declared as private ... LL | pub static S: Priv = Priv; - | ^^^^^^^^^^^^^^^^^^^^^^^^^^ can't leak private type + | ^^^^^^^^^^^^^^^^^^ can't leak private type error[E0446]: private type `types::Priv` in public interface --> $DIR/private-in-public.rs:15:5 | LL | struct Priv; - | ------------ `types::Priv` declared as private + | ----------- `types::Priv` declared as private ... LL | pub fn f1(arg: Priv) {} | ^^^^^^^^^^^^^^^^^^^^ can't leak private type @@ -29,7 +29,7 @@ error[E0446]: private type `types::Priv` in public interface --> $DIR/private-in-public.rs:16:5 | LL | struct Priv; - | ------------ `types::Priv` declared as private + | ----------- `types::Priv` declared as private ... LL | pub fn f2() -> Priv { panic!() } | ^^^^^^^^^^^^^^^^^^^ can't leak private type @@ -38,7 +38,7 @@ error[E0446]: private type `types::Priv` in public interface --> $DIR/private-in-public.rs:17:19 | LL | struct Priv; - | ------------ `types::Priv` declared as private + | ----------- `types::Priv` declared as private ... LL | pub struct S1(pub Priv); | ^^^^^^^^ can't leak private type @@ -47,7 +47,7 @@ error[E0446]: private type `types::Priv` in public interface --> $DIR/private-in-public.rs:18:21 | LL | struct Priv; - | ------------ `types::Priv` declared as private + | ----------- `types::Priv` declared as private ... LL | pub struct S2 { pub field: Priv } | ^^^^^^^^^^^^^^^ can't leak private type @@ -56,16 +56,16 @@ error[E0446]: private type `types::Priv` in public interface --> $DIR/private-in-public.rs:20:9 | LL | struct Priv; - | ------------ `types::Priv` declared as private + | ----------- `types::Priv` declared as private ... LL | pub const C: Priv = Priv; - | ^^^^^^^^^^^^^^^^^^^^^^^^^ can't leak private type + | ^^^^^^^^^^^^^^^^^ can't leak private type error[E0446]: private type `types::Priv` in public interface --> $DIR/private-in-public.rs:21:9 | LL | struct Priv; - | ------------ `types::Priv` declared as private + | ----------- `types::Priv` declared as private ... LL | pub fn f1(arg: Priv) {} | ^^^^^^^^^^^^^^^^^^^^ can't leak private type @@ -74,7 +74,7 @@ error[E0446]: private type `types::Priv` in public interface --> $DIR/private-in-public.rs:22:9 | LL | struct Priv; - | ------------ `types::Priv` declared as private + | ----------- `types::Priv` declared as private ... LL | pub fn f2() -> Priv { panic!() } | ^^^^^^^^^^^^^^^^^^^ can't leak private type @@ -86,7 +86,7 @@ LL | trait PrivTr {} | ------------ `traits::PrivTr` declared as private ... LL | pub enum E<T: PrivTr> { V(T) } - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ can't leak private trait + | ^^^^^^^^^^^^^^^^^^^^^ can't leak private trait error[E0445]: private trait `traits::PrivTr` in public interface --> $DIR/private-in-public.rs:32:5 @@ -104,18 +104,16 @@ LL | trait PrivTr {} | ------------ `traits::PrivTr` declared as private ... LL | pub struct S1<T: PrivTr>(T); - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ can't leak private trait + | ^^^^^^^^^^^^^^^^^^^^^^^^ can't leak private trait error[E0445]: private trait `traits::PrivTr` in public interface --> $DIR/private-in-public.rs:34:5 | -LL | trait PrivTr {} - | ------------ `traits::PrivTr` declared as private +LL | trait PrivTr {} + | ------------ `traits::PrivTr` declared as private ... -LL | / impl<T: PrivTr> Pub<T> { -LL | | pub fn f<U: PrivTr>(arg: U) {} -LL | | } - | |_____^ can't leak private trait +LL | impl<T: PrivTr> Pub<T> { + | ^^^^^^^^^^^^^^^^^^^^^^ can't leak private trait error[E0445]: private trait `traits::PrivTr` in public interface --> $DIR/private-in-public.rs:35:9 @@ -133,7 +131,7 @@ LL | trait PrivTr {} | ------------ `traits_where::PrivTr` declared as private ... LL | pub enum E<T> where T: PrivTr { V(T) } - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ can't leak private trait + | ^^^^^^^^^^^^^ can't leak private trait error[E0445]: private trait `traits_where::PrivTr` in public interface --> $DIR/private-in-public.rs:46:5 @@ -151,20 +149,16 @@ LL | trait PrivTr {} | ------------ `traits_where::PrivTr` declared as private ... LL | pub struct S1<T>(T) where T: PrivTr; - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ can't leak private trait + | ^^^^^^^^^^^^^^^^ can't leak private trait error[E0445]: private trait `traits_where::PrivTr` in public interface --> $DIR/private-in-public.rs:50:5 | -LL | trait PrivTr {} - | ------------ `traits_where::PrivTr` declared as private +LL | trait PrivTr {} + | ------------ `traits_where::PrivTr` declared as private ... -LL | / impl<T> Pub<T> where T: PrivTr { -LL | | -LL | | pub fn f<U>(arg: U) where U: PrivTr {} -LL | | -LL | | } - | |_____^ can't leak private trait +LL | impl<T> Pub<T> where T: PrivTr { + | ^^^^^^^^^^^^^^ can't leak private trait error[E0445]: private trait `traits_where::PrivTr` in public interface --> $DIR/private-in-public.rs:52:9 @@ -179,7 +173,7 @@ error[E0446]: private type `generics::Priv` in public interface --> $DIR/private-in-public.rs:63:5 | LL | struct Priv<T = u8>(T); - | ----------------------- `generics::Priv` declared as private + | ------------------- `generics::Priv` declared as private ... LL | pub fn f1(arg: [Priv; 1]) {} | ^^^^^^^^^^^^^^^^^^^^^^^^^ can't leak private type @@ -188,7 +182,7 @@ error[E0446]: private type `generics::Priv` in public interface --> $DIR/private-in-public.rs:64:5 | LL | struct Priv<T = u8>(T); - | ----------------------- `generics::Priv` declared as private + | ------------------- `generics::Priv` declared as private ... LL | pub fn f2(arg: Pub<Priv>) {} | ^^^^^^^^^^^^^^^^^^^^^^^^^ can't leak private type @@ -197,7 +191,7 @@ error[E0446]: private type `generics::Priv<generics::Pub>` in public interface --> $DIR/private-in-public.rs:65:5 | LL | struct Priv<T = u8>(T); - | ----------------------- `generics::Priv<generics::Pub>` declared as private + | ------------------- `generics::Priv<generics::Pub>` declared as private ... LL | pub fn f3(arg: Priv<Pub>) {} | ^^^^^^^^^^^^^^^^^^^^^^^^^ can't leak private type @@ -206,7 +200,7 @@ error[E0446]: private type `impls::Priv` in public interface --> $DIR/private-in-public.rs:80:9 | LL | struct Priv; - | ------------ `impls::Priv` declared as private + | ----------- `impls::Priv` declared as private ... LL | pub fn f(arg: Priv) {} | ^^^^^^^^^^^^^^^^^^^ can't leak private type @@ -224,7 +218,7 @@ error[E0446]: private type `aliases_pub::Priv` in public interface --> $DIR/private-in-public.rs:104:5 | LL | struct Priv; - | ------------ `aliases_pub::Priv` declared as private + | ----------- `aliases_pub::Priv` declared as private ... LL | pub fn f3(arg: <Priv as PrivTr>::Assoc) {} | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ can't leak private type @@ -233,7 +227,7 @@ error[E0446]: private type `aliases_pub::Priv` in public interface --> $DIR/private-in-public.rs:109:9 | LL | struct Priv; - | ------------ `aliases_pub::Priv` declared as private + | ----------- `aliases_pub::Priv` declared as private ... LL | pub fn f(arg: Priv) {} | ^^^^^^^^^^^^^^^^^^^ can't leak private type @@ -242,7 +236,7 @@ error[E0446]: private type `Priv1` in public interface --> $DIR/private-in-public.rs:131:5 | LL | struct Priv1; - | ------------- `Priv1` declared as private + | ------------ `Priv1` declared as private ... LL | pub fn f1(arg: PrivUseAlias) {} | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ can't leak private type @@ -251,7 +245,7 @@ error[E0446]: private type `Priv2` in public interface --> $DIR/private-in-public.rs:132:5 | LL | struct Priv2; - | ------------- `Priv2` declared as private + | ------------ `Priv2` declared as private ... LL | pub fn f2(arg: PrivAlias) {} | ^^^^^^^^^^^^^^^^^^^^^^^^^ can't leak private type @@ -269,7 +263,7 @@ error[E0446]: private type `aliases_priv::Priv` in public interface --> $DIR/private-in-public.rs:133:5 | LL | struct Priv; - | ------------ `aliases_priv::Priv` declared as private + | ----------- `aliases_priv::Priv` declared as private ... LL | pub fn f3(arg: <Priv as PrivTr>::Assoc) {} | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ can't leak private type @@ -278,7 +272,7 @@ error[E0446]: private type `aliases_params::Priv` in public interface --> $DIR/private-in-public.rs:143:5 | LL | struct Priv; - | ------------ `aliases_params::Priv` declared as private + | ----------- `aliases_params::Priv` declared as private ... LL | pub fn f2(arg: PrivAliasGeneric) {} | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ can't leak private type @@ -287,7 +281,7 @@ error[E0446]: private type `aliases_params::Priv` in public interface --> $DIR/private-in-public.rs:145:5 | LL | struct Priv; - | ------------ `aliases_params::Priv` declared as private + | ----------- `aliases_params::Priv` declared as private ... LL | pub fn f3(arg: Result<u8>) {} | ^^^^^^^^^^^^^^^^^^^^^^^^^^ can't leak private type diff --git a/src/test/ui/privacy/private-inferred-type.stderr b/src/test/ui/privacy/private-inferred-type.stderr index e7e968839b6..aecd8b58c83 100644 --- a/src/test/ui/privacy/private-inferred-type.stderr +++ b/src/test/ui/privacy/private-inferred-type.stderr @@ -2,19 +2,19 @@ error[E0446]: private type `Priv` in public interface --> $DIR/private-inferred-type.rs:61:36 | LL | struct Priv; - | ------------ `Priv` declared as private + | ----------- `Priv` declared as private ... LL | impl TraitWithAssocTy for u8 { type AssocTy = Priv; } - | ^^^^^^^^^^^^^^^^^^^^ can't leak private type + | ^^^^^^^^^^^^ can't leak private type error[E0446]: private type `S2` in public interface --> $DIR/private-inferred-type.rs:83:9 | LL | struct S2; - | ---------- `S2` declared as private + | --------- `S2` declared as private ... LL | type Target = S2Alias; - | ^^^^^^^^^^^^^^^^^^^^^^ can't leak private type + | ^^^^^^^^^^^ can't leak private type error: type `Priv` is private --> $DIR/private-inferred-type.rs:97:9 diff --git a/src/test/ui/privacy/pub-priv-dep/pub-priv1.stderr b/src/test/ui/privacy/pub-priv-dep/pub-priv1.stderr index f64b8569015..e62a440d8f5 100644 --- a/src/test/ui/privacy/pub-priv-dep/pub-priv1.stderr +++ b/src/test/ui/privacy/pub-priv-dep/pub-priv1.stderr @@ -20,7 +20,7 @@ error: trait `OtherTrait` from private dependency 'priv_dep' in public interface --> $DIR/pub-priv1.rs:35:5 | LL | type Foo: OtherTrait; - | ^^^^^^^^^^^^^^^^^^^^^ + | ^^^^^^^^^^^^^^^^^^^^ error: aborting due to 3 previous errors diff --git a/src/test/ui/privacy/restricted/private-in-public.stderr b/src/test/ui/privacy/restricted/private-in-public.stderr index ee9c031ebff..65d996f0f07 100644 --- a/src/test/ui/privacy/restricted/private-in-public.stderr +++ b/src/test/ui/privacy/restricted/private-in-public.stderr @@ -2,7 +2,7 @@ error[E0446]: private type `Priv` in public interface --> $DIR/private-in-public.rs:6:9 | LL | struct Priv; - | ------------ `Priv` declared as private + | ----------- `Priv` declared as private ... LL | pub(crate) fn g(_: Priv) {} | ^^^^^^^^^^^^^^^^^^^^^^^^ can't leak private type @@ -11,7 +11,7 @@ error[E0446]: private type `Priv` in public interface --> $DIR/private-in-public.rs:7:9 | LL | struct Priv; - | ------------ `Priv` declared as private + | ----------- `Priv` declared as private ... LL | pub(crate) fn h(_: Priv) {} | ^^^^^^^^^^^^^^^^^^^^^^^^ can't leak private type diff --git a/src/test/ui/privacy/restricted/test.stderr b/src/test/ui/privacy/restricted/test.stderr index c81520c35cd..1acd221b42c 100644 --- a/src/test/ui/privacy/restricted/test.stderr +++ b/src/test/ui/privacy/restricted/test.stderr @@ -34,7 +34,7 @@ note: the struct `Crate` is defined here --> $DIR/auxiliary/pub_restricted.rs:1:1 | LL | pub(crate) struct Crate; - | ^^^^^^^^^^^^^^^^^^^^^^^^ + | ^^^^^^^^^^^^^^^^^^^^^^^ error[E0603]: function `f` is private --> $DIR/test.rs:30:19 diff --git a/src/test/ui/privacy/where-priv-type.stderr b/src/test/ui/privacy/where-priv-type.stderr index 378c14810d9..7eb71346ae9 100644 --- a/src/test/ui/privacy/where-priv-type.stderr +++ b/src/test/ui/privacy/where-priv-type.stderr @@ -1,13 +1,8 @@ warning: private type `PrivTy` in public interface (error E0446) --> $DIR/where-priv-type.rs:19:1 | -LL | / pub struct S -LL | | -LL | | -LL | | where -LL | | PrivTy: -LL | | {} - | |__^ +LL | pub struct S + | ^^^^^^^^^^^^ | = note: `#[warn(private_in_public)]` on by default = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release! @@ -16,13 +11,8 @@ LL | | {} warning: private type `PrivTy` in public interface (error E0446) --> $DIR/where-priv-type.rs:27:1 | -LL | / pub enum E -LL | | -LL | | -LL | | where -LL | | PrivTy: -LL | | {} - | |__^ +LL | pub enum E + | ^^^^^^^^^^ | = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release! = note: for more information, see issue #34537 <https://github.com/rust-lang/rust/issues/34537> @@ -43,17 +33,11 @@ LL | | PrivTy: error[E0446]: private type `PrivTy` in public interface --> $DIR/where-priv-type.rs:43:1 | -LL | struct PrivTy; - | -------------- `PrivTy` declared as private +LL | struct PrivTy; + | ------------- `PrivTy` declared as private ... -LL | / impl S -LL | | -LL | | where -LL | | PrivTy: -... | -LL | | {} -LL | | } - | |_^ can't leak private type +LL | impl S + | ^^^^^^ can't leak private type warning: private type `PrivTy` in public interface (error E0446) --> $DIR/where-priv-type.rs:48:5 @@ -72,7 +56,7 @@ error[E0446]: private type `fn(u8) -> u8 {my_const_fn}` in public interface --> $DIR/where-priv-type.rs:80:5 | LL | type AssocTy = Const<{ my_const_fn(U) }>; - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ can't leak private type + | ^^^^^^^^^^^^ can't leak private type ... LL | const fn my_const_fn(val: u8) -> u8 { | ----------------------------------- `fn(u8) -> u8 {my_const_fn}` declared as private diff --git a/src/test/ui/privacy/where-pub-type-impls-priv-trait.stderr b/src/test/ui/privacy/where-pub-type-impls-priv-trait.stderr index 9ce7b9a139f..a433cebbbc0 100644 --- a/src/test/ui/privacy/where-pub-type-impls-priv-trait.stderr +++ b/src/test/ui/privacy/where-pub-type-impls-priv-trait.stderr @@ -1,28 +1,20 @@ error[E0445]: private trait `PrivTr` in public interface --> $DIR/where-pub-type-impls-priv-trait.rs:19:1 | -LL | trait PrivTr {} - | ------------ `PrivTr` declared as private +LL | trait PrivTr {} + | ------------ `PrivTr` declared as private ... -LL | / pub struct S -LL | | -LL | | where -LL | | PubTy: PrivTr -LL | | {} - | |__^ can't leak private trait +LL | pub struct S + | ^^^^^^^^^^^^ can't leak private trait error[E0445]: private trait `PrivTr` in public interface --> $DIR/where-pub-type-impls-priv-trait.rs:26:1 | -LL | trait PrivTr {} - | ------------ `PrivTr` declared as private +LL | trait PrivTr {} + | ------------ `PrivTr` declared as private ... -LL | / pub enum E -LL | | -LL | | where -LL | | PubTy: PrivTr -LL | | {} - | |__^ can't leak private trait +LL | pub enum E + | ^^^^^^^^^^ can't leak private trait error[E0445]: private trait `PrivTr` in public interface --> $DIR/where-pub-type-impls-priv-trait.rs:33:1 @@ -39,17 +31,11 @@ LL | | PubTy: PrivTr error[E0445]: private trait `PrivTr` in public interface --> $DIR/where-pub-type-impls-priv-trait.rs:40:1 | -LL | trait PrivTr {} - | ------------ `PrivTr` declared as private +LL | trait PrivTr {} + | ------------ `PrivTr` declared as private ... -LL | / impl S -LL | | -LL | | where -LL | | PubTy: PrivTr -... | -LL | | {} -LL | | } - | |_^ can't leak private trait +LL | impl S + | ^^^^^^ can't leak private trait error[E0445]: private trait `PrivTr` in public interface --> $DIR/where-pub-type-impls-priv-trait.rs:45:5 diff --git a/src/test/ui/proc-macro/resolve-error.stderr b/src/test/ui/proc-macro/resolve-error.stderr index e518c6ab800..a534b9d5377 100644 --- a/src/test/ui/proc-macro/resolve-error.stderr +++ b/src/test/ui/proc-macro/resolve-error.stderr @@ -76,7 +76,7 @@ LL | #[derive(Dlone)] ::: $SRC_DIR/core/src/clone.rs:LL:COL | LL | pub macro Clone($item:item) { - | --------------------------- similarly named derive macro `Clone` defined here + | --------------- similarly named derive macro `Clone` defined here error: cannot find derive macro `Dlone` in this scope --> $DIR/resolve-error.rs:35:10 @@ -87,7 +87,7 @@ LL | #[derive(Dlone)] ::: $SRC_DIR/core/src/clone.rs:LL:COL | LL | pub macro Clone($item:item) { - | --------------------------- similarly named derive macro `Clone` defined here + | --------------- similarly named derive macro `Clone` defined here error: cannot find attribute `FooWithLongNan` in this scope --> $DIR/resolve-error.rs:32:3 diff --git a/src/test/ui/pub/issue-33174-restricted-type-in-public-interface.stderr b/src/test/ui/pub/issue-33174-restricted-type-in-public-interface.stderr index 29d45858ff1..39d4f5ac8d3 100644 --- a/src/test/ui/pub/issue-33174-restricted-type-in-public-interface.stderr +++ b/src/test/ui/pub/issue-33174-restricted-type-in-public-interface.stderr @@ -2,28 +2,28 @@ error[E0446]: private type `Snail` in public interface --> $DIR/issue-33174-restricted-type-in-public-interface.rs:18:1 | LL | pub(crate) struct Snail; - | ------------------------ `Snail` declared as private + | ----------------------- `Snail` declared as private ... LL | pub type Helix_pomatia = Shell<Snail>; - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ can't leak private type + | ^^^^^^^^^^^^^^^^^^^^^^ can't leak private type error[E0446]: crate-private type `Turtle` in public interface --> $DIR/issue-33174-restricted-type-in-public-interface.rs:21:1 | LL | pub(super) struct Turtle; - | ------------------------- `Turtle` declared as crate-private + | ------------------------ `Turtle` declared as crate-private ... LL | pub type Dermochelys_coriacea = Shell<sea::Turtle>; - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ can't leak crate-private type + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ can't leak crate-private type error[E0446]: private type `Tortoise` in public interface --> $DIR/issue-33174-restricted-type-in-public-interface.rs:24:1 | LL | struct Tortoise; - | ---------------- `Tortoise` declared as private + | --------------- `Tortoise` declared as private ... LL | pub type Testudo_graeca = Shell<Tortoise>; - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ can't leak private type + | ^^^^^^^^^^^^^^^^^^^^^^^ can't leak private type error: aborting due to 3 previous errors diff --git a/src/test/ui/recursion/issue-38591-non-regular-dropck-recursion.rs b/src/test/ui/recursion/issue-38591-non-regular-dropck-recursion.rs index c857eb459b8..c9e93174e20 100644 --- a/src/test/ui/recursion/issue-38591-non-regular-dropck-recursion.rs +++ b/src/test/ui/recursion/issue-38591-non-regular-dropck-recursion.rs @@ -1,18 +1,14 @@ -// Dropck shouldn't hit a recursion limit from checking `S<u32>` since it has -// no free regions or type parameters. -// Codegen however, has to error for the infinitely many `drop_in_place` -// functions it has been asked to create. - -// build-fail -// normalize-stderr-test: ".nll/" -> "/" -// compile-flags: -Zmir-opt-level=0 +// `S` is infinitely recursing so it's not possible to generate a finite +// drop impl (ignoring polymorphization). +// +// Dropck should therefore detect that this is the case and eagerly error. struct S<T> { t: T, s: Box<S<fn(u: T)>>, } -fn f(x: S<u32>) {} +fn f(x: S<u32>) {} //~ ERROR overflow while adding drop-check rules for S<u32> fn main() { // Force instantiation. diff --git a/src/test/ui/recursion/issue-38591-non-regular-dropck-recursion.stderr b/src/test/ui/recursion/issue-38591-non-regular-dropck-recursion.stderr index d749ee00c22..1da29be43db 100644 --- a/src/test/ui/recursion/issue-38591-non-regular-dropck-recursion.stderr +++ b/src/test/ui/recursion/issue-38591-non-regular-dropck-recursion.stderr @@ -1,15 +1,10 @@ -error: reached the recursion limit while instantiating `std::ptr::drop_in_place::<S<fn(f...)))))))))))))))))))))))))))))>))` - --> $SRC_DIR/core/src/ptr/mod.rs:LL:COL +error[E0320]: overflow while adding drop-check rules for S<u32> + --> $DIR/issue-38591-non-regular-dropck-recursion.rs:11:6 | -LL | pub unsafe fn drop_in_place<T: ?Sized>(to_drop: *mut T) { - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ +LL | fn f(x: S<u32>) {} + | ^ | -note: `std::ptr::drop_in_place` defined here - --> $SRC_DIR/core/src/ptr/mod.rs:LL:COL - | -LL | pub unsafe fn drop_in_place<T: ?Sized>(to_drop: *mut T) { - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ - = note: the full type name has been written to '$TEST_BUILD_DIR/recursion/issue-38591-non-regular-dropck-recursion/issue-38591-non-regular-dropck-recursion.long-type.txt' + = note: overflowed on S<fn(fn(fn(fn(fn(fn(fn(fn(fn(fn(fn(fn(fn(fn(fn(fn(fn(fn(fn(fn(fn(fn(fn(fn(fn(fn(fn(fn(fn(fn(fn(fn(fn(fn(fn(fn(fn(fn(fn(fn(fn(fn(fn(fn(fn(fn(fn(fn(fn(fn(fn(fn(fn(fn(fn(fn(fn(fn(fn(fn(fn(fn(fn(fn(fn(fn(fn(fn(fn(fn(fn(fn(fn(fn(fn(fn(fn(fn(fn(fn(fn(fn(fn(fn(fn(fn(fn(fn(fn(fn(fn(fn(fn(fn(fn(fn(fn(fn(fn(fn(fn(fn(fn(fn(fn(fn(fn(fn(fn(fn(fn(fn(fn(fn(fn(fn(fn(fn(fn(fn(fn(fn(fn(fn(fn(fn(fn(fn(fn(u32)))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))> error: aborting due to previous error diff --git a/src/test/ui/recursion/issue-83150.rs b/src/test/ui/recursion/issue-83150.rs index aa3f66b2e28..e647f0ff4fb 100644 --- a/src/test/ui/recursion/issue-83150.rs +++ b/src/test/ui/recursion/issue-83150.rs @@ -1,5 +1,6 @@ // build-fail -//~^ ERROR overflow evaluating the requirement +// compile-flags: -Copt-level=0 +//~^^ ERROR overflow evaluating the requirement fn main() { let mut iter = 0u8..1; diff --git a/src/test/ui/recursion/issue-83150.stderr b/src/test/ui/recursion/issue-83150.stderr index 4c8469be626..aaa5884c60c 100644 --- a/src/test/ui/recursion/issue-83150.stderr +++ b/src/test/ui/recursion/issue-83150.stderr @@ -1,5 +1,5 @@ warning: function cannot return without recursing - --> $DIR/issue-83150.rs:9:1 + --> $DIR/issue-83150.rs:10:1 | LL | fn func<T: Iterator<Item = u8>>(iter: &mut T) { | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ cannot return without recursing @@ -9,10 +9,10 @@ LL | func(&mut iter.map(|x| x + 1)) = note: `#[warn(unconditional_recursion)]` on by default = help: a `loop` may express intention better if this is on purpose -error[E0275]: overflow evaluating the requirement `Map<&mut Map<&mut Map<&mut Map<&mut Map<&mut Map<&mut Map<&mut Map<&mut Map<&mut Map<&mut Map<&mut Map<&mut Map<&mut Map<&mut Map<&mut Map<&mut Map<&mut Map<&mut Map<&mut Map<&mut Map<&mut Map<&mut Map<&mut Map<&mut Map<&mut Map<&mut Map<&mut Map<&mut Map<&mut Map<&mut Map<&mut Map<&mut Map<&mut Map<&mut Map<&mut Map<&mut Map<&mut Map<&mut Map<&mut Map<&mut Map<&mut Map<&mut Map<&mut Map<&mut Map<&mut Map<&mut Map<&mut Map<&mut Map<&mut Map<&mut Map<&mut Map<&mut Map<&mut Map<&mut Map<&mut Map<&mut Map<&mut Map<&mut Map<&mut Map<&mut Map<&mut Map<&mut Map<&mut Map<&mut std::ops::Range<u8>, [closure@$DIR/issue-83150.rs:10:24: 10:33]>, [closure@$DIR/issue-83150.rs:10:24: 10:33]>, [closure@$DIR/issue-83150.rs:10:24: 10:33]>, [closure@$DIR/issue-83150.rs:10:24: 10:33]>, [closure@$DIR/issue-83150.rs:10:24: 10:33]>, [closure@$DIR/issue-83150.rs:10:24: 10:33]>, [closure@$DIR/issue-83150.rs:10:24: 10:33]>, [closure@$DIR/issue-83150.rs:10:24: 10:33]>, [closure@$DIR/issue-83150.rs:10:24: 10:33]>, [closure@$DIR/issue-83150.rs:10:24: 10:33]>, [closure@$DIR/issue-83150.rs:10:24: 10:33]>, [closure@$DIR/issue-83150.rs:10:24: 10:33]>, [closure@$DIR/issue-83150.rs:10:24: 10:33]>, [closure@$DIR/issue-83150.rs:10:24: 10:33]>, [closure@$DIR/issue-83150.rs:10:24: 10:33]>, [closure@$DIR/issue-83150.rs:10:24: 10:33]>, [closure@$DIR/issue-83150.rs:10:24: 10:33]>, [closure@$DIR/issue-83150.rs:10:24: 10:33]>, [closure@$DIR/issue-83150.rs:10:24: 10:33]>, [closure@$DIR/issue-83150.rs:10:24: 10:33]>, [closure@$DIR/issue-83150.rs:10:24: 10:33]>, [closure@$DIR/issue-83150.rs:10:24: 10:33]>, [closure@$DIR/issue-83150.rs:10:24: 10:33]>, [closure@$DIR/issue-83150.rs:10:24: 10:33]>, [closure@$DIR/issue-83150.rs:10:24: 10:33]>, [closure@$DIR/issue-83150.rs:10:24: 10:33]>, [closure@$DIR/issue-83150.rs:10:24: 10:33]>, [closure@$DIR/issue-83150.rs:10:24: 10:33]>, [closure@$DIR/issue-83150.rs:10:24: 10:33]>, [closure@$DIR/issue-83150.rs:10:24: 10:33]>, [closure@$DIR/issue-83150.rs:10:24: 10:33]>, [closure@$DIR/issue-83150.rs:10:24: 10:33]>, [closure@$DIR/issue-83150.rs:10:24: 10:33]>, [closure@$DIR/issue-83150.rs:10:24: 10:33]>, [closure@$DIR/issue-83150.rs:10:24: 10:33]>, [closure@$DIR/issue-83150.rs:10:24: 10:33]>, [closure@$DIR/issue-83150.rs:10:24: 10:33]>, [closure@$DIR/issue-83150.rs:10:24: 10:33]>, [closure@$DIR/issue-83150.rs:10:24: 10:33]>, [closure@$DIR/issue-83150.rs:10:24: 10:33]>, [closure@$DIR/issue-83150.rs:10:24: 10:33]>, [closure@$DIR/issue-83150.rs:10:24: 10:33]>, [closure@$DIR/issue-83150.rs:10:24: 10:33]>, [closure@$DIR/issue-83150.rs:10:24: 10:33]>, [closure@$DIR/issue-83150.rs:10:24: 10:33]>, [closure@$DIR/issue-83150.rs:10:24: 10:33]>, [closure@$DIR/issue-83150.rs:10:24: 10:33]>, [closure@$DIR/issue-83150.rs:10:24: 10:33]>, [closure@$DIR/issue-83150.rs:10:24: 10:33]>, [closure@$DIR/issue-83150.rs:10:24: 10:33]>, [closure@$DIR/issue-83150.rs:10:24: 10:33]>, [closure@$DIR/issue-83150.rs:10:24: 10:33]>, [closure@$DIR/issue-83150.rs:10:24: 10:33]>, [closure@$DIR/issue-83150.rs:10:24: 10:33]>, [closure@$DIR/issue-83150.rs:10:24: 10:33]>, [closure@$DIR/issue-83150.rs:10:24: 10:33]>, [closure@$DIR/issue-83150.rs:10:24: 10:33]>, [closure@$DIR/issue-83150.rs:10:24: 10:33]>, [closure@$DIR/issue-83150.rs:10:24: 10:33]>, [closure@$DIR/issue-83150.rs:10:24: 10:33]>, [closure@$DIR/issue-83150.rs:10:24: 10:33]>, [closure@$DIR/issue-83150.rs:10:24: 10:33]>, [closure@$DIR/issue-83150.rs:10:24: 10:33]>, [closure@$DIR/issue-83150.rs:10:24: 10:33]>: Iterator` +error[E0275]: overflow evaluating the requirement `Map<&mut Map<&mut Map<&mut Map<&mut Map<&mut Map<&mut Map<&mut Map<&mut Map<&mut Map<&mut Map<&mut Map<&mut Map<&mut Map<&mut Map<&mut Map<&mut Map<&mut Map<&mut Map<&mut Map<&mut Map<&mut Map<&mut Map<&mut Map<&mut Map<&mut Map<&mut Map<&mut Map<&mut Map<&mut Map<&mut Map<&mut Map<&mut Map<&mut Map<&mut Map<&mut Map<&mut Map<&mut Map<&mut Map<&mut Map<&mut Map<&mut Map<&mut Map<&mut Map<&mut Map<&mut Map<&mut Map<&mut Map<&mut Map<&mut Map<&mut Map<&mut Map<&mut Map<&mut Map<&mut Map<&mut Map<&mut Map<&mut Map<&mut Map<&mut Map<&mut Map<&mut Map<&mut Map<&mut Map<&mut std::ops::Range<u8>, [closure@$DIR/issue-83150.rs:11:24: 11:33]>, [closure@$DIR/issue-83150.rs:11:24: 11:33]>, [closure@$DIR/issue-83150.rs:11:24: 11:33]>, [closure@$DIR/issue-83150.rs:11:24: 11:33]>, [closure@$DIR/issue-83150.rs:11:24: 11:33]>, [closure@$DIR/issue-83150.rs:11:24: 11:33]>, [closure@$DIR/issue-83150.rs:11:24: 11:33]>, [closure@$DIR/issue-83150.rs:11:24: 11:33]>, [closure@$DIR/issue-83150.rs:11:24: 11:33]>, [closure@$DIR/issue-83150.rs:11:24: 11:33]>, [closure@$DIR/issue-83150.rs:11:24: 11:33]>, [closure@$DIR/issue-83150.rs:11:24: 11:33]>, [closure@$DIR/issue-83150.rs:11:24: 11:33]>, [closure@$DIR/issue-83150.rs:11:24: 11:33]>, [closure@$DIR/issue-83150.rs:11:24: 11:33]>, [closure@$DIR/issue-83150.rs:11:24: 11:33]>, [closure@$DIR/issue-83150.rs:11:24: 11:33]>, [closure@$DIR/issue-83150.rs:11:24: 11:33]>, [closure@$DIR/issue-83150.rs:11:24: 11:33]>, [closure@$DIR/issue-83150.rs:11:24: 11:33]>, [closure@$DIR/issue-83150.rs:11:24: 11:33]>, [closure@$DIR/issue-83150.rs:11:24: 11:33]>, [closure@$DIR/issue-83150.rs:11:24: 11:33]>, [closure@$DIR/issue-83150.rs:11:24: 11:33]>, [closure@$DIR/issue-83150.rs:11:24: 11:33]>, [closure@$DIR/issue-83150.rs:11:24: 11:33]>, [closure@$DIR/issue-83150.rs:11:24: 11:33]>, [closure@$DIR/issue-83150.rs:11:24: 11:33]>, [closure@$DIR/issue-83150.rs:11:24: 11:33]>, [closure@$DIR/issue-83150.rs:11:24: 11:33]>, [closure@$DIR/issue-83150.rs:11:24: 11:33]>, [closure@$DIR/issue-83150.rs:11:24: 11:33]>, [closure@$DIR/issue-83150.rs:11:24: 11:33]>, [closure@$DIR/issue-83150.rs:11:24: 11:33]>, [closure@$DIR/issue-83150.rs:11:24: 11:33]>, [closure@$DIR/issue-83150.rs:11:24: 11:33]>, [closure@$DIR/issue-83150.rs:11:24: 11:33]>, [closure@$DIR/issue-83150.rs:11:24: 11:33]>, [closure@$DIR/issue-83150.rs:11:24: 11:33]>, [closure@$DIR/issue-83150.rs:11:24: 11:33]>, [closure@$DIR/issue-83150.rs:11:24: 11:33]>, [closure@$DIR/issue-83150.rs:11:24: 11:33]>, [closure@$DIR/issue-83150.rs:11:24: 11:33]>, [closure@$DIR/issue-83150.rs:11:24: 11:33]>, [closure@$DIR/issue-83150.rs:11:24: 11:33]>, [closure@$DIR/issue-83150.rs:11:24: 11:33]>, [closure@$DIR/issue-83150.rs:11:24: 11:33]>, [closure@$DIR/issue-83150.rs:11:24: 11:33]>, [closure@$DIR/issue-83150.rs:11:24: 11:33]>, [closure@$DIR/issue-83150.rs:11:24: 11:33]>, [closure@$DIR/issue-83150.rs:11:24: 11:33]>, [closure@$DIR/issue-83150.rs:11:24: 11:33]>, [closure@$DIR/issue-83150.rs:11:24: 11:33]>, [closure@$DIR/issue-83150.rs:11:24: 11:33]>, [closure@$DIR/issue-83150.rs:11:24: 11:33]>, [closure@$DIR/issue-83150.rs:11:24: 11:33]>, [closure@$DIR/issue-83150.rs:11:24: 11:33]>, [closure@$DIR/issue-83150.rs:11:24: 11:33]>, [closure@$DIR/issue-83150.rs:11:24: 11:33]>, [closure@$DIR/issue-83150.rs:11:24: 11:33]>, [closure@$DIR/issue-83150.rs:11:24: 11:33]>, [closure@$DIR/issue-83150.rs:11:24: 11:33]>, [closure@$DIR/issue-83150.rs:11:24: 11:33]>, [closure@$DIR/issue-83150.rs:11:24: 11:33]>: Iterator` | = help: consider increasing the recursion limit by adding a `#![recursion_limit = "256"]` attribute to your crate (`issue_83150`) - = note: required because of the requirements on the impl of `Iterator` for `&mut Map<&mut Map<&mut Map<&mut Map<&mut Map<&mut Map<&mut Map<&mut Map<&mut Map<&mut Map<&mut Map<&mut Map<&mut Map<&mut Map<&mut Map<&mut Map<&mut Map<&mut Map<&mut Map<&mut Map<&mut Map<&mut Map<&mut Map<&mut Map<&mut Map<&mut Map<&mut Map<&mut Map<&mut Map<&mut Map<&mut Map<&mut Map<&mut Map<&mut Map<&mut Map<&mut Map<&mut Map<&mut Map<&mut Map<&mut Map<&mut Map<&mut Map<&mut Map<&mut Map<&mut Map<&mut Map<&mut Map<&mut Map<&mut Map<&mut Map<&mut Map<&mut Map<&mut Map<&mut Map<&mut Map<&mut Map<&mut Map<&mut Map<&mut Map<&mut Map<&mut Map<&mut Map<&mut Map<&mut Map<&mut std::ops::Range<u8>, [closure@$DIR/issue-83150.rs:10:24: 10:33]>, [closure@$DIR/issue-83150.rs:10:24: 10:33]>, [closure@$DIR/issue-83150.rs:10:24: 10:33]>, [closure@$DIR/issue-83150.rs:10:24: 10:33]>, [closure@$DIR/issue-83150.rs:10:24: 10:33]>, [closure@$DIR/issue-83150.rs:10:24: 10:33]>, [closure@$DIR/issue-83150.rs:10:24: 10:33]>, [closure@$DIR/issue-83150.rs:10:24: 10:33]>, [closure@$DIR/issue-83150.rs:10:24: 10:33]>, [closure@$DIR/issue-83150.rs:10:24: 10:33]>, [closure@$DIR/issue-83150.rs:10:24: 10:33]>, [closure@$DIR/issue-83150.rs:10:24: 10:33]>, [closure@$DIR/issue-83150.rs:10:24: 10:33]>, [closure@$DIR/issue-83150.rs:10:24: 10:33]>, [closure@$DIR/issue-83150.rs:10:24: 10:33]>, [closure@$DIR/issue-83150.rs:10:24: 10:33]>, [closure@$DIR/issue-83150.rs:10:24: 10:33]>, [closure@$DIR/issue-83150.rs:10:24: 10:33]>, [closure@$DIR/issue-83150.rs:10:24: 10:33]>, [closure@$DIR/issue-83150.rs:10:24: 10:33]>, [closure@$DIR/issue-83150.rs:10:24: 10:33]>, [closure@$DIR/issue-83150.rs:10:24: 10:33]>, [closure@$DIR/issue-83150.rs:10:24: 10:33]>, [closure@$DIR/issue-83150.rs:10:24: 10:33]>, [closure@$DIR/issue-83150.rs:10:24: 10:33]>, [closure@$DIR/issue-83150.rs:10:24: 10:33]>, [closure@$DIR/issue-83150.rs:10:24: 10:33]>, [closure@$DIR/issue-83150.rs:10:24: 10:33]>, [closure@$DIR/issue-83150.rs:10:24: 10:33]>, [closure@$DIR/issue-83150.rs:10:24: 10:33]>, [closure@$DIR/issue-83150.rs:10:24: 10:33]>, [closure@$DIR/issue-83150.rs:10:24: 10:33]>, [closure@$DIR/issue-83150.rs:10:24: 10:33]>, [closure@$DIR/issue-83150.rs:10:24: 10:33]>, [closure@$DIR/issue-83150.rs:10:24: 10:33]>, [closure@$DIR/issue-83150.rs:10:24: 10:33]>, [closure@$DIR/issue-83150.rs:10:24: 10:33]>, [closure@$DIR/issue-83150.rs:10:24: 10:33]>, [closure@$DIR/issue-83150.rs:10:24: 10:33]>, [closure@$DIR/issue-83150.rs:10:24: 10:33]>, [closure@$DIR/issue-83150.rs:10:24: 10:33]>, [closure@$DIR/issue-83150.rs:10:24: 10:33]>, [closure@$DIR/issue-83150.rs:10:24: 10:33]>, [closure@$DIR/issue-83150.rs:10:24: 10:33]>, [closure@$DIR/issue-83150.rs:10:24: 10:33]>, [closure@$DIR/issue-83150.rs:10:24: 10:33]>, [closure@$DIR/issue-83150.rs:10:24: 10:33]>, [closure@$DIR/issue-83150.rs:10:24: 10:33]>, [closure@$DIR/issue-83150.rs:10:24: 10:33]>, [closure@$DIR/issue-83150.rs:10:24: 10:33]>, [closure@$DIR/issue-83150.rs:10:24: 10:33]>, [closure@$DIR/issue-83150.rs:10:24: 10:33]>, [closure@$DIR/issue-83150.rs:10:24: 10:33]>, [closure@$DIR/issue-83150.rs:10:24: 10:33]>, [closure@$DIR/issue-83150.rs:10:24: 10:33]>, [closure@$DIR/issue-83150.rs:10:24: 10:33]>, [closure@$DIR/issue-83150.rs:10:24: 10:33]>, [closure@$DIR/issue-83150.rs:10:24: 10:33]>, [closure@$DIR/issue-83150.rs:10:24: 10:33]>, [closure@$DIR/issue-83150.rs:10:24: 10:33]>, [closure@$DIR/issue-83150.rs:10:24: 10:33]>, [closure@$DIR/issue-83150.rs:10:24: 10:33]>, [closure@$DIR/issue-83150.rs:10:24: 10:33]>, [closure@$DIR/issue-83150.rs:10:24: 10:33]>` + = note: required because of the requirements on the impl of `Iterator` for `&mut Map<&mut Map<&mut Map<&mut Map<&mut Map<&mut Map<&mut Map<&mut Map<&mut Map<&mut Map<&mut Map<&mut Map<&mut Map<&mut Map<&mut Map<&mut Map<&mut Map<&mut Map<&mut Map<&mut Map<&mut Map<&mut Map<&mut Map<&mut Map<&mut Map<&mut Map<&mut Map<&mut Map<&mut Map<&mut Map<&mut Map<&mut Map<&mut Map<&mut Map<&mut Map<&mut Map<&mut Map<&mut Map<&mut Map<&mut Map<&mut Map<&mut Map<&mut Map<&mut Map<&mut Map<&mut Map<&mut Map<&mut Map<&mut Map<&mut Map<&mut Map<&mut Map<&mut Map<&mut Map<&mut Map<&mut Map<&mut Map<&mut Map<&mut Map<&mut Map<&mut Map<&mut Map<&mut Map<&mut Map<&mut std::ops::Range<u8>, [closure@$DIR/issue-83150.rs:11:24: 11:33]>, [closure@$DIR/issue-83150.rs:11:24: 11:33]>, [closure@$DIR/issue-83150.rs:11:24: 11:33]>, [closure@$DIR/issue-83150.rs:11:24: 11:33]>, [closure@$DIR/issue-83150.rs:11:24: 11:33]>, [closure@$DIR/issue-83150.rs:11:24: 11:33]>, [closure@$DIR/issue-83150.rs:11:24: 11:33]>, [closure@$DIR/issue-83150.rs:11:24: 11:33]>, [closure@$DIR/issue-83150.rs:11:24: 11:33]>, [closure@$DIR/issue-83150.rs:11:24: 11:33]>, [closure@$DIR/issue-83150.rs:11:24: 11:33]>, [closure@$DIR/issue-83150.rs:11:24: 11:33]>, [closure@$DIR/issue-83150.rs:11:24: 11:33]>, [closure@$DIR/issue-83150.rs:11:24: 11:33]>, [closure@$DIR/issue-83150.rs:11:24: 11:33]>, [closure@$DIR/issue-83150.rs:11:24: 11:33]>, [closure@$DIR/issue-83150.rs:11:24: 11:33]>, [closure@$DIR/issue-83150.rs:11:24: 11:33]>, [closure@$DIR/issue-83150.rs:11:24: 11:33]>, [closure@$DIR/issue-83150.rs:11:24: 11:33]>, [closure@$DIR/issue-83150.rs:11:24: 11:33]>, [closure@$DIR/issue-83150.rs:11:24: 11:33]>, [closure@$DIR/issue-83150.rs:11:24: 11:33]>, [closure@$DIR/issue-83150.rs:11:24: 11:33]>, [closure@$DIR/issue-83150.rs:11:24: 11:33]>, [closure@$DIR/issue-83150.rs:11:24: 11:33]>, [closure@$DIR/issue-83150.rs:11:24: 11:33]>, [closure@$DIR/issue-83150.rs:11:24: 11:33]>, [closure@$DIR/issue-83150.rs:11:24: 11:33]>, [closure@$DIR/issue-83150.rs:11:24: 11:33]>, [closure@$DIR/issue-83150.rs:11:24: 11:33]>, [closure@$DIR/issue-83150.rs:11:24: 11:33]>, [closure@$DIR/issue-83150.rs:11:24: 11:33]>, [closure@$DIR/issue-83150.rs:11:24: 11:33]>, [closure@$DIR/issue-83150.rs:11:24: 11:33]>, [closure@$DIR/issue-83150.rs:11:24: 11:33]>, [closure@$DIR/issue-83150.rs:11:24: 11:33]>, [closure@$DIR/issue-83150.rs:11:24: 11:33]>, [closure@$DIR/issue-83150.rs:11:24: 11:33]>, [closure@$DIR/issue-83150.rs:11:24: 11:33]>, [closure@$DIR/issue-83150.rs:11:24: 11:33]>, [closure@$DIR/issue-83150.rs:11:24: 11:33]>, [closure@$DIR/issue-83150.rs:11:24: 11:33]>, [closure@$DIR/issue-83150.rs:11:24: 11:33]>, [closure@$DIR/issue-83150.rs:11:24: 11:33]>, [closure@$DIR/issue-83150.rs:11:24: 11:33]>, [closure@$DIR/issue-83150.rs:11:24: 11:33]>, [closure@$DIR/issue-83150.rs:11:24: 11:33]>, [closure@$DIR/issue-83150.rs:11:24: 11:33]>, [closure@$DIR/issue-83150.rs:11:24: 11:33]>, [closure@$DIR/issue-83150.rs:11:24: 11:33]>, [closure@$DIR/issue-83150.rs:11:24: 11:33]>, [closure@$DIR/issue-83150.rs:11:24: 11:33]>, [closure@$DIR/issue-83150.rs:11:24: 11:33]>, [closure@$DIR/issue-83150.rs:11:24: 11:33]>, [closure@$DIR/issue-83150.rs:11:24: 11:33]>, [closure@$DIR/issue-83150.rs:11:24: 11:33]>, [closure@$DIR/issue-83150.rs:11:24: 11:33]>, [closure@$DIR/issue-83150.rs:11:24: 11:33]>, [closure@$DIR/issue-83150.rs:11:24: 11:33]>, [closure@$DIR/issue-83150.rs:11:24: 11:33]>, [closure@$DIR/issue-83150.rs:11:24: 11:33]>, [closure@$DIR/issue-83150.rs:11:24: 11:33]>, [closure@$DIR/issue-83150.rs:11:24: 11:33]>` error: aborting due to previous error; 1 warning emitted diff --git a/src/test/ui/recursion/issue-86784.rs b/src/test/ui/recursion/issue-86784.rs new file mode 100644 index 00000000000..34f4aaedb32 --- /dev/null +++ b/src/test/ui/recursion/issue-86784.rs @@ -0,0 +1,2597 @@ +// build-pass + +fn main() { + let _temp_1 = 0; + let _temp_2 = 0; + let _temp_3 = 0; + let _temp_4 = 0; + let _temp_5 = 0; + let _temp_6 = 0; + let _temp_7 = 0; + let _temp_8 = 0; + let _temp_9 = 0; + let _temp_10 = 0; + let _temp_11 = 0; + let _temp_12 = 0; + let _temp_13 = 0; + let _temp_14 = 0; + let _temp_15 = 0; + let _temp_16 = 0; + let _temp_17 = 0; + let _temp_18 = 0; + let _temp_19 = 0; + let _temp_20 = 0; + let _temp_21 = 0; + let _temp_22 = 0; + let _temp_23 = 0; + let _temp_24 = 0; + let _temp_25 = 0; + let _temp_26 = 0; + let _temp_27 = 0; + let _temp_28 = 0; + let _temp_29 = 0; + let _temp_30 = 0; + let _temp_31 = 0; + let _temp_32 = 0; + let _temp_33 = 0; + let _temp_34 = 0; + let _temp_35 = 0; + let _temp_36 = 0; + let _temp_37 = 0; + let _temp_38 = 0; + let _temp_39 = 0; + let _temp_40 = 0; + let _temp_41 = 0; + let _temp_42 = 0; + let _temp_43 = 0; + let _temp_44 = 0; + let _temp_45 = 0; + let _temp_46 = 0; + let _temp_47 = 0; + let _temp_48 = 0; + let _temp_49 = 0; + let _temp_50 = 0; + let _temp_51 = 0; + let _temp_52 = 0; + let _temp_53 = 0; + let _temp_54 = 0; + let _temp_55 = 0; + let _temp_56 = 0; + let _temp_57 = 0; + let _temp_58 = 0; + let _temp_59 = 0; + let _temp_60 = 0; + let _temp_61 = 0; + let _temp_62 = 0; + let _temp_63 = 0; + let _temp_64 = 0; + let _temp_65 = 0; + let _temp_66 = 0; + let _temp_67 = 0; + let _temp_68 = 0; + let _temp_69 = 0; + let _temp_70 = 0; + let _temp_71 = 0; + let _temp_72 = 0; + let _temp_73 = 0; + let _temp_74 = 0; + let _temp_75 = 0; + let _temp_76 = 0; + let _temp_77 = 0; + let _temp_78 = 0; + let _temp_79 = 0; + let _temp_80 = 0; + let _temp_81 = 0; + let _temp_82 = 0; + let _temp_83 = 0; + let _temp_84 = 0; + let _temp_85 = 0; + let _temp_86 = 0; + let _temp_87 = 0; + let _temp_88 = 0; + let _temp_89 = 0; + let _temp_90 = 0; + let _temp_91 = 0; + let _temp_92 = 0; + let _temp_93 = 0; + let _temp_94 = 0; + let _temp_95 = 0; + let _temp_96 = 0; + let _temp_97 = 0; + let _temp_98 = 0; + let _temp_99 = 0; + let _temp_100 = 0; + let _temp_101 = 0; + let _temp_102 = 0; + let _temp_103 = 0; + let _temp_104 = 0; + let _temp_105 = 0; + let _temp_106 = 0; + let _temp_107 = 0; + let _temp_108 = 0; + let _temp_109 = 0; + let _temp_110 = 0; + let _temp_111 = 0; + let _temp_112 = 0; + let _temp_113 = 0; + let _temp_114 = 0; + let _temp_115 = 0; + let _temp_116 = 0; + let _temp_117 = 0; + let _temp_118 = 0; + let _temp_119 = 0; + let _temp_120 = 0; + let _temp_121 = 0; + let _temp_122 = 0; + let _temp_123 = 0; + let _temp_124 = 0; + let _temp_125 = 0; + let _temp_126 = 0; + let _temp_127 = 0; + let _temp_128 = 0; + let _temp_129 = 0; + let _temp_130 = 0; + let _temp_131 = 0; + let _temp_132 = 0; + let _temp_133 = 0; + let _temp_134 = 0; + let _temp_135 = 0; + let _temp_136 = 0; + let _temp_137 = 0; + let _temp_138 = 0; + let _temp_139 = 0; + let _temp_140 = 0; + let _temp_141 = 0; + let _temp_142 = 0; + let _temp_143 = 0; + let _temp_144 = 0; + let _temp_145 = 0; + let _temp_146 = 0; + let _temp_147 = 0; + let _temp_148 = 0; + let _temp_149 = 0; + let _temp_150 = 0; + let _temp_151 = 0; + let _temp_152 = 0; + let _temp_153 = 0; + let _temp_154 = 0; + let _temp_155 = 0; + let _temp_156 = 0; + let _temp_157 = 0; + let _temp_158 = 0; + let _temp_159 = 0; + let _temp_160 = 0; + let _temp_161 = 0; + let _temp_162 = 0; + let _temp_163 = 0; + let _temp_164 = 0; + let _temp_165 = 0; + let _temp_166 = 0; + let _temp_167 = 0; + let _temp_168 = 0; + let _temp_169 = 0; + let _temp_170 = 0; + let _temp_171 = 0; + let _temp_172 = 0; + let _temp_173 = 0; + let _temp_174 = 0; + let _temp_175 = 0; + let _temp_176 = 0; + let _temp_177 = 0; + let _temp_178 = 0; + let _temp_179 = 0; + let _temp_180 = 0; + let _temp_181 = 0; + let _temp_182 = 0; + let _temp_183 = 0; + let _temp_184 = 0; + let _temp_185 = 0; + let _temp_186 = 0; + let _temp_187 = 0; + let _temp_188 = 0; + let _temp_189 = 0; + let _temp_190 = 0; + let _temp_191 = 0; + let _temp_192 = 0; + let _temp_193 = 0; + let _temp_194 = 0; + let _temp_195 = 0; + let _temp_196 = 0; + let _temp_197 = 0; + let _temp_198 = 0; + let _temp_199 = 0; + let _temp_200 = 0; + let _temp_201 = 0; + let _temp_202 = 0; + let _temp_203 = 0; + let _temp_204 = 0; + let _temp_205 = 0; + let _temp_206 = 0; + let _temp_207 = 0; + let _temp_208 = 0; + let _temp_209 = 0; + let _temp_210 = 0; + let _temp_211 = 0; + let _temp_212 = 0; + let _temp_213 = 0; + let _temp_214 = 0; + let _temp_215 = 0; + let _temp_216 = 0; + let _temp_217 = 0; + let _temp_218 = 0; + let _temp_219 = 0; + let _temp_220 = 0; + let _temp_221 = 0; + let _temp_222 = 0; + let _temp_223 = 0; + let _temp_224 = 0; + let _temp_225 = 0; + let _temp_226 = 0; + let _temp_227 = 0; + let _temp_228 = 0; + let _temp_229 = 0; + let _temp_230 = 0; + let _temp_231 = 0; + let _temp_232 = 0; + let _temp_233 = 0; + let _temp_234 = 0; + let _temp_235 = 0; + let _temp_236 = 0; + let _temp_237 = 0; + let _temp_238 = 0; + let _temp_239 = 0; + let _temp_240 = 0; + let _temp_241 = 0; + let _temp_242 = 0; + let _temp_243 = 0; + let _temp_244 = 0; + let _temp_245 = 0; + let _temp_246 = 0; + let _temp_247 = 0; + let _temp_248 = 0; + let _temp_249 = 0; + let _temp_250 = 0; + let _temp_251 = 0; + let _temp_252 = 0; + let _temp_253 = 0; + let _temp_254 = 0; + let _temp_255 = 0; + let _temp_256 = 0; + let _temp_257 = 0; + let _temp_258 = 0; + let _temp_259 = 0; + let _temp_260 = 0; + let _temp_261 = 0; + let _temp_262 = 0; + let _temp_263 = 0; + let _temp_264 = 0; + let _temp_265 = 0; + let _temp_266 = 0; + let _temp_267 = 0; + let _temp_268 = 0; + let _temp_269 = 0; + let _temp_270 = 0; + let _temp_271 = 0; + let _temp_272 = 0; + let _temp_273 = 0; + let _temp_274 = 0; + let _temp_275 = 0; + let _temp_276 = 0; + let _temp_277 = 0; + let _temp_278 = 0; + let _temp_279 = 0; + let _temp_280 = 0; + let _temp_281 = 0; + let _temp_282 = 0; + let _temp_283 = 0; + let _temp_284 = 0; + let _temp_285 = 0; + let _temp_286 = 0; + let _temp_287 = 0; + let _temp_288 = 0; + let _temp_289 = 0; + let _temp_290 = 0; + let _temp_291 = 0; + let _temp_292 = 0; + let _temp_293 = 0; + let _temp_294 = 0; + let _temp_295 = 0; + let _temp_296 = 0; + let _temp_297 = 0; + let _temp_298 = 0; + let _temp_299 = 0; + let _temp_300 = 0; + let _temp_301 = 0; + let _temp_302 = 0; + let _temp_303 = 0; + let _temp_304 = 0; + let _temp_305 = 0; + let _temp_306 = 0; + let _temp_307 = 0; + let _temp_308 = 0; + let _temp_309 = 0; + let _temp_310 = 0; + let _temp_311 = 0; + let _temp_312 = 0; + let _temp_313 = 0; + let _temp_314 = 0; + let _temp_315 = 0; + let _temp_316 = 0; + let _temp_317 = 0; + let _temp_318 = 0; + let _temp_319 = 0; + let _temp_320 = 0; + let _temp_321 = 0; + let _temp_322 = 0; + let _temp_323 = 0; + let _temp_324 = 0; + let _temp_325 = 0; + let _temp_326 = 0; + let _temp_327 = 0; + let _temp_328 = 0; + let _temp_329 = 0; + let _temp_330 = 0; + let _temp_331 = 0; + let _temp_332 = 0; + let _temp_333 = 0; + let _temp_334 = 0; + let _temp_335 = 0; + let _temp_336 = 0; + let _temp_337 = 0; + let _temp_338 = 0; + let _temp_339 = 0; + let _temp_340 = 0; + let _temp_341 = 0; + let _temp_342 = 0; + let _temp_343 = 0; + let _temp_344 = 0; + let _temp_345 = 0; + let _temp_346 = 0; + let _temp_347 = 0; + let _temp_348 = 0; + let _temp_349 = 0; + let _temp_350 = 0; + let _temp_351 = 0; + let _temp_352 = 0; + let _temp_353 = 0; + let _temp_354 = 0; + let _temp_355 = 0; + let _temp_356 = 0; + let _temp_357 = 0; + let _temp_358 = 0; + let _temp_359 = 0; + let _temp_360 = 0; + let _temp_361 = 0; + let _temp_362 = 0; + let _temp_363 = 0; + let _temp_364 = 0; + let _temp_365 = 0; + let _temp_366 = 0; + let _temp_367 = 0; + let _temp_368 = 0; + let _temp_369 = 0; + let _temp_370 = 0; + let _temp_371 = 0; + let _temp_372 = 0; + let _temp_373 = 0; + let _temp_374 = 0; + let _temp_375 = 0; + let _temp_376 = 0; + let _temp_377 = 0; + let _temp_378 = 0; + let _temp_379 = 0; + let _temp_380 = 0; + let _temp_381 = 0; + let _temp_382 = 0; + let _temp_383 = 0; + let _temp_384 = 0; + let _temp_385 = 0; + let _temp_386 = 0; + let _temp_387 = 0; + let _temp_388 = 0; + let _temp_389 = 0; + let _temp_390 = 0; + let _temp_391 = 0; + let _temp_392 = 0; + let _temp_393 = 0; + let _temp_394 = 0; + let _temp_395 = 0; + let _temp_396 = 0; + let _temp_397 = 0; + let _temp_398 = 0; + let _temp_399 = 0; + let _temp_400 = 0; + let _temp_401 = 0; + let _temp_402 = 0; + let _temp_403 = 0; + let _temp_404 = 0; + let _temp_405 = 0; + let _temp_406 = 0; + let _temp_407 = 0; + let _temp_408 = 0; + let _temp_409 = 0; + let _temp_410 = 0; + let _temp_411 = 0; + let _temp_412 = 0; + let _temp_413 = 0; + let _temp_414 = 0; + let _temp_415 = 0; + let _temp_416 = 0; + let _temp_417 = 0; + let _temp_418 = 0; + let _temp_419 = 0; + let _temp_420 = 0; + let _temp_421 = 0; + let _temp_422 = 0; + let _temp_423 = 0; + let _temp_424 = 0; + let _temp_425 = 0; + let _temp_426 = 0; + let _temp_427 = 0; + let _temp_428 = 0; + let _temp_429 = 0; + let _temp_430 = 0; + let _temp_431 = 0; + let _temp_432 = 0; + let _temp_433 = 0; + let _temp_434 = 0; + let _temp_435 = 0; + let _temp_436 = 0; + let _temp_437 = 0; + let _temp_438 = 0; + let _temp_439 = 0; + let _temp_440 = 0; + let _temp_441 = 0; + let _temp_442 = 0; + let _temp_443 = 0; + let _temp_444 = 0; + let _temp_445 = 0; + let _temp_446 = 0; + let _temp_447 = 0; + let _temp_448 = 0; + let _temp_449 = 0; + let _temp_450 = 0; + let _temp_451 = 0; + let _temp_452 = 0; + let _temp_453 = 0; + let _temp_454 = 0; + let _temp_455 = 0; + let _temp_456 = 0; + let _temp_457 = 0; + let _temp_458 = 0; + let _temp_459 = 0; + let _temp_460 = 0; + let _temp_461 = 0; + let _temp_462 = 0; + let _temp_463 = 0; + let _temp_464 = 0; + let _temp_465 = 0; + let _temp_466 = 0; + let _temp_467 = 0; + let _temp_468 = 0; + let _temp_469 = 0; + let _temp_470 = 0; + let _temp_471 = 0; + let _temp_472 = 0; + let _temp_473 = 0; + let _temp_474 = 0; + let _temp_475 = 0; + let _temp_476 = 0; + let _temp_477 = 0; + let _temp_478 = 0; + let _temp_479 = 0; + let _temp_480 = 0; + let _temp_481 = 0; + let _temp_482 = 0; + let _temp_483 = 0; + let _temp_484 = 0; + let _temp_485 = 0; + let _temp_486 = 0; + let _temp_487 = 0; + let _temp_488 = 0; + let _temp_489 = 0; + let _temp_490 = 0; + let _temp_491 = 0; + let _temp_492 = 0; + let _temp_493 = 0; + let _temp_494 = 0; + let _temp_495 = 0; + let _temp_496 = 0; + let _temp_497 = 0; + let _temp_498 = 0; + let _temp_499 = 0; + let _temp_500 = 0; + let _temp_501 = 0; + let _temp_502 = 0; + let _temp_503 = 0; + let _temp_504 = 0; + let _temp_505 = 0; + let _temp_506 = 0; + let _temp_507 = 0; + let _temp_508 = 0; + let _temp_509 = 0; + let _temp_510 = 0; + let _temp_511 = 0; + let _temp_512 = 0; + let _temp_513 = 0; + let _temp_514 = 0; + let _temp_515 = 0; + let _temp_516 = 0; + let _temp_517 = 0; + let _temp_518 = 0; + let _temp_519 = 0; + let _temp_520 = 0; + let _temp_521 = 0; + let _temp_522 = 0; + let _temp_523 = 0; + let _temp_524 = 0; + let _temp_525 = 0; + let _temp_526 = 0; + let _temp_527 = 0; + let _temp_528 = 0; + let _temp_529 = 0; + let _temp_530 = 0; + let _temp_531 = 0; + let _temp_532 = 0; + let _temp_533 = 0; + let _temp_534 = 0; + let _temp_535 = 0; + let _temp_536 = 0; + let _temp_537 = 0; + let _temp_538 = 0; + let _temp_539 = 0; + let _temp_540 = 0; + let _temp_541 = 0; + let _temp_542 = 0; + let _temp_543 = 0; + let _temp_544 = 0; + let _temp_545 = 0; + let _temp_546 = 0; + let _temp_547 = 0; + let _temp_548 = 0; + let _temp_549 = 0; + let _temp_550 = 0; + let _temp_551 = 0; + let _temp_552 = 0; + let _temp_553 = 0; + let _temp_554 = 0; + let _temp_555 = 0; + let _temp_556 = 0; + let _temp_557 = 0; + let _temp_558 = 0; + let _temp_559 = 0; + let _temp_560 = 0; + let _temp_561 = 0; + let _temp_562 = 0; + let _temp_563 = 0; + let _temp_564 = 0; + let _temp_565 = 0; + let _temp_566 = 0; + let _temp_567 = 0; + let _temp_568 = 0; + let _temp_569 = 0; + let _temp_570 = 0; + let _temp_571 = 0; + let _temp_572 = 0; + let _temp_573 = 0; + let _temp_574 = 0; + let _temp_575 = 0; + let _temp_576 = 0; + let _temp_577 = 0; + let _temp_578 = 0; + let _temp_579 = 0; + let _temp_580 = 0; + let _temp_581 = 0; + let _temp_582 = 0; + let _temp_583 = 0; + let _temp_584 = 0; + let _temp_585 = 0; + let _temp_586 = 0; + let _temp_587 = 0; + let _temp_588 = 0; + let _temp_589 = 0; + let _temp_590 = 0; + let _temp_591 = 0; + let _temp_592 = 0; + let _temp_593 = 0; + let _temp_594 = 0; + let _temp_595 = 0; + let _temp_596 = 0; + let _temp_597 = 0; + let _temp_598 = 0; + let _temp_599 = 0; + let _temp_600 = 0; + let _temp_601 = 0; + let _temp_602 = 0; + let _temp_603 = 0; + let _temp_604 = 0; + let _temp_605 = 0; + let _temp_606 = 0; + let _temp_607 = 0; + let _temp_608 = 0; + let _temp_609 = 0; + let _temp_610 = 0; + let _temp_611 = 0; + let _temp_612 = 0; + let _temp_613 = 0; + let _temp_614 = 0; + let _temp_615 = 0; + let _temp_616 = 0; + let _temp_617 = 0; + let _temp_618 = 0; + let _temp_619 = 0; + let _temp_620 = 0; + let _temp_621 = 0; + let _temp_622 = 0; + let _temp_623 = 0; + let _temp_624 = 0; + let _temp_625 = 0; + let _temp_626 = 0; + let _temp_627 = 0; + let _temp_628 = 0; + let _temp_629 = 0; + let _temp_630 = 0; + let _temp_631 = 0; + let _temp_632 = 0; + let _temp_633 = 0; + let _temp_634 = 0; + let _temp_635 = 0; + let _temp_636 = 0; + let _temp_637 = 0; + let _temp_638 = 0; + let _temp_639 = 0; + let _temp_640 = 0; + let _temp_641 = 0; + let _temp_642 = 0; + let _temp_643 = 0; + let _temp_644 = 0; + let _temp_645 = 0; + let _temp_646 = 0; + let _temp_647 = 0; + let _temp_648 = 0; + let _temp_649 = 0; + let _temp_650 = 0; + let _temp_651 = 0; + let _temp_652 = 0; + let _temp_653 = 0; + let _temp_654 = 0; + let _temp_655 = 0; + let _temp_656 = 0; + let _temp_657 = 0; + let _temp_658 = 0; + let _temp_659 = 0; + let _temp_660 = 0; + let _temp_661 = 0; + let _temp_662 = 0; + let _temp_663 = 0; + let _temp_664 = 0; + let _temp_665 = 0; + let _temp_666 = 0; + let _temp_667 = 0; + let _temp_668 = 0; + let _temp_669 = 0; + let _temp_670 = 0; + let _temp_671 = 0; + let _temp_672 = 0; + let _temp_673 = 0; + let _temp_674 = 0; + let _temp_675 = 0; + let _temp_676 = 0; + let _temp_677 = 0; + let _temp_678 = 0; + let _temp_679 = 0; + let _temp_680 = 0; + let _temp_681 = 0; + let _temp_682 = 0; + let _temp_683 = 0; + let _temp_684 = 0; + let _temp_685 = 0; + let _temp_686 = 0; + let _temp_687 = 0; + let _temp_688 = 0; + let _temp_689 = 0; + let _temp_690 = 0; + let _temp_691 = 0; + let _temp_692 = 0; + let _temp_693 = 0; + let _temp_694 = 0; + let _temp_695 = 0; + let _temp_696 = 0; + let _temp_697 = 0; + let _temp_698 = 0; + let _temp_699 = 0; + let _temp_700 = 0; + let _temp_701 = 0; + let _temp_702 = 0; + let _temp_703 = 0; + let _temp_704 = 0; + let _temp_705 = 0; + let _temp_706 = 0; + let _temp_707 = 0; + let _temp_708 = 0; + let _temp_709 = 0; + let _temp_710 = 0; + let _temp_711 = 0; + let _temp_712 = 0; + let _temp_713 = 0; + let _temp_714 = 0; + let _temp_715 = 0; + let _temp_716 = 0; + let _temp_717 = 0; + let _temp_718 = 0; + let _temp_719 = 0; + let _temp_720 = 0; + let _temp_721 = 0; + let _temp_722 = 0; + let _temp_723 = 0; + let _temp_724 = 0; + let _temp_725 = 0; + let _temp_726 = 0; + let _temp_727 = 0; + let _temp_728 = 0; + let _temp_729 = 0; + let _temp_730 = 0; + let _temp_731 = 0; + let _temp_732 = 0; + let _temp_733 = 0; + let _temp_734 = 0; + let _temp_735 = 0; + let _temp_736 = 0; + let _temp_737 = 0; + let _temp_738 = 0; + let _temp_739 = 0; + let _temp_740 = 0; + let _temp_741 = 0; + let _temp_742 = 0; + let _temp_743 = 0; + let _temp_744 = 0; + let _temp_745 = 0; + let _temp_746 = 0; + let _temp_747 = 0; + let _temp_748 = 0; + let _temp_749 = 0; + let _temp_750 = 0; + let _temp_751 = 0; + let _temp_752 = 0; + let _temp_753 = 0; + let _temp_754 = 0; + let _temp_755 = 0; + let _temp_756 = 0; + let _temp_757 = 0; + let _temp_758 = 0; + let _temp_759 = 0; + let _temp_760 = 0; + let _temp_761 = 0; + let _temp_762 = 0; + let _temp_763 = 0; + let _temp_764 = 0; + let _temp_765 = 0; + let _temp_766 = 0; + let _temp_767 = 0; + let _temp_768 = 0; + let _temp_769 = 0; + let _temp_770 = 0; + let _temp_771 = 0; + let _temp_772 = 0; + let _temp_773 = 0; + let _temp_774 = 0; + let _temp_775 = 0; + let _temp_776 = 0; + let _temp_777 = 0; + let _temp_778 = 0; + let _temp_779 = 0; + let _temp_780 = 0; + let _temp_781 = 0; + let _temp_782 = 0; + let _temp_783 = 0; + let _temp_784 = 0; + let _temp_785 = 0; + let _temp_786 = 0; + let _temp_787 = 0; + let _temp_788 = 0; + let _temp_789 = 0; + let _temp_790 = 0; + let _temp_791 = 0; + let _temp_792 = 0; + let _temp_793 = 0; + let _temp_794 = 0; + let _temp_795 = 0; + let _temp_796 = 0; + let _temp_797 = 0; + let _temp_798 = 0; + let _temp_799 = 0; + let _temp_800 = 0; + let _temp_801 = 0; + let _temp_802 = 0; + let _temp_803 = 0; + let _temp_804 = 0; + let _temp_805 = 0; + let _temp_806 = 0; + let _temp_807 = 0; + let _temp_808 = 0; + let _temp_809 = 0; + let _temp_810 = 0; + let _temp_811 = 0; + let _temp_812 = 0; + let _temp_813 = 0; + let _temp_814 = 0; + let _temp_815 = 0; + let _temp_816 = 0; + let _temp_817 = 0; + let _temp_818 = 0; + let _temp_819 = 0; + let _temp_820 = 0; + let _temp_821 = 0; + let _temp_822 = 0; + let _temp_823 = 0; + let _temp_824 = 0; + let _temp_825 = 0; + let _temp_826 = 0; + let _temp_827 = 0; + let _temp_828 = 0; + let _temp_829 = 0; + let _temp_830 = 0; + let _temp_831 = 0; + let _temp_832 = 0; + let _temp_833 = 0; + let _temp_834 = 0; + let _temp_835 = 0; + let _temp_836 = 0; + let _temp_837 = 0; + let _temp_838 = 0; + let _temp_839 = 0; + let _temp_840 = 0; + let _temp_841 = 0; + let _temp_842 = 0; + let _temp_843 = 0; + let _temp_844 = 0; + let _temp_845 = 0; + let _temp_846 = 0; + let _temp_847 = 0; + let _temp_848 = 0; + let _temp_849 = 0; + let _temp_850 = 0; + let _temp_851 = 0; + let _temp_852 = 0; + let _temp_853 = 0; + let _temp_854 = 0; + let _temp_855 = 0; + let _temp_856 = 0; + let _temp_857 = 0; + let _temp_858 = 0; + let _temp_859 = 0; + let _temp_860 = 0; + let _temp_861 = 0; + let _temp_862 = 0; + let _temp_863 = 0; + let _temp_864 = 0; + let _temp_865 = 0; + let _temp_866 = 0; + let _temp_867 = 0; + let _temp_868 = 0; + let _temp_869 = 0; + let _temp_870 = 0; + let _temp_871 = 0; + let _temp_872 = 0; + let _temp_873 = 0; + let _temp_874 = 0; + let _temp_875 = 0; + let _temp_876 = 0; + let _temp_877 = 0; + let _temp_878 = 0; + let _temp_879 = 0; + let _temp_880 = 0; + let _temp_881 = 0; + let _temp_882 = 0; + let _temp_883 = 0; + let _temp_884 = 0; + let _temp_885 = 0; + let _temp_886 = 0; + let _temp_887 = 0; + let _temp_888 = 0; + let _temp_889 = 0; + let _temp_890 = 0; + let _temp_891 = 0; + let _temp_892 = 0; + let _temp_893 = 0; + let _temp_894 = 0; + let _temp_895 = 0; + let _temp_896 = 0; + let _temp_897 = 0; + let _temp_898 = 0; + let _temp_899 = 0; + let _temp_900 = 0; + let _temp_901 = 0; + let _temp_902 = 0; + let _temp_903 = 0; + let _temp_904 = 0; + let _temp_905 = 0; + let _temp_906 = 0; + let _temp_907 = 0; + let _temp_908 = 0; + let _temp_909 = 0; + let _temp_910 = 0; + let _temp_911 = 0; + let _temp_912 = 0; + let _temp_913 = 0; + let _temp_914 = 0; + let _temp_915 = 0; + let _temp_916 = 0; + let _temp_917 = 0; + let _temp_918 = 0; + let _temp_919 = 0; + let _temp_920 = 0; + let _temp_921 = 0; + let _temp_922 = 0; + let _temp_923 = 0; + let _temp_924 = 0; + let _temp_925 = 0; + let _temp_926 = 0; + let _temp_927 = 0; + let _temp_928 = 0; + let _temp_929 = 0; + let _temp_930 = 0; + let _temp_931 = 0; + let _temp_932 = 0; + let _temp_933 = 0; + let _temp_934 = 0; + let _temp_935 = 0; + let _temp_936 = 0; + let _temp_937 = 0; + let _temp_938 = 0; + let _temp_939 = 0; + let _temp_940 = 0; + let _temp_941 = 0; + let _temp_942 = 0; + let _temp_943 = 0; + let _temp_944 = 0; + let _temp_945 = 0; + let _temp_946 = 0; + let _temp_947 = 0; + let _temp_948 = 0; + let _temp_949 = 0; + let _temp_950 = 0; + let _temp_951 = 0; + let _temp_952 = 0; + let _temp_953 = 0; + let _temp_954 = 0; + let _temp_955 = 0; + let _temp_956 = 0; + let _temp_957 = 0; + let _temp_958 = 0; + let _temp_959 = 0; + let _temp_960 = 0; + let _temp_961 = 0; + let _temp_962 = 0; + let _temp_963 = 0; + let _temp_964 = 0; + let _temp_965 = 0; + let _temp_966 = 0; + let _temp_967 = 0; + let _temp_968 = 0; + let _temp_969 = 0; + let _temp_970 = 0; + let _temp_971 = 0; + let _temp_972 = 0; + let _temp_973 = 0; + let _temp_974 = 0; + let _temp_975 = 0; + let _temp_976 = 0; + let _temp_977 = 0; + let _temp_978 = 0; + let _temp_979 = 0; + let _temp_980 = 0; + let _temp_981 = 0; + let _temp_982 = 0; + let _temp_983 = 0; + let _temp_984 = 0; + let _temp_985 = 0; + let _temp_986 = 0; + let _temp_987 = 0; + let _temp_988 = 0; + let _temp_989 = 0; + let _temp_990 = 0; + let _temp_991 = 0; + let _temp_992 = 0; + let _temp_993 = 0; + let _temp_994 = 0; + let _temp_995 = 0; + let _temp_996 = 0; + let _temp_997 = 0; + let _temp_998 = 0; + let _temp_999 = 0; + let _temp_1000 = 0; + let _temp_1001 = 0; + let _temp_1002 = 0; + let _temp_1003 = 0; + let _temp_1004 = 0; + let _temp_1005 = 0; + let _temp_1006 = 0; + let _temp_1007 = 0; + let _temp_1008 = 0; + let _temp_1009 = 0; + let _temp_1010 = 0; + let _temp_1011 = 0; + let _temp_1012 = 0; + let _temp_1013 = 0; + let _temp_1014 = 0; + let _temp_1015 = 0; + let _temp_1016 = 0; + let _temp_1017 = 0; + let _temp_1018 = 0; + let _temp_1019 = 0; + let _temp_1020 = 0; + let _temp_1021 = 0; + let _temp_1022 = 0; + let _temp_1023 = 0; + let _temp_1024 = 0; + let _temp_1025 = 0; + let _temp_1026 = 0; + let _temp_1027 = 0; + let _temp_1028 = 0; + let _temp_1029 = 0; + let _temp_1030 = 0; + let _temp_1031 = 0; + let _temp_1032 = 0; + let _temp_1033 = 0; + let _temp_1034 = 0; + let _temp_1035 = 0; + let _temp_1036 = 0; + let _temp_1037 = 0; + let _temp_1038 = 0; + let _temp_1039 = 0; + let _temp_1040 = 0; + let _temp_1041 = 0; + let _temp_1042 = 0; + let _temp_1043 = 0; + let _temp_1044 = 0; + let _temp_1045 = 0; + let _temp_1046 = 0; + let _temp_1047 = 0; + let _temp_1048 = 0; + let _temp_1049 = 0; + let _temp_1050 = 0; + let _temp_1051 = 0; + let _temp_1052 = 0; + let _temp_1053 = 0; + let _temp_1054 = 0; + let _temp_1055 = 0; + let _temp_1056 = 0; + let _temp_1057 = 0; + let _temp_1058 = 0; + let _temp_1059 = 0; + let _temp_1060 = 0; + let _temp_1061 = 0; + let _temp_1062 = 0; + let _temp_1063 = 0; + let _temp_1064 = 0; + let _temp_1065 = 0; + let _temp_1066 = 0; + let _temp_1067 = 0; + let _temp_1068 = 0; + let _temp_1069 = 0; + let _temp_1070 = 0; + let _temp_1071 = 0; + let _temp_1072 = 0; + let _temp_1073 = 0; + let _temp_1074 = 0; + let _temp_1075 = 0; + let _temp_1076 = 0; + let _temp_1077 = 0; + let _temp_1078 = 0; + let _temp_1079 = 0; + let _temp_1080 = 0; + let _temp_1081 = 0; + let _temp_1082 = 0; + let _temp_1083 = 0; + let _temp_1084 = 0; + let _temp_1085 = 0; + let _temp_1086 = 0; + let _temp_1087 = 0; + let _temp_1088 = 0; + let _temp_1089 = 0; + let _temp_1090 = 0; + let _temp_1091 = 0; + let _temp_1092 = 0; + let _temp_1093 = 0; + let _temp_1094 = 0; + let _temp_1095 = 0; + let _temp_1096 = 0; + let _temp_1097 = 0; + let _temp_1098 = 0; + let _temp_1099 = 0; + let _temp_1100 = 0; + let _temp_1101 = 0; + let _temp_1102 = 0; + let _temp_1103 = 0; + let _temp_1104 = 0; + let _temp_1105 = 0; + let _temp_1106 = 0; + let _temp_1107 = 0; + let _temp_1108 = 0; + let _temp_1109 = 0; + let _temp_1110 = 0; + let _temp_1111 = 0; + let _temp_1112 = 0; + let _temp_1113 = 0; + let _temp_1114 = 0; + let _temp_1115 = 0; + let _temp_1116 = 0; + let _temp_1117 = 0; + let _temp_1118 = 0; + let _temp_1119 = 0; + let _temp_1120 = 0; + let _temp_1121 = 0; + let _temp_1122 = 0; + let _temp_1123 = 0; + let _temp_1124 = 0; + let _temp_1125 = 0; + let _temp_1126 = 0; + let _temp_1127 = 0; + let _temp_1128 = 0; + let _temp_1129 = 0; + let _temp_1130 = 0; + let _temp_1131 = 0; + let _temp_1132 = 0; + let _temp_1133 = 0; + let _temp_1134 = 0; + let _temp_1135 = 0; + let _temp_1136 = 0; + let _temp_1137 = 0; + let _temp_1138 = 0; + let _temp_1139 = 0; + let _temp_1140 = 0; + let _temp_1141 = 0; + let _temp_1142 = 0; + let _temp_1143 = 0; + let _temp_1144 = 0; + let _temp_1145 = 0; + let _temp_1146 = 0; + let _temp_1147 = 0; + let _temp_1148 = 0; + let _temp_1149 = 0; + let _temp_1150 = 0; + let _temp_1151 = 0; + let _temp_1152 = 0; + let _temp_1153 = 0; + let _temp_1154 = 0; + let _temp_1155 = 0; + let _temp_1156 = 0; + let _temp_1157 = 0; + let _temp_1158 = 0; + let _temp_1159 = 0; + let _temp_1160 = 0; + let _temp_1161 = 0; + let _temp_1162 = 0; + let _temp_1163 = 0; + let _temp_1164 = 0; + let _temp_1165 = 0; + let _temp_1166 = 0; + let _temp_1167 = 0; + let _temp_1168 = 0; + let _temp_1169 = 0; + let _temp_1170 = 0; + let _temp_1171 = 0; + let _temp_1172 = 0; + let _temp_1173 = 0; + let _temp_1174 = 0; + let _temp_1175 = 0; + let _temp_1176 = 0; + let _temp_1177 = 0; + let _temp_1178 = 0; + let _temp_1179 = 0; + let _temp_1180 = 0; + let _temp_1181 = 0; + let _temp_1182 = 0; + let _temp_1183 = 0; + let _temp_1184 = 0; + let _temp_1185 = 0; + let _temp_1186 = 0; + let _temp_1187 = 0; + let _temp_1188 = 0; + let _temp_1189 = 0; + let _temp_1190 = 0; + let _temp_1191 = 0; + let _temp_1192 = 0; + let _temp_1193 = 0; + let _temp_1194 = 0; + let _temp_1195 = 0; + let _temp_1196 = 0; + let _temp_1197 = 0; + let _temp_1198 = 0; + let _temp_1199 = 0; + let _temp_1200 = 0; + let _temp_1201 = 0; + let _temp_1202 = 0; + let _temp_1203 = 0; + let _temp_1204 = 0; + let _temp_1205 = 0; + let _temp_1206 = 0; + let _temp_1207 = 0; + let _temp_1208 = 0; + let _temp_1209 = 0; + let _temp_1210 = 0; + let _temp_1211 = 0; + let _temp_1212 = 0; + let _temp_1213 = 0; + let _temp_1214 = 0; + let _temp_1215 = 0; + let _temp_1216 = 0; + let _temp_1217 = 0; + let _temp_1218 = 0; + let _temp_1219 = 0; + let _temp_1220 = 0; + let _temp_1221 = 0; + let _temp_1222 = 0; + let _temp_1223 = 0; + let _temp_1224 = 0; + let _temp_1225 = 0; + let _temp_1226 = 0; + let _temp_1227 = 0; + let _temp_1228 = 0; + let _temp_1229 = 0; + let _temp_1230 = 0; + let _temp_1231 = 0; + let _temp_1232 = 0; + let _temp_1233 = 0; + let _temp_1234 = 0; + let _temp_1235 = 0; + let _temp_1236 = 0; + let _temp_1237 = 0; + let _temp_1238 = 0; + let _temp_1239 = 0; + let _temp_1240 = 0; + let _temp_1241 = 0; + let _temp_1242 = 0; + let _temp_1243 = 0; + let _temp_1244 = 0; + let _temp_1245 = 0; + let _temp_1246 = 0; + let _temp_1247 = 0; + let _temp_1248 = 0; + let _temp_1249 = 0; + let _temp_1250 = 0; + let _temp_1251 = 0; + let _temp_1252 = 0; + let _temp_1253 = 0; + let _temp_1254 = 0; + let _temp_1255 = 0; + let _temp_1256 = 0; + let _temp_1257 = 0; + let _temp_1258 = 0; + let _temp_1259 = 0; + let _temp_1260 = 0; + let _temp_1261 = 0; + let _temp_1262 = 0; + let _temp_1263 = 0; + let _temp_1264 = 0; + let _temp_1265 = 0; + let _temp_1266 = 0; + let _temp_1267 = 0; + let _temp_1268 = 0; + let _temp_1269 = 0; + let _temp_1270 = 0; + let _temp_1271 = 0; + let _temp_1272 = 0; + let _temp_1273 = 0; + let _temp_1274 = 0; + let _temp_1275 = 0; + let _temp_1276 = 0; + let _temp_1277 = 0; + let _temp_1278 = 0; + let _temp_1279 = 0; + let _temp_1280 = 0; + let _temp_1281 = 0; + let _temp_1282 = 0; + let _temp_1283 = 0; + let _temp_1284 = 0; + let _temp_1285 = 0; + let _temp_1286 = 0; + let _temp_1287 = 0; + let _temp_1288 = 0; + let _temp_1289 = 0; + let _temp_1290 = 0; + let _temp_1291 = 0; + let _temp_1292 = 0; + let _temp_1293 = 0; + let _temp_1294 = 0; + let _temp_1295 = 0; + let _temp_1296 = 0; + let _temp_1297 = 0; + let _temp_1298 = 0; + let _temp_1299 = 0; + let _temp_1300 = 0; + let _temp_1301 = 0; + let _temp_1302 = 0; + let _temp_1303 = 0; + let _temp_1304 = 0; + let _temp_1305 = 0; + let _temp_1306 = 0; + let _temp_1307 = 0; + let _temp_1308 = 0; + let _temp_1309 = 0; + let _temp_1310 = 0; + let _temp_1311 = 0; + let _temp_1312 = 0; + let _temp_1313 = 0; + let _temp_1314 = 0; + let _temp_1315 = 0; + let _temp_1316 = 0; + let _temp_1317 = 0; + let _temp_1318 = 0; + let _temp_1319 = 0; + let _temp_1320 = 0; + let _temp_1321 = 0; + let _temp_1322 = 0; + let _temp_1323 = 0; + let _temp_1324 = 0; + let _temp_1325 = 0; + let _temp_1326 = 0; + let _temp_1327 = 0; + let _temp_1328 = 0; + let _temp_1329 = 0; + let _temp_1330 = 0; + let _temp_1331 = 0; + let _temp_1332 = 0; + let _temp_1333 = 0; + let _temp_1334 = 0; + let _temp_1335 = 0; + let _temp_1336 = 0; + let _temp_1337 = 0; + let _temp_1338 = 0; + let _temp_1339 = 0; + let _temp_1340 = 0; + let _temp_1341 = 0; + let _temp_1342 = 0; + let _temp_1343 = 0; + let _temp_1344 = 0; + let _temp_1345 = 0; + let _temp_1346 = 0; + let _temp_1347 = 0; + let _temp_1348 = 0; + let _temp_1349 = 0; + let _temp_1350 = 0; + let _temp_1351 = 0; + let _temp_1352 = 0; + let _temp_1353 = 0; + let _temp_1354 = 0; + let _temp_1355 = 0; + let _temp_1356 = 0; + let _temp_1357 = 0; + let _temp_1358 = 0; + let _temp_1359 = 0; + let _temp_1360 = 0; + let _temp_1361 = 0; + let _temp_1362 = 0; + let _temp_1363 = 0; + let _temp_1364 = 0; + let _temp_1365 = 0; + let _temp_1366 = 0; + let _temp_1367 = 0; + let _temp_1368 = 0; + let _temp_1369 = 0; + let _temp_1370 = 0; + let _temp_1371 = 0; + let _temp_1372 = 0; + let _temp_1373 = 0; + let _temp_1374 = 0; + let _temp_1375 = 0; + let _temp_1376 = 0; + let _temp_1377 = 0; + let _temp_1378 = 0; + let _temp_1379 = 0; + let _temp_1380 = 0; + let _temp_1381 = 0; + let _temp_1382 = 0; + let _temp_1383 = 0; + let _temp_1384 = 0; + let _temp_1385 = 0; + let _temp_1386 = 0; + let _temp_1387 = 0; + let _temp_1388 = 0; + let _temp_1389 = 0; + let _temp_1390 = 0; + let _temp_1391 = 0; + let _temp_1392 = 0; + let _temp_1393 = 0; + let _temp_1394 = 0; + let _temp_1395 = 0; + let _temp_1396 = 0; + let _temp_1397 = 0; + let _temp_1398 = 0; + let _temp_1399 = 0; + let _temp_1400 = 0; + let _temp_1401 = 0; + let _temp_1402 = 0; + let _temp_1403 = 0; + let _temp_1404 = 0; + let _temp_1405 = 0; + let _temp_1406 = 0; + let _temp_1407 = 0; + let _temp_1408 = 0; + let _temp_1409 = 0; + let _temp_1410 = 0; + let _temp_1411 = 0; + let _temp_1412 = 0; + let _temp_1413 = 0; + let _temp_1414 = 0; + let _temp_1415 = 0; + let _temp_1416 = 0; + let _temp_1417 = 0; + let _temp_1418 = 0; + let _temp_1419 = 0; + let _temp_1420 = 0; + let _temp_1421 = 0; + let _temp_1422 = 0; + let _temp_1423 = 0; + let _temp_1424 = 0; + let _temp_1425 = 0; + let _temp_1426 = 0; + let _temp_1427 = 0; + let _temp_1428 = 0; + let _temp_1429 = 0; + let _temp_1430 = 0; + let _temp_1431 = 0; + let _temp_1432 = 0; + let _temp_1433 = 0; + let _temp_1434 = 0; + let _temp_1435 = 0; + let _temp_1436 = 0; + let _temp_1437 = 0; + let _temp_1438 = 0; + let _temp_1439 = 0; + let _temp_1440 = 0; + let _temp_1441 = 0; + let _temp_1442 = 0; + let _temp_1443 = 0; + let _temp_1444 = 0; + let _temp_1445 = 0; + let _temp_1446 = 0; + let _temp_1447 = 0; + let _temp_1448 = 0; + let _temp_1449 = 0; + let _temp_1450 = 0; + let _temp_1451 = 0; + let _temp_1452 = 0; + let _temp_1453 = 0; + let _temp_1454 = 0; + let _temp_1455 = 0; + let _temp_1456 = 0; + let _temp_1457 = 0; + let _temp_1458 = 0; + let _temp_1459 = 0; + let _temp_1460 = 0; + let _temp_1461 = 0; + let _temp_1462 = 0; + let _temp_1463 = 0; + let _temp_1464 = 0; + let _temp_1465 = 0; + let _temp_1466 = 0; + let _temp_1467 = 0; + let _temp_1468 = 0; + let _temp_1469 = 0; + let _temp_1470 = 0; + let _temp_1471 = 0; + let _temp_1472 = 0; + let _temp_1473 = 0; + let _temp_1474 = 0; + let _temp_1475 = 0; + let _temp_1476 = 0; + let _temp_1477 = 0; + let _temp_1478 = 0; + let _temp_1479 = 0; + let _temp_1480 = 0; + let _temp_1481 = 0; + let _temp_1482 = 0; + let _temp_1483 = 0; + let _temp_1484 = 0; + let _temp_1485 = 0; + let _temp_1486 = 0; + let _temp_1487 = 0; + let _temp_1488 = 0; + let _temp_1489 = 0; + let _temp_1490 = 0; + let _temp_1491 = 0; + let _temp_1492 = 0; + let _temp_1493 = 0; + let _temp_1494 = 0; + let _temp_1495 = 0; + let _temp_1496 = 0; + let _temp_1497 = 0; + let _temp_1498 = 0; + let _temp_1499 = 0; + let _temp_1500 = 0; + let _temp_1501 = 0; + let _temp_1502 = 0; + let _temp_1503 = 0; + let _temp_1504 = 0; + let _temp_1505 = 0; + let _temp_1506 = 0; + let _temp_1507 = 0; + let _temp_1508 = 0; + let _temp_1509 = 0; + let _temp_1510 = 0; + let _temp_1511 = 0; + let _temp_1512 = 0; + let _temp_1513 = 0; + let _temp_1514 = 0; + let _temp_1515 = 0; + let _temp_1516 = 0; + let _temp_1517 = 0; + let _temp_1518 = 0; + let _temp_1519 = 0; + let _temp_1520 = 0; + let _temp_1521 = 0; + let _temp_1522 = 0; + let _temp_1523 = 0; + let _temp_1524 = 0; + let _temp_1525 = 0; + let _temp_1526 = 0; + let _temp_1527 = 0; + let _temp_1528 = 0; + let _temp_1529 = 0; + let _temp_1530 = 0; + let _temp_1531 = 0; + let _temp_1532 = 0; + let _temp_1533 = 0; + let _temp_1534 = 0; + let _temp_1535 = 0; + let _temp_1536 = 0; + let _temp_1537 = 0; + let _temp_1538 = 0; + let _temp_1539 = 0; + let _temp_1540 = 0; + let _temp_1541 = 0; + let _temp_1542 = 0; + let _temp_1543 = 0; + let _temp_1544 = 0; + let _temp_1545 = 0; + let _temp_1546 = 0; + let _temp_1547 = 0; + let _temp_1548 = 0; + let _temp_1549 = 0; + let _temp_1550 = 0; + let _temp_1551 = 0; + let _temp_1552 = 0; + let _temp_1553 = 0; + let _temp_1554 = 0; + let _temp_1555 = 0; + let _temp_1556 = 0; + let _temp_1557 = 0; + let _temp_1558 = 0; + let _temp_1559 = 0; + let _temp_1560 = 0; + let _temp_1561 = 0; + let _temp_1562 = 0; + let _temp_1563 = 0; + let _temp_1564 = 0; + let _temp_1565 = 0; + let _temp_1566 = 0; + let _temp_1567 = 0; + let _temp_1568 = 0; + let _temp_1569 = 0; + let _temp_1570 = 0; + let _temp_1571 = 0; + let _temp_1572 = 0; + let _temp_1573 = 0; + let _temp_1574 = 0; + let _temp_1575 = 0; + let _temp_1576 = 0; + let _temp_1577 = 0; + let _temp_1578 = 0; + let _temp_1579 = 0; + let _temp_1580 = 0; + let _temp_1581 = 0; + let _temp_1582 = 0; + let _temp_1583 = 0; + let _temp_1584 = 0; + let _temp_1585 = 0; + let _temp_1586 = 0; + let _temp_1587 = 0; + let _temp_1588 = 0; + let _temp_1589 = 0; + let _temp_1590 = 0; + let _temp_1591 = 0; + let _temp_1592 = 0; + let _temp_1593 = 0; + let _temp_1594 = 0; + let _temp_1595 = 0; + let _temp_1596 = 0; + let _temp_1597 = 0; + let _temp_1598 = 0; + let _temp_1599 = 0; + let _temp_1600 = 0; + let _temp_1601 = 0; + let _temp_1602 = 0; + let _temp_1603 = 0; + let _temp_1604 = 0; + let _temp_1605 = 0; + let _temp_1606 = 0; + let _temp_1607 = 0; + let _temp_1608 = 0; + let _temp_1609 = 0; + let _temp_1610 = 0; + let _temp_1611 = 0; + let _temp_1612 = 0; + let _temp_1613 = 0; + let _temp_1614 = 0; + let _temp_1615 = 0; + let _temp_1616 = 0; + let _temp_1617 = 0; + let _temp_1618 = 0; + let _temp_1619 = 0; + let _temp_1620 = 0; + let _temp_1621 = 0; + let _temp_1622 = 0; + let _temp_1623 = 0; + let _temp_1624 = 0; + let _temp_1625 = 0; + let _temp_1626 = 0; + let _temp_1627 = 0; + let _temp_1628 = 0; + let _temp_1629 = 0; + let _temp_1630 = 0; + let _temp_1631 = 0; + let _temp_1632 = 0; + let _temp_1633 = 0; + let _temp_1634 = 0; + let _temp_1635 = 0; + let _temp_1636 = 0; + let _temp_1637 = 0; + let _temp_1638 = 0; + let _temp_1639 = 0; + let _temp_1640 = 0; + let _temp_1641 = 0; + let _temp_1642 = 0; + let _temp_1643 = 0; + let _temp_1644 = 0; + let _temp_1645 = 0; + let _temp_1646 = 0; + let _temp_1647 = 0; + let _temp_1648 = 0; + let _temp_1649 = 0; + let _temp_1650 = 0; + let _temp_1651 = 0; + let _temp_1652 = 0; + let _temp_1653 = 0; + let _temp_1654 = 0; + let _temp_1655 = 0; + let _temp_1656 = 0; + let _temp_1657 = 0; + let _temp_1658 = 0; + let _temp_1659 = 0; + let _temp_1660 = 0; + let _temp_1661 = 0; + let _temp_1662 = 0; + let _temp_1663 = 0; + let _temp_1664 = 0; + let _temp_1665 = 0; + let _temp_1666 = 0; + let _temp_1667 = 0; + let _temp_1668 = 0; + let _temp_1669 = 0; + let _temp_1670 = 0; + let _temp_1671 = 0; + let _temp_1672 = 0; + let _temp_1673 = 0; + let _temp_1674 = 0; + let _temp_1675 = 0; + let _temp_1676 = 0; + let _temp_1677 = 0; + let _temp_1678 = 0; + let _temp_1679 = 0; + let _temp_1680 = 0; + let _temp_1681 = 0; + let _temp_1682 = 0; + let _temp_1683 = 0; + let _temp_1684 = 0; + let _temp_1685 = 0; + let _temp_1686 = 0; + let _temp_1687 = 0; + let _temp_1688 = 0; + let _temp_1689 = 0; + let _temp_1690 = 0; + let _temp_1691 = 0; + let _temp_1692 = 0; + let _temp_1693 = 0; + let _temp_1694 = 0; + let _temp_1695 = 0; + let _temp_1696 = 0; + let _temp_1697 = 0; + let _temp_1698 = 0; + let _temp_1699 = 0; + let _temp_1700 = 0; + let _temp_1701 = 0; + let _temp_1702 = 0; + let _temp_1703 = 0; + let _temp_1704 = 0; + let _temp_1705 = 0; + let _temp_1706 = 0; + let _temp_1707 = 0; + let _temp_1708 = 0; + let _temp_1709 = 0; + let _temp_1710 = 0; + let _temp_1711 = 0; + let _temp_1712 = 0; + let _temp_1713 = 0; + let _temp_1714 = 0; + let _temp_1715 = 0; + let _temp_1716 = 0; + let _temp_1717 = 0; + let _temp_1718 = 0; + let _temp_1719 = 0; + let _temp_1720 = 0; + let _temp_1721 = 0; + let _temp_1722 = 0; + let _temp_1723 = 0; + let _temp_1724 = 0; + let _temp_1725 = 0; + let _temp_1726 = 0; + let _temp_1727 = 0; + let _temp_1728 = 0; + let _temp_1729 = 0; + let _temp_1730 = 0; + let _temp_1731 = 0; + let _temp_1732 = 0; + let _temp_1733 = 0; + let _temp_1734 = 0; + let _temp_1735 = 0; + let _temp_1736 = 0; + let _temp_1737 = 0; + let _temp_1738 = 0; + let _temp_1739 = 0; + let _temp_1740 = 0; + let _temp_1741 = 0; + let _temp_1742 = 0; + let _temp_1743 = 0; + let _temp_1744 = 0; + let _temp_1745 = 0; + let _temp_1746 = 0; + let _temp_1747 = 0; + let _temp_1748 = 0; + let _temp_1749 = 0; + let _temp_1750 = 0; + let _temp_1751 = 0; + let _temp_1752 = 0; + let _temp_1753 = 0; + let _temp_1754 = 0; + let _temp_1755 = 0; + let _temp_1756 = 0; + let _temp_1757 = 0; + let _temp_1758 = 0; + let _temp_1759 = 0; + let _temp_1760 = 0; + let _temp_1761 = 0; + let _temp_1762 = 0; + let _temp_1763 = 0; + let _temp_1764 = 0; + let _temp_1765 = 0; + let _temp_1766 = 0; + let _temp_1767 = 0; + let _temp_1768 = 0; + let _temp_1769 = 0; + let _temp_1770 = 0; + let _temp_1771 = 0; + let _temp_1772 = 0; + let _temp_1773 = 0; + let _temp_1774 = 0; + let _temp_1775 = 0; + let _temp_1776 = 0; + let _temp_1777 = 0; + let _temp_1778 = 0; + let _temp_1779 = 0; + let _temp_1780 = 0; + let _temp_1781 = 0; + let _temp_1782 = 0; + let _temp_1783 = 0; + let _temp_1784 = 0; + let _temp_1785 = 0; + let _temp_1786 = 0; + let _temp_1787 = 0; + let _temp_1788 = 0; + let _temp_1789 = 0; + let _temp_1790 = 0; + let _temp_1791 = 0; + let _temp_1792 = 0; + let _temp_1793 = 0; + let _temp_1794 = 0; + let _temp_1795 = 0; + let _temp_1796 = 0; + let _temp_1797 = 0; + let _temp_1798 = 0; + let _temp_1799 = 0; + let _temp_1800 = 0; + let _temp_1801 = 0; + let _temp_1802 = 0; + let _temp_1803 = 0; + let _temp_1804 = 0; + let _temp_1805 = 0; + let _temp_1806 = 0; + let _temp_1807 = 0; + let _temp_1808 = 0; + let _temp_1809 = 0; + let _temp_1810 = 0; + let _temp_1811 = 0; + let _temp_1812 = 0; + let _temp_1813 = 0; + let _temp_1814 = 0; + let _temp_1815 = 0; + let _temp_1816 = 0; + let _temp_1817 = 0; + let _temp_1818 = 0; + let _temp_1819 = 0; + let _temp_1820 = 0; + let _temp_1821 = 0; + let _temp_1822 = 0; + let _temp_1823 = 0; + let _temp_1824 = 0; + let _temp_1825 = 0; + let _temp_1826 = 0; + let _temp_1827 = 0; + let _temp_1828 = 0; + let _temp_1829 = 0; + let _temp_1830 = 0; + let _temp_1831 = 0; + let _temp_1832 = 0; + let _temp_1833 = 0; + let _temp_1834 = 0; + let _temp_1835 = 0; + let _temp_1836 = 0; + let _temp_1837 = 0; + let _temp_1838 = 0; + let _temp_1839 = 0; + let _temp_1840 = 0; + let _temp_1841 = 0; + let _temp_1842 = 0; + let _temp_1843 = 0; + let _temp_1844 = 0; + let _temp_1845 = 0; + let _temp_1846 = 0; + let _temp_1847 = 0; + let _temp_1848 = 0; + let _temp_1849 = 0; + let _temp_1850 = 0; + let _temp_1851 = 0; + let _temp_1852 = 0; + let _temp_1853 = 0; + let _temp_1854 = 0; + let _temp_1855 = 0; + let _temp_1856 = 0; + let _temp_1857 = 0; + let _temp_1858 = 0; + let _temp_1859 = 0; + let _temp_1860 = 0; + let _temp_1861 = 0; + let _temp_1862 = 0; + let _temp_1863 = 0; + let _temp_1864 = 0; + let _temp_1865 = 0; + let _temp_1866 = 0; + let _temp_1867 = 0; + let _temp_1868 = 0; + let _temp_1869 = 0; + let _temp_1870 = 0; + let _temp_1871 = 0; + let _temp_1872 = 0; + let _temp_1873 = 0; + let _temp_1874 = 0; + let _temp_1875 = 0; + let _temp_1876 = 0; + let _temp_1877 = 0; + let _temp_1878 = 0; + let _temp_1879 = 0; + let _temp_1880 = 0; + let _temp_1881 = 0; + let _temp_1882 = 0; + let _temp_1883 = 0; + let _temp_1884 = 0; + let _temp_1885 = 0; + let _temp_1886 = 0; + let _temp_1887 = 0; + let _temp_1888 = 0; + let _temp_1889 = 0; + let _temp_1890 = 0; + let _temp_1891 = 0; + let _temp_1892 = 0; + let _temp_1893 = 0; + let _temp_1894 = 0; + let _temp_1895 = 0; + let _temp_1896 = 0; + let _temp_1897 = 0; + let _temp_1898 = 0; + let _temp_1899 = 0; + let _temp_1900 = 0; + let _temp_1901 = 0; + let _temp_1902 = 0; + let _temp_1903 = 0; + let _temp_1904 = 0; + let _temp_1905 = 0; + let _temp_1906 = 0; + let _temp_1907 = 0; + let _temp_1908 = 0; + let _temp_1909 = 0; + let _temp_1910 = 0; + let _temp_1911 = 0; + let _temp_1912 = 0; + let _temp_1913 = 0; + let _temp_1914 = 0; + let _temp_1915 = 0; + let _temp_1916 = 0; + let _temp_1917 = 0; + let _temp_1918 = 0; + let _temp_1919 = 0; + let _temp_1920 = 0; + let _temp_1921 = 0; + let _temp_1922 = 0; + let _temp_1923 = 0; + let _temp_1924 = 0; + let _temp_1925 = 0; + let _temp_1926 = 0; + let _temp_1927 = 0; + let _temp_1928 = 0; + let _temp_1929 = 0; + let _temp_1930 = 0; + let _temp_1931 = 0; + let _temp_1932 = 0; + let _temp_1933 = 0; + let _temp_1934 = 0; + let _temp_1935 = 0; + let _temp_1936 = 0; + let _temp_1937 = 0; + let _temp_1938 = 0; + let _temp_1939 = 0; + let _temp_1940 = 0; + let _temp_1941 = 0; + let _temp_1942 = 0; + let _temp_1943 = 0; + let _temp_1944 = 0; + let _temp_1945 = 0; + let _temp_1946 = 0; + let _temp_1947 = 0; + let _temp_1948 = 0; + let _temp_1949 = 0; + let _temp_1950 = 0; + let _temp_1951 = 0; + let _temp_1952 = 0; + let _temp_1953 = 0; + let _temp_1954 = 0; + let _temp_1955 = 0; + let _temp_1956 = 0; + let _temp_1957 = 0; + let _temp_1958 = 0; + let _temp_1959 = 0; + let _temp_1960 = 0; + let _temp_1961 = 0; + let _temp_1962 = 0; + let _temp_1963 = 0; + let _temp_1964 = 0; + let _temp_1965 = 0; + let _temp_1966 = 0; + let _temp_1967 = 0; + let _temp_1968 = 0; + let _temp_1969 = 0; + let _temp_1970 = 0; + let _temp_1971 = 0; + let _temp_1972 = 0; + let _temp_1973 = 0; + let _temp_1974 = 0; + let _temp_1975 = 0; + let _temp_1976 = 0; + let _temp_1977 = 0; + let _temp_1978 = 0; + let _temp_1979 = 0; + let _temp_1980 = 0; + let _temp_1981 = 0; + let _temp_1982 = 0; + let _temp_1983 = 0; + let _temp_1984 = 0; + let _temp_1985 = 0; + let _temp_1986 = 0; + let _temp_1987 = 0; + let _temp_1988 = 0; + let _temp_1989 = 0; + let _temp_1990 = 0; + let _temp_1991 = 0; + let _temp_1992 = 0; + let _temp_1993 = 0; + let _temp_1994 = 0; + let _temp_1995 = 0; + let _temp_1996 = 0; + let _temp_1997 = 0; + let _temp_1998 = 0; + let _temp_1999 = 0; + let _temp_2000 = 0; + let _temp_2001 = 0; + let _temp_2002 = 0; + let _temp_2003 = 0; + let _temp_2004 = 0; + let _temp_2005 = 0; + let _temp_2006 = 0; + let _temp_2007 = 0; + let _temp_2008 = 0; + let _temp_2009 = 0; + let _temp_2010 = 0; + let _temp_2011 = 0; + let _temp_2012 = 0; + let _temp_2013 = 0; + let _temp_2014 = 0; + let _temp_2015 = 0; + let _temp_2016 = 0; + let _temp_2017 = 0; + let _temp_2018 = 0; + let _temp_2019 = 0; + let _temp_2020 = 0; + let _temp_2021 = 0; + let _temp_2022 = 0; + let _temp_2023 = 0; + let _temp_2024 = 0; + let _temp_2025 = 0; + let _temp_2026 = 0; + let _temp_2027 = 0; + let _temp_2028 = 0; + let _temp_2029 = 0; + let _temp_2030 = 0; + let _temp_2031 = 0; + let _temp_2032 = 0; + let _temp_2033 = 0; + let _temp_2034 = 0; + let _temp_2035 = 0; + let _temp_2036 = 0; + let _temp_2037 = 0; + let _temp_2038 = 0; + let _temp_2039 = 0; + let _temp_2040 = 0; + let _temp_2041 = 0; + let _temp_2042 = 0; + let _temp_2043 = 0; + let _temp_2044 = 0; + let _temp_2045 = 0; + let _temp_2046 = 0; + let _temp_2047 = 0; + let _temp_2048 = 0; + let _temp_2049 = 0; + let _temp_2050 = 0; + let _temp_2051 = 0; + let _temp_2052 = 0; + let _temp_2053 = 0; + let _temp_2054 = 0; + let _temp_2055 = 0; + let _temp_2056 = 0; + let _temp_2057 = 0; + let _temp_2058 = 0; + let _temp_2059 = 0; + let _temp_2060 = 0; + let _temp_2061 = 0; + let _temp_2062 = 0; + let _temp_2063 = 0; + let _temp_2064 = 0; + let _temp_2065 = 0; + let _temp_2066 = 0; + let _temp_2067 = 0; + let _temp_2068 = 0; + let _temp_2069 = 0; + let _temp_2070 = 0; + let _temp_2071 = 0; + let _temp_2072 = 0; + let _temp_2073 = 0; + let _temp_2074 = 0; + let _temp_2075 = 0; + let _temp_2076 = 0; + let _temp_2077 = 0; + let _temp_2078 = 0; + let _temp_2079 = 0; + let _temp_2080 = 0; + let _temp_2081 = 0; + let _temp_2082 = 0; + let _temp_2083 = 0; + let _temp_2084 = 0; + let _temp_2085 = 0; + let _temp_2086 = 0; + let _temp_2087 = 0; + let _temp_2088 = 0; + let _temp_2089 = 0; + let _temp_2090 = 0; + let _temp_2091 = 0; + let _temp_2092 = 0; + let _temp_2093 = 0; + let _temp_2094 = 0; + let _temp_2095 = 0; + let _temp_2096 = 0; + let _temp_2097 = 0; + let _temp_2098 = 0; + let _temp_2099 = 0; + let _temp_2100 = 0; + let _temp_2101 = 0; + let _temp_2102 = 0; + let _temp_2103 = 0; + let _temp_2104 = 0; + let _temp_2105 = 0; + let _temp_2106 = 0; + let _temp_2107 = 0; + let _temp_2108 = 0; + let _temp_2109 = 0; + let _temp_2110 = 0; + let _temp_2111 = 0; + let _temp_2112 = 0; + let _temp_2113 = 0; + let _temp_2114 = 0; + let _temp_2115 = 0; + let _temp_2116 = 0; + let _temp_2117 = 0; + let _temp_2118 = 0; + let _temp_2119 = 0; + let _temp_2120 = 0; + let _temp_2121 = 0; + let _temp_2122 = 0; + let _temp_2123 = 0; + let _temp_2124 = 0; + let _temp_2125 = 0; + let _temp_2126 = 0; + let _temp_2127 = 0; + let _temp_2128 = 0; + let _temp_2129 = 0; + let _temp_2130 = 0; + let _temp_2131 = 0; + let _temp_2132 = 0; + let _temp_2133 = 0; + let _temp_2134 = 0; + let _temp_2135 = 0; + let _temp_2136 = 0; + let _temp_2137 = 0; + let _temp_2138 = 0; + let _temp_2139 = 0; + let _temp_2140 = 0; + let _temp_2141 = 0; + let _temp_2142 = 0; + let _temp_2143 = 0; + let _temp_2144 = 0; + let _temp_2145 = 0; + let _temp_2146 = 0; + let _temp_2147 = 0; + let _temp_2148 = 0; + let _temp_2149 = 0; + let _temp_2150 = 0; + let _temp_2151 = 0; + let _temp_2152 = 0; + let _temp_2153 = 0; + let _temp_2154 = 0; + let _temp_2155 = 0; + let _temp_2156 = 0; + let _temp_2157 = 0; + let _temp_2158 = 0; + let _temp_2159 = 0; + let _temp_2160 = 0; + let _temp_2161 = 0; + let _temp_2162 = 0; + let _temp_2163 = 0; + let _temp_2164 = 0; + let _temp_2165 = 0; + let _temp_2166 = 0; + let _temp_2167 = 0; + let _temp_2168 = 0; + let _temp_2169 = 0; + let _temp_2170 = 0; + let _temp_2171 = 0; + let _temp_2172 = 0; + let _temp_2173 = 0; + let _temp_2174 = 0; + let _temp_2175 = 0; + let _temp_2176 = 0; + let _temp_2177 = 0; + let _temp_2178 = 0; + let _temp_2179 = 0; + let _temp_2180 = 0; + let _temp_2181 = 0; + let _temp_2182 = 0; + let _temp_2183 = 0; + let _temp_2184 = 0; + let _temp_2185 = 0; + let _temp_2186 = 0; + let _temp_2187 = 0; + let _temp_2188 = 0; + let _temp_2189 = 0; + let _temp_2190 = 0; + let _temp_2191 = 0; + let _temp_2192 = 0; + let _temp_2193 = 0; + let _temp_2194 = 0; + let _temp_2195 = 0; + let _temp_2196 = 0; + let _temp_2197 = 0; + let _temp_2198 = 0; + let _temp_2199 = 0; + let _temp_2200 = 0; + let _temp_2201 = 0; + let _temp_2202 = 0; + let _temp_2203 = 0; + let _temp_2204 = 0; + let _temp_2205 = 0; + let _temp_2206 = 0; + let _temp_2207 = 0; + let _temp_2208 = 0; + let _temp_2209 = 0; + let _temp_2210 = 0; + let _temp_2211 = 0; + let _temp_2212 = 0; + let _temp_2213 = 0; + let _temp_2214 = 0; + let _temp_2215 = 0; + let _temp_2216 = 0; + let _temp_2217 = 0; + let _temp_2218 = 0; + let _temp_2219 = 0; + let _temp_2220 = 0; + let _temp_2221 = 0; + let _temp_2222 = 0; + let _temp_2223 = 0; + let _temp_2224 = 0; + let _temp_2225 = 0; + let _temp_2226 = 0; + let _temp_2227 = 0; + let _temp_2228 = 0; + let _temp_2229 = 0; + let _temp_2230 = 0; + let _temp_2231 = 0; + let _temp_2232 = 0; + let _temp_2233 = 0; + let _temp_2234 = 0; + let _temp_2235 = 0; + let _temp_2236 = 0; + let _temp_2237 = 0; + let _temp_2238 = 0; + let _temp_2239 = 0; + let _temp_2240 = 0; + let _temp_2241 = 0; + let _temp_2242 = 0; + let _temp_2243 = 0; + let _temp_2244 = 0; + let _temp_2245 = 0; + let _temp_2246 = 0; + let _temp_2247 = 0; + let _temp_2248 = 0; + let _temp_2249 = 0; + let _temp_2250 = 0; + let _temp_2251 = 0; + let _temp_2252 = 0; + let _temp_2253 = 0; + let _temp_2254 = 0; + let _temp_2255 = 0; + let _temp_2256 = 0; + let _temp_2257 = 0; + let _temp_2258 = 0; + let _temp_2259 = 0; + let _temp_2260 = 0; + let _temp_2261 = 0; + let _temp_2262 = 0; + let _temp_2263 = 0; + let _temp_2264 = 0; + let _temp_2265 = 0; + let _temp_2266 = 0; + let _temp_2267 = 0; + let _temp_2268 = 0; + let _temp_2269 = 0; + let _temp_2270 = 0; + let _temp_2271 = 0; + let _temp_2272 = 0; + let _temp_2273 = 0; + let _temp_2274 = 0; + let _temp_2275 = 0; + let _temp_2276 = 0; + let _temp_2277 = 0; + let _temp_2278 = 0; + let _temp_2279 = 0; + let _temp_2280 = 0; + let _temp_2281 = 0; + let _temp_2282 = 0; + let _temp_2283 = 0; + let _temp_2284 = 0; + let _temp_2285 = 0; + let _temp_2286 = 0; + let _temp_2287 = 0; + let _temp_2288 = 0; + let _temp_2289 = 0; + let _temp_2290 = 0; + let _temp_2291 = 0; + let _temp_2292 = 0; + let _temp_2293 = 0; + let _temp_2294 = 0; + let _temp_2295 = 0; + let _temp_2296 = 0; + let _temp_2297 = 0; + let _temp_2298 = 0; + let _temp_2299 = 0; + let _temp_2300 = 0; + let _temp_2301 = 0; + let _temp_2302 = 0; + let _temp_2303 = 0; + let _temp_2304 = 0; + let _temp_2305 = 0; + let _temp_2306 = 0; + let _temp_2307 = 0; + let _temp_2308 = 0; + let _temp_2309 = 0; + let _temp_2310 = 0; + let _temp_2311 = 0; + let _temp_2312 = 0; + let _temp_2313 = 0; + let _temp_2314 = 0; + let _temp_2315 = 0; + let _temp_2316 = 0; + let _temp_2317 = 0; + let _temp_2318 = 0; + let _temp_2319 = 0; + let _temp_2320 = 0; + let _temp_2321 = 0; + let _temp_2322 = 0; + let _temp_2323 = 0; + let _temp_2324 = 0; + let _temp_2325 = 0; + let _temp_2326 = 0; + let _temp_2327 = 0; + let _temp_2328 = 0; + let _temp_2329 = 0; + let _temp_2330 = 0; + let _temp_2331 = 0; + let _temp_2332 = 0; + let _temp_2333 = 0; + let _temp_2334 = 0; + let _temp_2335 = 0; + let _temp_2336 = 0; + let _temp_2337 = 0; + let _temp_2338 = 0; + let _temp_2339 = 0; + let _temp_2340 = 0; + let _temp_2341 = 0; + let _temp_2342 = 0; + let _temp_2343 = 0; + let _temp_2344 = 0; + let _temp_2345 = 0; + let _temp_2346 = 0; + let _temp_2347 = 0; + let _temp_2348 = 0; + let _temp_2349 = 0; + let _temp_2350 = 0; + let _temp_2351 = 0; + let _temp_2352 = 0; + let _temp_2353 = 0; + let _temp_2354 = 0; + let _temp_2355 = 0; + let _temp_2356 = 0; + let _temp_2357 = 0; + let _temp_2358 = 0; + let _temp_2359 = 0; + let _temp_2360 = 0; + let _temp_2361 = 0; + let _temp_2362 = 0; + let _temp_2363 = 0; + let _temp_2364 = 0; + let _temp_2365 = 0; + let _temp_2366 = 0; + let _temp_2367 = 0; + let _temp_2368 = 0; + let _temp_2369 = 0; + let _temp_2370 = 0; + let _temp_2371 = 0; + let _temp_2372 = 0; + let _temp_2373 = 0; + let _temp_2374 = 0; + let _temp_2375 = 0; + let _temp_2376 = 0; + let _temp_2377 = 0; + let _temp_2378 = 0; + let _temp_2379 = 0; + let _temp_2380 = 0; + let _temp_2381 = 0; + let _temp_2382 = 0; + let _temp_2383 = 0; + let _temp_2384 = 0; + let _temp_2385 = 0; + let _temp_2386 = 0; + let _temp_2387 = 0; + let _temp_2388 = 0; + let _temp_2389 = 0; + let _temp_2390 = 0; + let _temp_2391 = 0; + let _temp_2392 = 0; + let _temp_2393 = 0; + let _temp_2394 = 0; + let _temp_2395 = 0; + let _temp_2396 = 0; + let _temp_2397 = 0; + let _temp_2398 = 0; + let _temp_2399 = 0; + let _temp_2400 = 0; + let _temp_2401 = 0; + let _temp_2402 = 0; + let _temp_2403 = 0; + let _temp_2404 = 0; + let _temp_2405 = 0; + let _temp_2406 = 0; + let _temp_2407 = 0; + let _temp_2408 = 0; + let _temp_2409 = 0; + let _temp_2410 = 0; + let _temp_2411 = 0; + let _temp_2412 = 0; + let _temp_2413 = 0; + let _temp_2414 = 0; + let _temp_2415 = 0; + let _temp_2416 = 0; + let _temp_2417 = 0; + let _temp_2418 = 0; + let _temp_2419 = 0; + let _temp_2420 = 0; + let _temp_2421 = 0; + let _temp_2422 = 0; + let _temp_2423 = 0; + let _temp_2424 = 0; + let _temp_2425 = 0; + let _temp_2426 = 0; + let _temp_2427 = 0; + let _temp_2428 = 0; + let _temp_2429 = 0; + let _temp_2430 = 0; + let _temp_2431 = 0; + let _temp_2432 = 0; + let _temp_2433 = 0; + let _temp_2434 = 0; + let _temp_2435 = 0; + let _temp_2436 = 0; + let _temp_2437 = 0; + let _temp_2438 = 0; + let _temp_2439 = 0; + let _temp_2440 = 0; + let _temp_2441 = 0; + let _temp_2442 = 0; + let _temp_2443 = 0; + let _temp_2444 = 0; + let _temp_2445 = 0; + let _temp_2446 = 0; + let _temp_2447 = 0; + let _temp_2448 = 0; + let _temp_2449 = 0; + let _temp_2450 = 0; + let _temp_2451 = 0; + let _temp_2452 = 0; + let _temp_2453 = 0; + let _temp_2454 = 0; + let _temp_2455 = 0; + let _temp_2456 = 0; + let _temp_2457 = 0; + let _temp_2458 = 0; + let _temp_2459 = 0; + let _temp_2460 = 0; + let _temp_2461 = 0; + let _temp_2462 = 0; + let _temp_2463 = 0; + let _temp_2464 = 0; + let _temp_2465 = 0; + let _temp_2466 = 0; + let _temp_2467 = 0; + let _temp_2468 = 0; + let _temp_2469 = 0; + let _temp_2470 = 0; + let _temp_2471 = 0; + let _temp_2472 = 0; + let _temp_2473 = 0; + let _temp_2474 = 0; + let _temp_2475 = 0; + let _temp_2476 = 0; + let _temp_2477 = 0; + let _temp_2478 = 0; + let _temp_2479 = 0; + let _temp_2480 = 0; + let _temp_2481 = 0; + let _temp_2482 = 0; + let _temp_2483 = 0; + let _temp_2484 = 0; + let _temp_2485 = 0; + let _temp_2486 = 0; + let _temp_2487 = 0; + let _temp_2488 = 0; + let _temp_2489 = 0; + let _temp_2490 = 0; + let _temp_2491 = 0; + let _temp_2492 = 0; + let _temp_2493 = 0; + let _temp_2494 = 0; + let _temp_2495 = 0; + let _temp_2496 = 0; + let _temp_2497 = 0; + let _temp_2498 = 0; + let _temp_2499 = 0; + let _temp_2500 = 0; + let _temp_2501 = 0; + let _temp_2502 = 0; + let _temp_2503 = 0; + let _temp_2504 = 0; + let _temp_2505 = 0; + let _temp_2506 = 0; + let _temp_2507 = 0; + let _temp_2508 = 0; + let _temp_2509 = 0; + let _temp_2510 = 0; + let _temp_2511 = 0; + let _temp_2512 = 0; + let _temp_2513 = 0; + let _temp_2514 = 0; + let _temp_2515 = 0; + let _temp_2516 = 0; + let _temp_2517 = 0; + let _temp_2518 = 0; + let _temp_2519 = 0; + let _temp_2520 = 0; + let _temp_2521 = 0; + let _temp_2522 = 0; + let _temp_2523 = 0; + let _temp_2524 = 0; + let _temp_2525 = 0; + let _temp_2526 = 0; + let _temp_2527 = 0; + let _temp_2528 = 0; + let _temp_2529 = 0; + let _temp_2530 = 0; + let _temp_2531 = 0; + let _temp_2532 = 0; + let _temp_2533 = 0; + let _temp_2534 = 0; + let _temp_2535 = 0; + let _temp_2536 = 0; + let _temp_2537 = 0; + let _temp_2538 = 0; + let _temp_2539 = 0; + let _temp_2540 = 0; + let _temp_2541 = 0; + let _temp_2542 = 0; + let _temp_2543 = 0; + let _temp_2544 = 0; + let _temp_2545 = 0; + let _temp_2546 = 0; + let _temp_2547 = 0; + let _temp_2548 = 0; + let _temp_2549 = 0; + let _temp_2550 = 0; + let _temp_2551 = 0; + let _temp_2552 = 0; + let _temp_2553 = 0; + let _temp_2554 = 0; + let _temp_2555 = 0; + let _temp_2556 = 0; + let _temp_2557 = 0; + let _temp_2558 = 0; + let _temp_2559 = 0; + let _temp_2560 = 0; + let _temp_2561 = 0; + let _temp_2562 = 0; + let _temp_2563 = 0; + let _temp_2564 = 0; + let _temp_2565 = 0; + let _temp_2566 = 0; + let _temp_2567 = 0; + let _temp_2568 = 0; + let _temp_2569 = 0; + let _temp_2570 = 0; + let _temp_2571 = 0; + let _temp_2572 = 0; + let _temp_2573 = 0; + let _temp_2574 = 0; + let _temp_2575 = 0; + let _temp_2576 = 0; + let _temp_2577 = 0; + let _temp_2578 = 0; + let _temp_2579 = 0; + let _temp_2580 = 0; + let _temp_2581 = 0; + let _temp_2582 = 0; + let _temp_2583 = 0; + let _temp_2584 = 0; + let _temp_2585 = 0; + let _temp_2586 = 0; + let _temp_2587 = 0; + let _temp_2588 = 0; + let _temp_2589 = 0; + let _temp_2590 = 0; + let _temp_2591 = 0; + let _temp_2592 = 0; + let _temp_2593 = 0; +} diff --git a/src/test/ui/recursion/recursive-static-definition.stderr b/src/test/ui/recursion/recursive-static-definition.stderr index d4d2c8c3d9c..1359761457a 100644 --- a/src/test/ui/recursion/recursive-static-definition.stderr +++ b/src/test/ui/recursion/recursive-static-definition.stderr @@ -2,7 +2,7 @@ error[E0391]: cycle detected when const-evaluating + checking `FOO` --> $DIR/recursive-static-definition.rs:1:1 | LL | pub static FOO: u32 = FOO; - | ^^^^^^^^^^^^^^^^^^^^^^^^^^ + | ^^^^^^^^^^^^^^^^^^^ | note: ...which requires const-evaluating + checking `FOO`... --> $DIR/recursive-static-definition.rs:1:23 diff --git a/src/test/ui/recursion/recursive-types-are-not-uninhabited.stderr b/src/test/ui/recursion/recursive-types-are-not-uninhabited.stderr index a9159562d9d..acbd0d05984 100644 --- a/src/test/ui/recursion/recursive-types-are-not-uninhabited.stderr +++ b/src/test/ui/recursion/recursive-types-are-not-uninhabited.stderr @@ -9,15 +9,11 @@ LL | let Ok(x) = res; note: `Result<u32, &R>` defined here --> $SRC_DIR/core/src/result.rs:LL:COL | -LL | / pub enum Result<T, E> { -LL | | /// Contains the success value -LL | | #[lang = "Ok"] -LL | | #[stable(feature = "rust1", since = "1.0.0")] -... | -LL | | Err(#[stable(feature = "rust1", since = "1.0.0")] E), - | | ^^^ not covered -LL | | } - | |_- +LL | pub enum Result<T, E> { + | --------------------- +... +LL | Err(#[stable(feature = "rust1", since = "1.0.0")] E), + | ^^^ not covered = note: the matched value is of type `Result<u32, &R>` help: you might want to use `if let` to ignore the variant that isn't matched | diff --git a/src/test/ui/repr/repr-packed-contains-align.stderr b/src/test/ui/repr/repr-packed-contains-align.stderr index 32f9bb8bf33..531004e8e20 100644 --- a/src/test/ui/repr/repr-packed-contains-align.stderr +++ b/src/test/ui/repr/repr-packed-contains-align.stderr @@ -2,25 +2,25 @@ error[E0588]: packed type cannot transitively contain a `#[repr(align)]` type --> $DIR/repr-packed-contains-align.rs:19:1 | LL | struct SC(SA); - | ^^^^^^^^^^^^^^ + | ^^^^^^^^^ | note: `SA` has a `#[repr(align)]` attribute --> $DIR/repr-packed-contains-align.rs:5:1 | LL | struct SA(i32); - | ^^^^^^^^^^^^^^^ + | ^^^^^^^^^ error[E0588]: packed type cannot transitively contain a `#[repr(align)]` type --> $DIR/repr-packed-contains-align.rs:22:1 | LL | struct SD(SB); - | ^^^^^^^^^^^^^^ + | ^^^^^^^^^ | note: `SA` has a `#[repr(align)]` attribute --> $DIR/repr-packed-contains-align.rs:5:1 | LL | struct SA(i32); - | ^^^^^^^^^^^^^^^ + | ^^^^^^^^^ note: `SD` contains a field of type `SB` --> $DIR/repr-packed-contains-align.rs:22:11 | @@ -36,29 +36,25 @@ error[E0588]: packed type cannot transitively contain a `#[repr(align)]` type --> $DIR/repr-packed-contains-align.rs:25:1 | LL | struct SE(UA); - | ^^^^^^^^^^^^^^ + | ^^^^^^^^^ | note: `UA` has a `#[repr(align)]` attribute --> $DIR/repr-packed-contains-align.rs:10:1 | -LL | / union UA { -LL | | i: i32 -LL | | } - | |_^ +LL | union UA { + | ^^^^^^^^ error[E0588]: packed type cannot transitively contain a `#[repr(align)]` type --> $DIR/repr-packed-contains-align.rs:28:1 | LL | struct SF(UB); - | ^^^^^^^^^^^^^^ + | ^^^^^^^^^ | note: `UA` has a `#[repr(align)]` attribute --> $DIR/repr-packed-contains-align.rs:10:1 | -LL | / union UA { -LL | | i: i32 -LL | | } - | |_^ +LL | union UA { + | ^^^^^^^^ note: `SF` contains a field of type `UB` --> $DIR/repr-packed-contains-align.rs:28:11 | @@ -73,34 +69,26 @@ LL | a: UA error[E0588]: packed type cannot transitively contain a `#[repr(align)]` type --> $DIR/repr-packed-contains-align.rs:31:1 | -LL | / union UC { -LL | | a: UA -LL | | } - | |_^ +LL | union UC { + | ^^^^^^^^ | note: `UA` has a `#[repr(align)]` attribute --> $DIR/repr-packed-contains-align.rs:10:1 | -LL | / union UA { -LL | | i: i32 -LL | | } - | |_^ +LL | union UA { + | ^^^^^^^^ error[E0588]: packed type cannot transitively contain a `#[repr(align)]` type --> $DIR/repr-packed-contains-align.rs:36:1 | -LL | / union UD { -LL | | n: UB -LL | | } - | |_^ +LL | union UD { + | ^^^^^^^^ | note: `UA` has a `#[repr(align)]` attribute --> $DIR/repr-packed-contains-align.rs:10:1 | -LL | / union UA { -LL | | i: i32 -LL | | } - | |_^ +LL | union UA { + | ^^^^^^^^ note: `UD` contains a field of type `UB` --> $DIR/repr-packed-contains-align.rs:37:5 | @@ -115,30 +103,26 @@ LL | a: UA error[E0588]: packed type cannot transitively contain a `#[repr(align)]` type --> $DIR/repr-packed-contains-align.rs:41:1 | -LL | / union UE { -LL | | a: SA -LL | | } - | |_^ +LL | union UE { + | ^^^^^^^^ | note: `SA` has a `#[repr(align)]` attribute --> $DIR/repr-packed-contains-align.rs:5:1 | LL | struct SA(i32); - | ^^^^^^^^^^^^^^^ + | ^^^^^^^^^ error[E0588]: packed type cannot transitively contain a `#[repr(align)]` type --> $DIR/repr-packed-contains-align.rs:46:1 | -LL | / union UF { -LL | | n: SB -LL | | } - | |_^ +LL | union UF { + | ^^^^^^^^ | note: `SA` has a `#[repr(align)]` attribute --> $DIR/repr-packed-contains-align.rs:5:1 | LL | struct SA(i32); - | ^^^^^^^^^^^^^^^ + | ^^^^^^^^^ note: `UF` contains a field of type `SB` --> $DIR/repr-packed-contains-align.rs:47:5 | diff --git a/src/test/ui/repr/repr-transparent-issue-87496.stderr b/src/test/ui/repr/repr-transparent-issue-87496.stderr index c488755cc24..3dc13b1c13c 100644 --- a/src/test/ui/repr/repr-transparent-issue-87496.stderr +++ b/src/test/ui/repr/repr-transparent-issue-87496.stderr @@ -10,7 +10,7 @@ note: the type is defined here --> $DIR/repr-transparent-issue-87496.rs:6:1 | LL | struct TransparentCustomZst(()); - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^ warning: 1 warning emitted diff --git a/src/test/ui/repr/repr-transparent.stderr b/src/test/ui/repr/repr-transparent.stderr index 001a181881f..6ff3641bc15 100644 --- a/src/test/ui/repr/repr-transparent.stderr +++ b/src/test/ui/repr/repr-transparent.stderr @@ -2,9 +2,8 @@ error[E0690]: transparent struct needs at most one non-zero-sized field, but has --> $DIR/repr-transparent.rs:26:1 | LL | struct MultipleNonZst(u8, u8); - | ^^^^^^^^^^^^^^^^^^^^^^--^^--^^ - | | | | - | | | this field is non-zero-sized + | ^^^^^^^^^^^^^^^^^^^^^ -- -- this field is non-zero-sized + | | | | | this field is non-zero-sized | needs at most one non-zero-sized field, but has 2 @@ -12,9 +11,8 @@ error[E0690]: transparent struct needs at most one non-zero-sized field, but has --> $DIR/repr-transparent.rs:32:1 | LL | pub struct StructWithProjection(f32, <f32 as Mirror>::It); - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^---^^-------------------^^ - | | | | - | | | this field is non-zero-sized + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ --- ------------------- this field is non-zero-sized + | | | | | this field is non-zero-sized | needs at most one non-zero-sized field, but has 2 diff --git a/src/test/ui/resolve/issue-23305.stderr b/src/test/ui/resolve/issue-23305.stderr index 0dcf0184db1..f839bd42432 100644 --- a/src/test/ui/resolve/issue-23305.stderr +++ b/src/test/ui/resolve/issue-23305.stderr @@ -1,10 +1,10 @@ -error[E0391]: cycle detected when computing type of `<impl at $DIR/issue-23305.rs:5:1: 5:24>` +error[E0391]: cycle detected when computing type of `<impl at $DIR/issue-23305.rs:5:1: 5:21>` --> $DIR/issue-23305.rs:5:16 | LL | impl dyn ToNbt<Self> {} | ^^^^ | - = note: ...which immediately requires computing type of `<impl at $DIR/issue-23305.rs:5:1: 5:24>` again + = note: ...which immediately requires computing type of `<impl at $DIR/issue-23305.rs:5:1: 5:21>` again note: cycle used when collecting item types in top-level module --> $DIR/issue-23305.rs:1:1 | diff --git a/src/test/ui/resolve/privacy-struct-ctor.stderr b/src/test/ui/resolve/privacy-struct-ctor.stderr index ada053014ef..17a666a401c 100644 --- a/src/test/ui/resolve/privacy-struct-ctor.stderr +++ b/src/test/ui/resolve/privacy-struct-ctor.stderr @@ -114,7 +114,7 @@ note: the tuple struct constructor `S` is defined here --> $DIR/auxiliary/privacy-struct-ctor.rs:2:5 | LL | pub struct S(u8); - | ^^^^^^^^^^^^^^^^^ + | ^^^^^^^^^^^^ error[E0603]: tuple struct constructor `Z` is private --> $DIR/privacy-struct-ctor.rs:45:19 @@ -131,7 +131,7 @@ note: the tuple struct constructor `Z` is defined here --> $DIR/auxiliary/privacy-struct-ctor.rs:5:9 | LL | pub(in m) struct Z(pub(in m::n) u8); - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | ^^^^^^^^^^^^^^^^^^ error: aborting due to 10 previous errors diff --git a/src/test/ui/resolve/resolve-self-in-impl.stderr b/src/test/ui/resolve/resolve-self-in-impl.stderr index 7f623e47353..aa99c1a3335 100644 --- a/src/test/ui/resolve/resolve-self-in-impl.stderr +++ b/src/test/ui/resolve/resolve-self-in-impl.stderr @@ -1,10 +1,10 @@ -error[E0391]: cycle detected when computing type of `<impl at $DIR/resolve-self-in-impl.rs:14:1: 14:20>` +error[E0391]: cycle detected when computing type of `<impl at $DIR/resolve-self-in-impl.rs:14:1: 14:17>` --> $DIR/resolve-self-in-impl.rs:14:13 | LL | impl Tr for Self {} | ^^^^ | - = note: ...which immediately requires computing type of `<impl at $DIR/resolve-self-in-impl.rs:14:1: 14:20>` again + = note: ...which immediately requires computing type of `<impl at $DIR/resolve-self-in-impl.rs:14:1: 14:17>` again note: cycle used when collecting item types in top-level module --> $DIR/resolve-self-in-impl.rs:1:1 | @@ -17,13 +17,13 @@ LL | | LL | | fn main() {} | |____________^ -error[E0391]: cycle detected when computing type of `<impl at $DIR/resolve-self-in-impl.rs:15:1: 15:23>` +error[E0391]: cycle detected when computing type of `<impl at $DIR/resolve-self-in-impl.rs:15:1: 15:20>` --> $DIR/resolve-self-in-impl.rs:15:15 | LL | impl Tr for S<Self> {} | ^^^^ | - = note: ...which immediately requires computing type of `<impl at $DIR/resolve-self-in-impl.rs:15:1: 15:23>` again + = note: ...which immediately requires computing type of `<impl at $DIR/resolve-self-in-impl.rs:15:1: 15:20>` again note: cycle used when collecting item types in top-level module --> $DIR/resolve-self-in-impl.rs:1:1 | @@ -36,13 +36,13 @@ LL | | LL | | fn main() {} | |____________^ -error[E0391]: cycle detected when computing type of `<impl at $DIR/resolve-self-in-impl.rs:16:1: 16:13>` +error[E0391]: cycle detected when computing type of `<impl at $DIR/resolve-self-in-impl.rs:16:1: 16:10>` --> $DIR/resolve-self-in-impl.rs:16:6 | LL | impl Self {} | ^^^^ | - = note: ...which immediately requires computing type of `<impl at $DIR/resolve-self-in-impl.rs:16:1: 16:13>` again + = note: ...which immediately requires computing type of `<impl at $DIR/resolve-self-in-impl.rs:16:1: 16:10>` again note: cycle used when collecting item types in top-level module --> $DIR/resolve-self-in-impl.rs:1:1 | @@ -55,13 +55,13 @@ LL | | LL | | fn main() {} | |____________^ -error[E0391]: cycle detected when computing type of `<impl at $DIR/resolve-self-in-impl.rs:17:1: 17:16>` +error[E0391]: cycle detected when computing type of `<impl at $DIR/resolve-self-in-impl.rs:17:1: 17:13>` --> $DIR/resolve-self-in-impl.rs:17:8 | LL | impl S<Self> {} | ^^^^ | - = note: ...which immediately requires computing type of `<impl at $DIR/resolve-self-in-impl.rs:17:1: 17:16>` again + = note: ...which immediately requires computing type of `<impl at $DIR/resolve-self-in-impl.rs:17:1: 17:13>` again note: cycle used when collecting item types in top-level module --> $DIR/resolve-self-in-impl.rs:1:1 | @@ -74,13 +74,13 @@ LL | | LL | | fn main() {} | |____________^ -error[E0391]: cycle detected when computing trait implemented by `<impl at $DIR/resolve-self-in-impl.rs:18:1: 18:26>` +error[E0391]: cycle detected when computing trait implemented by `<impl at $DIR/resolve-self-in-impl.rs:18:1: 18:23>` --> $DIR/resolve-self-in-impl.rs:18:1 | LL | impl Tr<Self::A> for S {} | ^^^^^^^^^^^^^^^^^^^^^^ | - = note: ...which immediately requires computing trait implemented by `<impl at $DIR/resolve-self-in-impl.rs:18:1: 18:26>` again + = note: ...which immediately requires computing trait implemented by `<impl at $DIR/resolve-self-in-impl.rs:18:1: 18:23>` again note: cycle used when collecting item types in top-level module --> $DIR/resolve-self-in-impl.rs:1:1 | diff --git a/src/test/ui/rfc-2005-default-binding-mode/const.stderr b/src/test/ui/rfc-2005-default-binding-mode/const.stderr index 10d30ec1a1b..0f567125432 100644 --- a/src/test/ui/rfc-2005-default-binding-mode/const.stderr +++ b/src/test/ui/rfc-2005-default-binding-mode/const.stderr @@ -2,7 +2,7 @@ error[E0308]: mismatched types --> $DIR/const.rs:14:9 | LL | const FOO: Foo = Foo{bar: 5}; - | ----------------------------- constant defined here + | -------------- constant defined here ... LL | match &f { | -- this expression has type `&Foo` diff --git a/src/test/ui/rfc-2008-non-exhaustive/enum.stderr b/src/test/ui/rfc-2008-non-exhaustive/enum.stderr index 5ef078c2005..872cb9b8bc6 100644 --- a/src/test/ui/rfc-2008-non-exhaustive/enum.stderr +++ b/src/test/ui/rfc-2008-non-exhaustive/enum.stderr @@ -8,7 +8,7 @@ note: `EmptyNonExhaustiveEnum` defined here --> $DIR/auxiliary/enums.rs:18:1 | LL | pub enum EmptyNonExhaustiveEnum {} - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ = note: the matched value is of type `EmptyNonExhaustiveEnum`, which is marked as non-exhaustive help: ensure that all possible cases are being handled by adding a match arm with a wildcard pattern as shown | @@ -26,12 +26,8 @@ LL | match enum_unit { note: `NonExhaustiveEnum` defined here --> $DIR/auxiliary/enums.rs:4:1 | -LL | / pub enum NonExhaustiveEnum { -LL | | Unit, -LL | | Tuple(u32), -LL | | Struct { field: u32 }, -LL | | } - | |_^ +LL | pub enum NonExhaustiveEnum { + | ^^^^^^^^^^^^^^^^^^^^^^^^^^ = note: the matched value is of type `NonExhaustiveEnum`, which is marked as non-exhaustive help: ensure that all possible cases are being handled by adding a match arm with a wildcard pattern or an explicit pattern as shown | @@ -48,12 +44,8 @@ LL | match enum_unit {}; note: `NonExhaustiveEnum` defined here --> $DIR/auxiliary/enums.rs:4:1 | -LL | / pub enum NonExhaustiveEnum { -LL | | Unit, -LL | | Tuple(u32), -LL | | Struct { field: u32 }, -LL | | } - | |_^ +LL | pub enum NonExhaustiveEnum { + | ^^^^^^^^^^^^^^^^^^^^^^^^^^ = note: the matched value is of type `NonExhaustiveEnum`, which is marked as non-exhaustive help: ensure that all possible cases are being handled by adding a match arm with a wildcard pattern or an explicit pattern as shown | diff --git a/src/test/ui/rfc-2008-non-exhaustive/struct.stderr b/src/test/ui/rfc-2008-non-exhaustive/struct.stderr index 272b2ef6ee1..2b34d071179 100644 --- a/src/test/ui/rfc-2008-non-exhaustive/struct.stderr +++ b/src/test/ui/rfc-2008-non-exhaustive/struct.stderr @@ -25,7 +25,7 @@ note: the tuple struct constructor `TupleStruct` is defined here --> $DIR/auxiliary/structs.rs:12:1 | LL | pub struct TupleStruct(pub u16, pub u16); - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | ^^^^^^^^^^^^^^^^^^^^^^ error[E0603]: unit struct `UnitStruct` is private --> $DIR/struct.rs:32:32 @@ -37,7 +37,7 @@ note: the unit struct `UnitStruct` is defined here --> $DIR/auxiliary/structs.rs:9:1 | LL | pub struct UnitStruct; - | ^^^^^^^^^^^^^^^^^^^^^^ + | ^^^^^^^^^^^^^^^^^^^^^ error[E0639]: cannot create non-exhaustive struct using struct expression --> $DIR/struct.rs:7:14 diff --git a/src/test/ui/rfc-2008-non-exhaustive/uninhabited/indirect_match.stderr b/src/test/ui/rfc-2008-non-exhaustive/uninhabited/indirect_match.stderr index 2dc4eabb863..66e93291c72 100644 --- a/src/test/ui/rfc-2008-non-exhaustive/uninhabited/indirect_match.stderr +++ b/src/test/ui/rfc-2008-non-exhaustive/uninhabited/indirect_match.stderr @@ -8,7 +8,7 @@ note: `IndirectUninhabitedEnum` defined here --> $DIR/auxiliary/uninhabited.rs:26:1 | LL | pub struct IndirectUninhabitedEnum(UninhabitedEnum); - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ = note: the matched value is of type `IndirectUninhabitedEnum` help: ensure that all possible cases are being handled by adding a match arm with a wildcard pattern as shown | @@ -27,7 +27,7 @@ note: `IndirectUninhabitedStruct` defined here --> $DIR/auxiliary/uninhabited.rs:28:1 | LL | pub struct IndirectUninhabitedStruct(UninhabitedStruct); - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ = note: the matched value is of type `IndirectUninhabitedStruct` help: ensure that all possible cases are being handled by adding a match arm with a wildcard pattern as shown | @@ -46,7 +46,7 @@ note: `IndirectUninhabitedTupleStruct` defined here --> $DIR/auxiliary/uninhabited.rs:30:1 | LL | pub struct IndirectUninhabitedTupleStruct(UninhabitedTupleStruct); - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ = note: the matched value is of type `IndirectUninhabitedTupleStruct` help: ensure that all possible cases are being handled by adding a match arm with a wildcard pattern as shown | @@ -65,7 +65,7 @@ note: `IndirectUninhabitedVariants` defined here --> $DIR/auxiliary/uninhabited.rs:32:1 | LL | pub struct IndirectUninhabitedVariants(UninhabitedVariants); - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ = note: the matched value is of type `IndirectUninhabitedVariants` help: ensure that all possible cases are being handled by adding a match arm with a wildcard pattern as shown | diff --git a/src/test/ui/rfc-2008-non-exhaustive/uninhabited/indirect_match_with_exhaustive_patterns.stderr b/src/test/ui/rfc-2008-non-exhaustive/uninhabited/indirect_match_with_exhaustive_patterns.stderr index f0cb13de3f7..ef97c1fa17f 100644 --- a/src/test/ui/rfc-2008-non-exhaustive/uninhabited/indirect_match_with_exhaustive_patterns.stderr +++ b/src/test/ui/rfc-2008-non-exhaustive/uninhabited/indirect_match_with_exhaustive_patterns.stderr @@ -8,7 +8,7 @@ note: `IndirectUninhabitedEnum` defined here --> $DIR/auxiliary/uninhabited.rs:26:1 | LL | pub struct IndirectUninhabitedEnum(UninhabitedEnum); - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ = note: the matched value is of type `IndirectUninhabitedEnum` help: ensure that all possible cases are being handled by adding a match arm with a wildcard pattern as shown | @@ -27,7 +27,7 @@ note: `IndirectUninhabitedStruct` defined here --> $DIR/auxiliary/uninhabited.rs:28:1 | LL | pub struct IndirectUninhabitedStruct(UninhabitedStruct); - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ = note: the matched value is of type `IndirectUninhabitedStruct` help: ensure that all possible cases are being handled by adding a match arm with a wildcard pattern as shown | @@ -46,7 +46,7 @@ note: `IndirectUninhabitedTupleStruct` defined here --> $DIR/auxiliary/uninhabited.rs:30:1 | LL | pub struct IndirectUninhabitedTupleStruct(UninhabitedTupleStruct); - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ = note: the matched value is of type `IndirectUninhabitedTupleStruct` help: ensure that all possible cases are being handled by adding a match arm with a wildcard pattern as shown | @@ -65,7 +65,7 @@ note: `IndirectUninhabitedVariants` defined here --> $DIR/auxiliary/uninhabited.rs:32:1 | LL | pub struct IndirectUninhabitedVariants(UninhabitedVariants); - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ = note: the matched value is of type `IndirectUninhabitedVariants` help: ensure that all possible cases are being handled by adding a match arm with a wildcard pattern as shown | diff --git a/src/test/ui/rfc-2008-non-exhaustive/uninhabited/match.stderr b/src/test/ui/rfc-2008-non-exhaustive/uninhabited/match.stderr index 49febd9241d..32a5c07f196 100644 --- a/src/test/ui/rfc-2008-non-exhaustive/uninhabited/match.stderr +++ b/src/test/ui/rfc-2008-non-exhaustive/uninhabited/match.stderr @@ -7,9 +7,8 @@ LL | match x {} note: `UninhabitedEnum` defined here --> $DIR/auxiliary/uninhabited.rs:5:1 | -LL | / pub enum UninhabitedEnum { -LL | | } - | |_^ +LL | pub enum UninhabitedEnum { + | ^^^^^^^^^^^^^^^^^^^^^^^^ = note: the matched value is of type `UninhabitedEnum`, which is marked as non-exhaustive help: ensure that all possible cases are being handled by adding a match arm with a wildcard pattern as shown | @@ -27,10 +26,8 @@ LL | match x {} note: `UninhabitedStruct` defined here --> $DIR/auxiliary/uninhabited.rs:9:1 | -LL | / pub struct UninhabitedStruct { -LL | | _priv: !, -LL | | } - | |_^ +LL | pub struct UninhabitedStruct { + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ = note: the matched value is of type `UninhabitedStruct` help: ensure that all possible cases are being handled by adding a match arm with a wildcard pattern as shown | @@ -49,7 +46,7 @@ note: `UninhabitedTupleStruct` defined here --> $DIR/auxiliary/uninhabited.rs:14:1 | LL | pub struct UninhabitedTupleStruct(!); - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ = note: the matched value is of type `UninhabitedTupleStruct` help: ensure that all possible cases are being handled by adding a match arm with a wildcard pattern as shown | @@ -67,13 +64,12 @@ LL | match x {} note: `UninhabitedVariants` defined here --> $DIR/auxiliary/uninhabited.rs:17:23 | -LL | / pub enum UninhabitedVariants { -LL | | #[non_exhaustive] Tuple(!), - | | ^^^^^ not covered -LL | | #[non_exhaustive] Struct { x: ! } - | | ^^^^^^ not covered -LL | | } - | |_- +LL | pub enum UninhabitedVariants { + | ---------------------------- +LL | #[non_exhaustive] Tuple(!), + | ^^^^^ not covered +LL | #[non_exhaustive] Struct { x: ! } + | ^^^^^^ not covered = note: the matched value is of type `UninhabitedVariants` help: ensure that all possible cases are being handled by adding a match arm with a wildcard pattern, a match arm with multiple or-patterns as shown, or multiple match arms | diff --git a/src/test/ui/rfc-2008-non-exhaustive/uninhabited/match_with_exhaustive_patterns.stderr b/src/test/ui/rfc-2008-non-exhaustive/uninhabited/match_with_exhaustive_patterns.stderr index e18c2678d32..d854ea28ff6 100644 --- a/src/test/ui/rfc-2008-non-exhaustive/uninhabited/match_with_exhaustive_patterns.stderr +++ b/src/test/ui/rfc-2008-non-exhaustive/uninhabited/match_with_exhaustive_patterns.stderr @@ -7,9 +7,8 @@ LL | match x {} note: `UninhabitedEnum` defined here --> $DIR/auxiliary/uninhabited.rs:5:1 | -LL | / pub enum UninhabitedEnum { -LL | | } - | |_^ +LL | pub enum UninhabitedEnum { + | ^^^^^^^^^^^^^^^^^^^^^^^^ = note: the matched value is of type `UninhabitedEnum`, which is marked as non-exhaustive help: ensure that all possible cases are being handled by adding a match arm with a wildcard pattern as shown | @@ -27,10 +26,8 @@ LL | match x {} note: `UninhabitedStruct` defined here --> $DIR/auxiliary/uninhabited.rs:9:1 | -LL | / pub struct UninhabitedStruct { -LL | | _priv: !, -LL | | } - | |_^ +LL | pub struct UninhabitedStruct { + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ = note: the matched value is of type `UninhabitedStruct` help: ensure that all possible cases are being handled by adding a match arm with a wildcard pattern as shown | @@ -49,7 +46,7 @@ note: `UninhabitedTupleStruct` defined here --> $DIR/auxiliary/uninhabited.rs:14:1 | LL | pub struct UninhabitedTupleStruct(!); - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ = note: the matched value is of type `UninhabitedTupleStruct` help: ensure that all possible cases are being handled by adding a match arm with a wildcard pattern as shown | @@ -67,13 +64,12 @@ LL | match x {} note: `UninhabitedVariants` defined here --> $DIR/auxiliary/uninhabited.rs:17:23 | -LL | / pub enum UninhabitedVariants { -LL | | #[non_exhaustive] Tuple(!), - | | ^^^^^ not covered -LL | | #[non_exhaustive] Struct { x: ! } - | | ^^^^^^ not covered -LL | | } - | |_- +LL | pub enum UninhabitedVariants { + | ---------------------------- +LL | #[non_exhaustive] Tuple(!), + | ^^^^^ not covered +LL | #[non_exhaustive] Struct { x: ! } + | ^^^^^^ not covered = note: the matched value is of type `UninhabitedVariants` help: ensure that all possible cases are being handled by adding a match arm with a wildcard pattern, a match arm with multiple or-patterns as shown, or multiple match arms | diff --git a/src/test/ui/rfc-2093-infer-outlives/cross-crate.stderr b/src/test/ui/rfc-2093-infer-outlives/cross-crate.stderr index 1da8e648251..76300cce55c 100644 --- a/src/test/ui/rfc-2093-infer-outlives/cross-crate.stderr +++ b/src/test/ui/rfc-2093-infer-outlives/cross-crate.stderr @@ -1,10 +1,8 @@ error: rustc_outlives --> $DIR/cross-crate.rs:4:1 | -LL | / struct Foo<'a, T> { -LL | | bar: std::slice::IterMut<'a, T> -LL | | } - | |_^ +LL | struct Foo<'a, T> { + | ^^^^^^^^^^^^^^^^^ | = note: T: 'a diff --git a/src/test/ui/rfc-2093-infer-outlives/enum.stderr b/src/test/ui/rfc-2093-infer-outlives/enum.stderr index 868ca2c4587..b6ce2450e22 100644 --- a/src/test/ui/rfc-2093-infer-outlives/enum.stderr +++ b/src/test/ui/rfc-2093-infer-outlives/enum.stderr @@ -1,30 +1,24 @@ error: rustc_outlives --> $DIR/enum.rs:7:1 | -LL | / enum Foo<'a, T> { -LL | | One(Bar<'a, T>) -LL | | } - | |_^ +LL | enum Foo<'a, T> { + | ^^^^^^^^^^^^^^^ | = note: T: 'a error: rustc_outlives --> $DIR/enum.rs:13:1 | -LL | / struct Bar<'b, U> { -LL | | field2: &'b U -LL | | } - | |_^ +LL | struct Bar<'b, U> { + | ^^^^^^^^^^^^^^^^^ | = note: U: 'b error: rustc_outlives --> $DIR/enum.rs:19:1 | -LL | / enum Ying<'c, K> { -LL | | One(&'c Yang<K>) -LL | | } - | |_^ +LL | enum Ying<'c, K> { + | ^^^^^^^^^^^^^^^^ | = note: K: 'c diff --git a/src/test/ui/rfc-2093-infer-outlives/explicit-dyn.stderr b/src/test/ui/rfc-2093-infer-outlives/explicit-dyn.stderr index 4608962c7c3..595a5c28088 100644 --- a/src/test/ui/rfc-2093-infer-outlives/explicit-dyn.stderr +++ b/src/test/ui/rfc-2093-infer-outlives/explicit-dyn.stderr @@ -1,11 +1,8 @@ error: rustc_outlives --> $DIR/explicit-dyn.rs:7:1 | -LL | / struct Foo<'a, A> -LL | | { -LL | | foo: Box<dyn Trait<'a, A>> -LL | | } - | |_^ +LL | struct Foo<'a, A> + | ^^^^^^^^^^^^^^^^^ | = note: A: 'a diff --git a/src/test/ui/rfc-2093-infer-outlives/explicit-enum.stderr b/src/test/ui/rfc-2093-infer-outlives/explicit-enum.stderr index 062f5d5e9a7..3059f95aefb 100644 --- a/src/test/ui/rfc-2093-infer-outlives/explicit-enum.stderr +++ b/src/test/ui/rfc-2093-infer-outlives/explicit-enum.stderr @@ -1,10 +1,8 @@ error: rustc_outlives --> $DIR/explicit-enum.rs:4:1 | -LL | / enum Foo<'a, U> { -LL | | One(Bar<'a, U>) -LL | | } - | |_^ +LL | enum Foo<'a, U> { + | ^^^^^^^^^^^^^^^ | = note: U: 'a diff --git a/src/test/ui/rfc-2093-infer-outlives/explicit-projection.stderr b/src/test/ui/rfc-2093-infer-outlives/explicit-projection.stderr index a85aa3d7565..589e9589913 100644 --- a/src/test/ui/rfc-2093-infer-outlives/explicit-projection.stderr +++ b/src/test/ui/rfc-2093-infer-outlives/explicit-projection.stderr @@ -1,11 +1,8 @@ error: rustc_outlives --> $DIR/explicit-projection.rs:8:1 | -LL | / struct Foo<'a, A, B> where A: Trait<'a, B> -LL | | { -LL | | foo: <A as Trait<'a, B>>::Type -LL | | } - | |_^ +LL | struct Foo<'a, A, B> where A: Trait<'a, B> + | ^^^^^^^^^^^^^^^^^^^^ | = note: B: 'a diff --git a/src/test/ui/rfc-2093-infer-outlives/explicit-struct.stderr b/src/test/ui/rfc-2093-infer-outlives/explicit-struct.stderr index 309c54bb449..9912e36b29c 100644 --- a/src/test/ui/rfc-2093-infer-outlives/explicit-struct.stderr +++ b/src/test/ui/rfc-2093-infer-outlives/explicit-struct.stderr @@ -1,10 +1,8 @@ error: rustc_outlives --> $DIR/explicit-struct.rs:4:1 | -LL | / struct Foo<'b, U> { -LL | | bar: Bar<'b, U> -LL | | } - | |_^ +LL | struct Foo<'b, U> { + | ^^^^^^^^^^^^^^^^^ | = note: U: 'b diff --git a/src/test/ui/rfc-2093-infer-outlives/explicit-union.stderr b/src/test/ui/rfc-2093-infer-outlives/explicit-union.stderr index 47c283faf50..2c6d06aa8c7 100644 --- a/src/test/ui/rfc-2093-infer-outlives/explicit-union.stderr +++ b/src/test/ui/rfc-2093-infer-outlives/explicit-union.stderr @@ -1,10 +1,8 @@ error: rustc_outlives --> $DIR/explicit-union.rs:5:1 | -LL | / union Foo<'b, U: Copy> { -LL | | bar: Bar<'b, U> -LL | | } - | |_^ +LL | union Foo<'b, U: Copy> { + | ^^^^^^^^^^^^^^^^^^^^^^ | = note: U: 'b diff --git a/src/test/ui/rfc-2093-infer-outlives/nested-enum.stderr b/src/test/ui/rfc-2093-infer-outlives/nested-enum.stderr index 10387f51b1e..4350e6e8bee 100644 --- a/src/test/ui/rfc-2093-infer-outlives/nested-enum.stderr +++ b/src/test/ui/rfc-2093-infer-outlives/nested-enum.stderr @@ -1,11 +1,8 @@ error: rustc_outlives --> $DIR/nested-enum.rs:4:1 | -LL | / enum Foo<'a, T> { -LL | | -LL | | One(Bar<'a, T>) -LL | | } - | |_^ +LL | enum Foo<'a, T> { + | ^^^^^^^^^^^^^^^ | = note: T: 'a diff --git a/src/test/ui/rfc-2093-infer-outlives/nested-regions.stderr b/src/test/ui/rfc-2093-infer-outlives/nested-regions.stderr index ffdd5542bb4..c08add7eded 100644 --- a/src/test/ui/rfc-2093-infer-outlives/nested-regions.stderr +++ b/src/test/ui/rfc-2093-infer-outlives/nested-regions.stderr @@ -1,10 +1,8 @@ error: rustc_outlives --> $DIR/nested-regions.rs:4:1 | -LL | / struct Foo<'a, 'b, T> { -LL | | x: &'a &'b T -LL | | } - | |_^ +LL | struct Foo<'a, 'b, T> { + | ^^^^^^^^^^^^^^^^^^^^^ | = note: 'b: 'a = note: T: 'a diff --git a/src/test/ui/rfc-2093-infer-outlives/nested-structs.stderr b/src/test/ui/rfc-2093-infer-outlives/nested-structs.stderr index 86bcbe640e4..76955523443 100644 --- a/src/test/ui/rfc-2093-infer-outlives/nested-structs.stderr +++ b/src/test/ui/rfc-2093-infer-outlives/nested-structs.stderr @@ -1,10 +1,8 @@ error: rustc_outlives --> $DIR/nested-structs.rs:4:1 | -LL | / struct Foo<'a, T> { -LL | | field1: Bar<'a, T> -LL | | } - | |_^ +LL | struct Foo<'a, T> { + | ^^^^^^^^^^^^^^^^^ | = note: T: 'a diff --git a/src/test/ui/rfc-2093-infer-outlives/nested-union.stderr b/src/test/ui/rfc-2093-infer-outlives/nested-union.stderr index e0f248fa38a..0116a2a68ce 100644 --- a/src/test/ui/rfc-2093-infer-outlives/nested-union.stderr +++ b/src/test/ui/rfc-2093-infer-outlives/nested-union.stderr @@ -1,10 +1,8 @@ error: rustc_outlives --> $DIR/nested-union.rs:5:1 | -LL | / union Foo<'a, T: Copy> { -LL | | field1: Bar<'a, T> -LL | | } - | |_^ +LL | union Foo<'a, T: Copy> { + | ^^^^^^^^^^^^^^^^^^^^^^ | = note: T: 'a diff --git a/src/test/ui/rfc-2093-infer-outlives/projection.stderr b/src/test/ui/rfc-2093-infer-outlives/projection.stderr index 840676e7966..d9342013f55 100644 --- a/src/test/ui/rfc-2093-infer-outlives/projection.stderr +++ b/src/test/ui/rfc-2093-infer-outlives/projection.stderr @@ -1,10 +1,8 @@ error: rustc_outlives --> $DIR/projection.rs:4:1 | -LL | / struct Foo<'a, T: Iterator> { -LL | | bar: &'a T::Item -LL | | } - | |_^ +LL | struct Foo<'a, T: Iterator> { + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^ | = note: <T as Iterator>::Item: 'a diff --git a/src/test/ui/rfc-2093-infer-outlives/reference.stderr b/src/test/ui/rfc-2093-infer-outlives/reference.stderr index d69aaf6f849..50811435781 100644 --- a/src/test/ui/rfc-2093-infer-outlives/reference.stderr +++ b/src/test/ui/rfc-2093-infer-outlives/reference.stderr @@ -1,10 +1,8 @@ error: rustc_outlives --> $DIR/reference.rs:4:1 | -LL | / struct Foo<'a, T> { -LL | | bar: &'a T, -LL | | } - | |_^ +LL | struct Foo<'a, T> { + | ^^^^^^^^^^^^^^^^^ | = note: T: 'a diff --git a/src/test/ui/rfc-2093-infer-outlives/self-dyn.stderr b/src/test/ui/rfc-2093-infer-outlives/self-dyn.stderr index 7836b3f5aab..9c836b190cf 100644 --- a/src/test/ui/rfc-2093-infer-outlives/self-dyn.stderr +++ b/src/test/ui/rfc-2093-infer-outlives/self-dyn.stderr @@ -1,11 +1,8 @@ error: rustc_outlives --> $DIR/self-dyn.rs:8:1 | -LL | / struct Foo<'a, 'b, A> -LL | | { -LL | | foo: Box<dyn Trait<'a, 'b, A>> -LL | | } - | |_^ +LL | struct Foo<'a, 'b, A> + | ^^^^^^^^^^^^^^^^^^^^^ | = note: A: 'a diff --git a/src/test/ui/rfc-2093-infer-outlives/self-structs.stderr b/src/test/ui/rfc-2093-infer-outlives/self-structs.stderr index b972ad84466..2b4625f77a5 100644 --- a/src/test/ui/rfc-2093-infer-outlives/self-structs.stderr +++ b/src/test/ui/rfc-2093-infer-outlives/self-structs.stderr @@ -1,10 +1,8 @@ error: rustc_outlives --> $DIR/self-structs.rs:4:1 | -LL | / struct Foo<'a, 'b, T> { -LL | | field1: dyn Bar<'a, 'b, T> -LL | | } - | |_^ +LL | struct Foo<'a, 'b, T> { + | ^^^^^^^^^^^^^^^^^^^^^ | = note: T: 'a diff --git a/src/test/ui/simd/type-len.stderr b/src/test/ui/simd/type-len.stderr index f122d8bb0dc..2a6bd1b0fd5 100644 --- a/src/test/ui/simd/type-len.stderr +++ b/src/test/ui/simd/type-len.stderr @@ -2,37 +2,37 @@ error[E0075]: SIMD vector cannot be empty --> $DIR/type-len.rs:6:1 | LL | struct empty; - | ^^^^^^^^^^^^^ + | ^^^^^^^^^^^^ error[E0075]: SIMD vector cannot be empty --> $DIR/type-len.rs:9:1 | LL | struct empty2([f32; 0]); - | ^^^^^^^^^^^^^^^^^^^^^^^^ + | ^^^^^^^^^^^^^ error[E0076]: SIMD vector should be homogeneous --> $DIR/type-len.rs:15:1 | LL | struct i64f64(i64, f64); - | ^^^^^^^^^^^^^^^^^^^^^^^^ SIMD elements must have the same type + | ^^^^^^^^^^^^^ SIMD elements must have the same type error[E0077]: SIMD vector element type should be a primitive scalar (integer/float/pointer) type --> $DIR/type-len.rs:20:1 | LL | struct FooV(Foo, Foo); - | ^^^^^^^^^^^^^^^^^^^^^^ + | ^^^^^^^^^^^ error[E0077]: SIMD vector element type should be a primitive scalar (integer/float/pointer) type --> $DIR/type-len.rs:23:1 | LL | struct FooV2([Foo; 2]); - | ^^^^^^^^^^^^^^^^^^^^^^^ + | ^^^^^^^^^^^^ error[E0075]: SIMD vector cannot have more than 32768 elements --> $DIR/type-len.rs:26:1 | LL | struct TooBig([f32; 65536]); - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | ^^^^^^^^^^^^^ error: aborting due to 6 previous errors diff --git a/src/test/ui/span/drop-location-span-error-rust-2021-incompatible-closure-captures-93117.rs b/src/test/ui/span/drop-location-span-error-rust-2021-incompatible-closure-captures-93117.rs new file mode 100644 index 00000000000..b280c8ab6e2 --- /dev/null +++ b/src/test/ui/span/drop-location-span-error-rust-2021-incompatible-closure-captures-93117.rs @@ -0,0 +1,18 @@ +// compile-flags: -Wrust-2021-incompatible-closure-captures + +pub struct A {} + +impl A { + async fn create(path: impl AsRef<std::path::Path>) { //~ ERROR `async fn` is not permitted in Rust 2015 + //~^ WARN changes to closure capture in Rust 2021 will affect drop order [rust_2021_incompatible_closure_captures] + ; + crate(move || {} ).await //~ ERROR expected function, found module `crate` + } +} + +trait C{async fn new(val: T) {} //~ ERROR `async fn` is not permitted in Rust 2015 +//~^ ERROR functions in traits cannot be declared `async` +//~^^ ERROR cannot find type `T` in this scope +//~^^^ WARN changes to closure capture in Rust 2021 will affect drop order [rust_2021_incompatible_closure_captures] + +//~ ERROR this file contains an unclosed delimiter diff --git a/src/test/ui/span/drop-location-span-error-rust-2021-incompatible-closure-captures-93117.stderr b/src/test/ui/span/drop-location-span-error-rust-2021-incompatible-closure-captures-93117.stderr new file mode 100644 index 00000000000..50de2322907 --- /dev/null +++ b/src/test/ui/span/drop-location-span-error-rust-2021-incompatible-closure-captures-93117.stderr @@ -0,0 +1,93 @@ +error: this file contains an unclosed delimiter + --> $DIR/drop-location-span-error-rust-2021-incompatible-closure-captures-93117.rs:18:53 + | +LL | trait C{async fn new(val: T) {} + | - unclosed delimiter +... +LL | + | ^ + +error[E0670]: `async fn` is not permitted in Rust 2015 + --> $DIR/drop-location-span-error-rust-2021-incompatible-closure-captures-93117.rs:6:5 + | +LL | async fn create(path: impl AsRef<std::path::Path>) { + | ^^^^^ to use `async fn`, switch to Rust 2018 or later + | + = help: pass `--edition 2021` to `rustc` + = note: for more on editions, read https://doc.rust-lang.org/edition-guide + +error[E0670]: `async fn` is not permitted in Rust 2015 + --> $DIR/drop-location-span-error-rust-2021-incompatible-closure-captures-93117.rs:13:9 + | +LL | trait C{async fn new(val: T) {} + | ^^^^^ to use `async fn`, switch to Rust 2018 or later + | + = help: pass `--edition 2021` to `rustc` + = note: for more on editions, read https://doc.rust-lang.org/edition-guide + +error[E0706]: functions in traits cannot be declared `async` + --> $DIR/drop-location-span-error-rust-2021-incompatible-closure-captures-93117.rs:13:9 + | +LL | trait C{async fn new(val: T) {} + | -----^^^^^^^^^^^^^^^^^^ + | | + | `async` because of this + | + = note: `async` trait functions are not currently supported + = note: consider using the `async-trait` crate: https://crates.io/crates/async-trait + +error[E0423]: expected function, found module `crate` + --> $DIR/drop-location-span-error-rust-2021-incompatible-closure-captures-93117.rs:9:5 + | +LL | crate(move || {} ).await + | ^^^^^ not a function + +error[E0412]: cannot find type `T` in this scope + --> $DIR/drop-location-span-error-rust-2021-incompatible-closure-captures-93117.rs:13:27 + | +LL | pub struct A {} + | ------------ similarly named struct `A` defined here +... +LL | trait C{async fn new(val: T) {} + | ^ help: a struct with a similar name exists: `A` + +warning: changes to closure capture in Rust 2021 will affect drop order + --> $DIR/drop-location-span-error-rust-2021-incompatible-closure-captures-93117.rs:6:57 + | +LL | async fn create(path: impl AsRef<std::path::Path>) { + | _____________________----_____________________________-__^ + | | | | + | | | in Rust 2018, `path` is dropped here along with the closure, but in Rust 2021 `path` is not part of the closure + | | in Rust 2018, this causes the closure to capture `path`, but in Rust 2021, it has no effect +LL | | +LL | | ; +LL | | crate(move || {} ).await +LL | | } + | |_____^ + | + = note: requested on the command line with `-W rust-2021-incompatible-closure-captures` + = note: for more information, see <https://doc.rust-lang.org/nightly/edition-guide/rust-2021/disjoint-capture-in-closures.html> +help: add a dummy let to cause `path` to be fully captured + | +LL | async fn create(path: impl AsRef<std::path::Path>) { let _ = &path; + | ++++++++++++++ + +warning: changes to closure capture in Rust 2021 will affect drop order + --> $DIR/drop-location-span-error-rust-2021-incompatible-closure-captures-93117.rs:13:30 + | +LL | trait C{async fn new(val: T) {} + | --- - ^^ + | | | + | | in Rust 2018, `val` is dropped here along with the closure, but in Rust 2021 `val` is not part of the closure + | in Rust 2018, this causes the closure to capture `val`, but in Rust 2021, it has no effect + | + = note: for more information, see <https://doc.rust-lang.org/nightly/edition-guide/rust-2021/disjoint-capture-in-closures.html> +help: add a dummy let to cause `val` to be fully captured + | +LL | trait C{async fn new(val: T) { let _ = &val;} + | +++++++++++++ + +error: aborting due to 6 previous errors; 2 warnings emitted + +Some errors have detailed explanations: E0412, E0423, E0670, E0706. +For more information about an error, try `rustc --explain E0412`. diff --git a/src/test/ui/span/drop-location-span-error-rust-2021-incompatible-closure-captures-96258.rs b/src/test/ui/span/drop-location-span-error-rust-2021-incompatible-closure-captures-96258.rs new file mode 100644 index 00000000000..a776e508907 --- /dev/null +++ b/src/test/ui/span/drop-location-span-error-rust-2021-incompatible-closure-captures-96258.rs @@ -0,0 +1,15 @@ +// compile-flags -Wrust-2021-incompatible-closure-captures + +fn main() {} + +pub(crate) struct Numberer {} + +impl Numberer { + pub(crate) async fn new( + //~^ ERROR `async fn` is not permitted in Rust 2015 + interval: Duration, + //~^ ERROR cannot find type `Duration` in this scope + ) -> Numberer { + Numberer {} + } +} diff --git a/src/test/ui/span/drop-location-span-error-rust-2021-incompatible-closure-captures-96258.stderr b/src/test/ui/span/drop-location-span-error-rust-2021-incompatible-closure-captures-96258.stderr new file mode 100644 index 00000000000..37b2f413860 --- /dev/null +++ b/src/test/ui/span/drop-location-span-error-rust-2021-incompatible-closure-captures-96258.stderr @@ -0,0 +1,24 @@ +error[E0670]: `async fn` is not permitted in Rust 2015 + --> $DIR/drop-location-span-error-rust-2021-incompatible-closure-captures-96258.rs:8:16 + | +LL | pub(crate) async fn new( + | ^^^^^ to use `async fn`, switch to Rust 2018 or later + | + = help: pass `--edition 2021` to `rustc` + = note: for more on editions, read https://doc.rust-lang.org/edition-guide + +error[E0412]: cannot find type `Duration` in this scope + --> $DIR/drop-location-span-error-rust-2021-incompatible-closure-captures-96258.rs:10:19 + | +LL | interval: Duration, + | ^^^^^^^^ not found in this scope + | +help: consider importing this struct + | +LL | use std::time::Duration; + | + +error: aborting due to 2 previous errors + +Some errors have detailed explanations: E0412, E0670. +For more information about an error, try `rustc --explain E0412`. diff --git a/src/test/ui/span/impl-wrong-item-for-trait.stderr b/src/test/ui/span/impl-wrong-item-for-trait.stderr index 82ef13f3362..f919092f9ee 100644 --- a/src/test/ui/span/impl-wrong-item-for-trait.stderr +++ b/src/test/ui/span/impl-wrong-item-for-trait.stderr @@ -38,7 +38,7 @@ error[E0046]: not all trait items implemented, missing: `MY_CONST` --> $DIR/impl-wrong-item-for-trait.rs:19:1 | LL | const MY_CONST: u32; - | -------------------- `MY_CONST` from trait + | ------------------- `MY_CONST` from trait ... LL | impl Foo for FooMethodForConst { | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ missing `MY_CONST` in implementation diff --git a/src/test/ui/span/issue-39018.stderr b/src/test/ui/span/issue-39018.stderr index e0cfe04cf41..eea94643e0a 100644 --- a/src/test/ui/span/issue-39018.stderr +++ b/src/test/ui/span/issue-39018.stderr @@ -29,14 +29,8 @@ LL | enum World { note: the following trait must be implemented --> $SRC_DIR/core/src/ops/arith.rs:LL:COL | -LL | / pub trait Add<Rhs = Self> { -LL | | /// The resulting type after applying the `+` operator. -LL | | #[stable(feature = "rust1", since = "1.0.0")] -LL | | type Output; -... | -LL | | fn add(self, rhs: Rhs) -> Self::Output; -LL | | } - | |_^ +LL | pub trait Add<Rhs = Self> { + | ^^^^^^^^^^^^^^^^^^^^^^^^^ error[E0369]: cannot add `String` to `&str` --> $DIR/issue-39018.rs:11:22 diff --git a/src/test/ui/span/issue-42234-unknown-receiver-type.full.stderr b/src/test/ui/span/issue-42234-unknown-receiver-type.full.stderr index cd3ffdc6f9d..2b178990850 100644 --- a/src/test/ui/span/issue-42234-unknown-receiver-type.full.stderr +++ b/src/test/ui/span/issue-42234-unknown-receiver-type.full.stderr @@ -3,8 +3,9 @@ error[E0282]: type annotations needed | LL | let x: Option<_> = None; | ^^^^ cannot infer type of the type parameter `T` declared on the enum `Option` +LL | x.unwrap().method_that_could_exist_on_some_type(); + | ---------- type must be known at this point | - = note: type must be known at this point help: consider specifying the generic argument | LL | let x: Option<_> = None::<T>; @@ -16,7 +17,6 @@ error[E0282]: type annotations needed LL | .sum::<_>() | ^^^ cannot infer type of the type parameter `S` declared on the associated function `sum` | - = note: type must be known at this point help: consider specifying the generic argument | LL | .sum::<_>() diff --git a/src/test/ui/span/issue-42234-unknown-receiver-type.generic_arg.stderr b/src/test/ui/span/issue-42234-unknown-receiver-type.generic_arg.stderr index b6a3f07f571..d93d54e878b 100644 --- a/src/test/ui/span/issue-42234-unknown-receiver-type.generic_arg.stderr +++ b/src/test/ui/span/issue-42234-unknown-receiver-type.generic_arg.stderr @@ -3,8 +3,9 @@ error[E0282]: type annotations needed | LL | let x: Option<_> = None; | ^^^^ cannot infer type of the type parameter `T` declared on the enum `Option` +LL | x.unwrap().method_that_could_exist_on_some_type(); + | ---------- type must be known at this point | - = note: type must be known at this point help: consider specifying the generic argument | LL | let x: Option<_> = None::<T>; @@ -16,7 +17,6 @@ error[E0282]: type annotations needed LL | .sum::<_>() | ^^^ cannot infer type of the type parameter `S` declared on the associated function `sum` | - = note: type must be known at this point help: consider specifying the generic argument | LL | .sum::<S>() diff --git a/src/test/ui/span/macro-span-replacement.stderr b/src/test/ui/span/macro-span-replacement.stderr index 433d02dcbe7..5dd56342889 100644 --- a/src/test/ui/span/macro-span-replacement.stderr +++ b/src/test/ui/span/macro-span-replacement.stderr @@ -1,8 +1,8 @@ warning: struct `S` is never constructed - --> $DIR/macro-span-replacement.rs:7:14 + --> $DIR/macro-span-replacement.rs:7:12 | LL | $b $a; - | ^ + | ^^ ... LL | m!(S struct); | ------------ in this macro invocation diff --git a/src/test/ui/span/method-and-field-eager-resolution.stderr b/src/test/ui/span/method-and-field-eager-resolution.stderr index 2dd650f38ce..7d240589a3f 100644 --- a/src/test/ui/span/method-and-field-eager-resolution.stderr +++ b/src/test/ui/span/method-and-field-eager-resolution.stderr @@ -3,8 +3,10 @@ error[E0282]: type annotations needed | LL | let mut x = Default::default(); | ^^^^^ +LL | +LL | x.0; + | - type must be known at this point | - = note: type must be known at this point help: consider giving `x` an explicit type | LL | let mut x: _ = Default::default(); @@ -15,8 +17,10 @@ error[E0282]: type annotations needed | LL | let mut x = Default::default(); | ^^^^^ +LL | +LL | x[0]; + | - type must be known at this point | - = note: type must be known at this point help: consider giving `x` an explicit type | LL | let mut x: _ = Default::default(); diff --git a/src/test/ui/span/multiline-span-E0072.stderr b/src/test/ui/span/multiline-span-E0072.stderr index acfc60b51f3..79b13f45fd8 100644 --- a/src/test/ui/span/multiline-span-E0072.stderr +++ b/src/test/ui/span/multiline-span-E0072.stderr @@ -3,12 +3,10 @@ error[E0072]: recursive type `ListNode` has infinite size | LL | / struct LL | | ListNode -LL | | { -LL | | head: u8, -LL | | tail: Option<ListNode>, - | | ---------------- recursive without indirection -LL | | } - | |_^ recursive type has infinite size + | |________^ recursive type has infinite size +... +LL | tail: Option<ListNode>, + | ---------------- recursive without indirection | help: insert some indirection (e.g., a `Box`, `Rc`, or `&`) to make `ListNode` representable | diff --git a/src/test/ui/span/transitive-dep-span.stderr b/src/test/ui/span/transitive-dep-span.stderr index 2b3dfc5c135..4dc3e572116 100644 --- a/src/test/ui/span/transitive-dep-span.stderr +++ b/src/test/ui/span/transitive-dep-span.stderr @@ -1,19 +1,18 @@ error: expected one of `!` or `::`, found `error` --> $DIR/auxiliary/transitive_dep_three.rs:6:27 | -LL | / macro_rules! parse_error { -LL | | () => { parse error } - | | ^^^^^ expected one of `!` or `::` -LL | | } - | |_________- in this expansion of `transitive_dep_two::parse_error!` +LL | macro_rules! parse_error { + | ------------------------ in this expansion of `transitive_dep_two::parse_error!` +LL | () => { parse error } + | ^^^^^ expected one of `!` or `::` | ::: $DIR/transitive-dep-span.rs:13:1 | -LL | transitive_dep_two::parse_error!(); - | ---------------------------------- - | | - | in this macro invocation - | in this macro invocation +LL | transitive_dep_two::parse_error!(); + | ---------------------------------- + | | + | in this macro invocation + | in this macro invocation error: aborting due to previous error diff --git a/src/test/ui/span/type-annotations-needed-expr.stderr b/src/test/ui/span/type-annotations-needed-expr.stderr index e4a8f746462..9dff6c64db4 100644 --- a/src/test/ui/span/type-annotations-needed-expr.stderr +++ b/src/test/ui/span/type-annotations-needed-expr.stderr @@ -4,7 +4,6 @@ error[E0282]: type annotations needed LL | let _ = (vec![1,2,3]).into_iter().sum() as f64; | ^^^ cannot infer type of the type parameter `S` declared on the associated function `sum` | - = note: type must be known at this point help: consider specifying the generic argument | LL | let _ = (vec![1,2,3]).into_iter().sum::<S>() as f64; diff --git a/src/test/ui/specialization/defaultimpl/specialization-no-default.stderr b/src/test/ui/specialization/defaultimpl/specialization-no-default.stderr index 3f1a5495e21..360b7bc787a 100644 --- a/src/test/ui/specialization/defaultimpl/specialization-no-default.stderr +++ b/src/test/ui/specialization/defaultimpl/specialization-no-default.stderr @@ -11,67 +11,55 @@ LL | #![feature(specialization)] error[E0520]: `foo` specializes an item from a parent `impl`, but that item is not marked `default` --> $DIR/specialization-no-default.rs:20:5 | -LL | / impl<T> Foo for T { -LL | | fn foo(&self) {} -LL | | fn bar(&self) {} -LL | | } - | |_- parent `impl` is here +LL | impl<T> Foo for T { + | ----------------- parent `impl` is here ... -LL | fn foo(&self) {} - | ^^^^^^^^^^^^^^^^ cannot specialize default item `foo` +LL | fn foo(&self) {} + | ^^^^^^^^^^^^^^^^ cannot specialize default item `foo` | = note: to specialize, `foo` in the parent `impl` must be marked `default` error[E0520]: `bar` specializes an item from a parent `impl`, but that item is not marked `default` --> $DIR/specialization-no-default.rs:23:5 | -LL | / impl<T> Foo for T { -LL | | fn foo(&self) {} -LL | | fn bar(&self) {} -LL | | } - | |_- parent `impl` is here +LL | impl<T> Foo for T { + | ----------------- parent `impl` is here ... -LL | fn bar(&self) {} - | ^^^^^^^^^^^^^^^^ cannot specialize default item `bar` +LL | fn bar(&self) {} + | ^^^^^^^^^^^^^^^^ cannot specialize default item `bar` | = note: to specialize, `bar` in the parent `impl` must be marked `default` error[E0520]: `T` specializes an item from a parent `impl`, but that item is not marked `default` --> $DIR/specialization-no-default.rs:37:5 | -LL | / impl<T> Bar for T { -LL | | type T = u8; -LL | | } - | |_- parent `impl` is here +LL | impl<T> Bar for T { + | ----------------- parent `impl` is here ... -LL | type T = (); - | ^^^^^^^^^^^^ cannot specialize default item `T` +LL | type T = (); + | ^^^^^^^^^^^^ cannot specialize default item `T` | = note: to specialize, `T` in the parent `impl` must be marked `default` error[E0520]: `baz` specializes an item from a parent `impl`, but that item is not marked `default` --> $DIR/specialization-no-default.rs:55:5 | -LL | / impl<T: Clone> Baz for T { -LL | | fn baz(&self) {} -LL | | } - | |_- parent `impl` is here +LL | impl<T: Clone> Baz for T { + | ------------------------ parent `impl` is here ... -LL | fn baz(&self) {} - | ^^^^^^^^^^^^^^^^ cannot specialize default item `baz` +LL | fn baz(&self) {} + | ^^^^^^^^^^^^^^^^ cannot specialize default item `baz` | = note: to specialize, `baz` in the parent `impl` must be marked `default` error[E0520]: `redundant` specializes an item from a parent `impl`, but that item is not marked `default` --> $DIR/specialization-no-default.rs:74:5 | -LL | / impl<T: Clone> Redundant for T { -LL | | fn redundant(&self) {} -LL | | } - | |_- parent `impl` is here +LL | impl<T: Clone> Redundant for T { + | ------------------------------ parent `impl` is here ... -LL | fn redundant(&self) {} - | ^^^^^^^^^^^^^^^^^^^^^^ cannot specialize default item `redundant` +LL | fn redundant(&self) {} + | ^^^^^^^^^^^^^^^^^^^^^^ cannot specialize default item `redundant` | = note: to specialize, `redundant` in the parent `impl` must be marked `default` diff --git a/src/test/ui/specialization/defaultimpl/specialization-trait-not-implemented.stderr b/src/test/ui/specialization/defaultimpl/specialization-trait-not-implemented.stderr index d2350bc7e4f..53a22305e81 100644 --- a/src/test/ui/specialization/defaultimpl/specialization-trait-not-implemented.stderr +++ b/src/test/ui/specialization/defaultimpl/specialization-trait-not-implemented.stderr @@ -12,7 +12,7 @@ error[E0599]: the method `foo_one` exists for struct `MyStruct`, but its trait b --> $DIR/specialization-trait-not-implemented.rs:22:29 | LL | struct MyStruct; - | ---------------- + | --------------- | | | | | method `foo_one` not found for this struct | doesn't satisfy `MyStruct: Foo` @@ -21,18 +21,17 @@ LL | println!("{}", MyStruct.foo_one()); | ^^^^^^^ method cannot be called on `MyStruct` due to unsatisfied trait bounds | note: trait bound `MyStruct: Foo` was not satisfied - --> $DIR/specialization-trait-not-implemented.rs:14:17 + --> $DIR/specialization-trait-not-implemented.rs:14:1 | LL | default impl<T> Foo for T { - | ^^^ ^ + | ^^^^^^^^^^^^^^^^---^^^^^- + | | + | unsatisfied trait bound introduced here note: the following trait must be implemented --> $DIR/specialization-trait-not-implemented.rs:7:1 | -LL | / trait Foo { -LL | | fn foo_one(&self) -> &'static str; -LL | | fn foo_two(&self) -> &'static str; -LL | | } - | |_^ +LL | trait Foo { + | ^^^^^^^^^ = help: items from traits can only be used if the trait is implemented and in scope note: `Foo` defines an item `foo_one`, perhaps you need to implement it --> $DIR/specialization-trait-not-implemented.rs:7:1 diff --git a/src/test/ui/specialization/issue-50452-fail.stderr b/src/test/ui/specialization/issue-50452-fail.stderr index 8e7c5037eff..7249ad73871 100644 --- a/src/test/ui/specialization/issue-50452-fail.stderr +++ b/src/test/ui/specialization/issue-50452-fail.stderr @@ -11,13 +11,11 @@ LL | #![feature(specialization)] error[E0520]: `foo` specializes an item from a parent `impl`, but that item is not marked `default` --> $DIR/issue-50452-fail.rs:10:5 | -LL | fn foo() {} - | ^^^^^^^^^^^ cannot specialize default item `foo` +LL | fn foo() {} + | ^^^^^^^^^^^ cannot specialize default item `foo` ... -LL | / impl<T> Foo for T { -LL | | fn foo() {} -LL | | } - | |_- parent `impl` is here +LL | impl<T> Foo for T { + | ----------------- parent `impl` is here | = note: to specialize, `foo` in the parent `impl` must be marked `default` diff --git a/src/test/ui/specialization/issue-52050.stderr b/src/test/ui/specialization/issue-52050.stderr index 8732b10d8f8..6d24997a5bf 100644 --- a/src/test/ui/specialization/issue-52050.stderr +++ b/src/test/ui/specialization/issue-52050.stderr @@ -11,15 +11,11 @@ LL | #![feature(specialization)] error[E0119]: conflicting implementations of trait `IntoPyDictPointer` for type `()` --> $DIR/issue-52050.rs:28:1 | -LL | / impl<I> IntoPyDictPointer for I -LL | | where -LL | | I: Iterator, -LL | | { -LL | | } - | |_- first implementation here -LL | -LL | impl IntoPyDictPointer for () - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ conflicting implementation for `()` +LL | impl<I> IntoPyDictPointer for I + | ------------------------------- first implementation here +... +LL | impl IntoPyDictPointer for () + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ conflicting implementation for `()` | = note: upstream crates may add a new impl of trait `std::iter::Iterator` for type `()` in future versions diff --git a/src/test/ui/specialization/min_specialization/dyn-trait-assoc-types.stderr b/src/test/ui/specialization/min_specialization/dyn-trait-assoc-types.stderr index 6345cee2c37..db5558f16be 100644 --- a/src/test/ui/specialization/min_specialization/dyn-trait-assoc-types.stderr +++ b/src/test/ui/specialization/min_specialization/dyn-trait-assoc-types.stderr @@ -1,20 +1,14 @@ error: specializing impl repeats parameter `T` --> $DIR/dyn-trait-assoc-types.rs:22:1 | -LL | / impl<'a, T> Specializable for dyn B<T, Y = T> + 'a { -LL | | -LL | | fn f() {} -LL | | } - | |_^ +LL | impl<'a, T> Specializable for dyn B<T, Y = T> + 'a { + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ error: specializing impl repeats parameter `T` --> $DIR/dyn-trait-assoc-types.rs:27:1 | -LL | / impl<'a, T> Specializable for dyn C<Y = (T, T)> + 'a { -LL | | -LL | | fn f() {} -LL | | } - | |_^ +LL | impl<'a, T> Specializable for dyn C<Y = (T, T)> + 'a { + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ error: aborting due to 2 previous errors diff --git a/src/test/ui/specialization/min_specialization/repeated_projection_type.stderr b/src/test/ui/specialization/min_specialization/repeated_projection_type.stderr index 1a7eb82c95b..a751ba79347 100644 --- a/src/test/ui/specialization/min_specialization/repeated_projection_type.stderr +++ b/src/test/ui/specialization/min_specialization/repeated_projection_type.stderr @@ -1,11 +1,8 @@ -error: cannot specialize on `Binder(ProjectionPredicate(ProjectionTy { substs: [V], item_def_id: DefId(0:6 ~ repeated_projection_type[54ea]::Id::This) }, Ty((I,))), [])` - --> $DIR/repeated_projection_type.rs:19:1 +error: cannot specialize on associated type `<V as Id>::This == (I,)` + --> $DIR/repeated_projection_type.rs:19:15 | -LL | / impl<I, V: Id<This = (I,)>> X for V { -LL | | -LL | | fn f() {} -LL | | } - | |_^ +LL | impl<I, V: Id<This = (I,)>> X for V { + | ^^^^^^^^^^^ error: aborting due to previous error diff --git a/src/test/ui/specialization/min_specialization/repeating_lifetimes.stderr b/src/test/ui/specialization/min_specialization/repeating_lifetimes.stderr index ce9309f7012..16dccb10b45 100644 --- a/src/test/ui/specialization/min_specialization/repeating_lifetimes.stderr +++ b/src/test/ui/specialization/min_specialization/repeating_lifetimes.stderr @@ -1,11 +1,8 @@ error: specializing impl repeats parameter `'a` --> $DIR/repeating_lifetimes.rs:14:1 | -LL | / impl<'a> X for (&'a u8, &'a u8) { -LL | | -LL | | fn f() {} -LL | | } - | |_^ +LL | impl<'a> X for (&'a u8, &'a u8) { + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ error: aborting due to previous error diff --git a/src/test/ui/specialization/min_specialization/repeating_param.stderr b/src/test/ui/specialization/min_specialization/repeating_param.stderr index 8b4be1c4995..5e6adf723b5 100644 --- a/src/test/ui/specialization/min_specialization/repeating_param.stderr +++ b/src/test/ui/specialization/min_specialization/repeating_param.stderr @@ -1,11 +1,8 @@ error: specializing impl repeats parameter `T` --> $DIR/repeating_param.rs:12:1 | -LL | / impl<T> X for (T, T) { -LL | | -LL | | fn f() {} -LL | | } - | |_^ +LL | impl<T> X for (T, T) { + | ^^^^^^^^^^^^^^^^^^^^ error: aborting due to previous error diff --git a/src/test/ui/specialization/min_specialization/spec-marker-supertraits.stderr b/src/test/ui/specialization/min_specialization/spec-marker-supertraits.stderr index 964109dd10f..ba9d6bbe300 100644 --- a/src/test/ui/specialization/min_specialization/spec-marker-supertraits.stderr +++ b/src/test/ui/specialization/min_specialization/spec-marker-supertraits.stderr @@ -1,13 +1,8 @@ error: cannot specialize on trait `HasMethod` - --> $DIR/spec-marker-supertraits.rs:22:1 + --> $DIR/spec-marker-supertraits.rs:22:9 | -LL | / impl<T: Marker> Spec for T { -LL | | -LL | | fn spec_me(&self) { -LL | | self.method(); -LL | | } -LL | | } - | |_^ +LL | impl<T: Marker> Spec for T { + | ^^^^^^ error: aborting due to previous error diff --git a/src/test/ui/specialization/min_specialization/specialization_marker.stderr b/src/test/ui/specialization/min_specialization/specialization_marker.stderr index ffeced19821..b47c14f3c9f 100644 --- a/src/test/ui/specialization/min_specialization/specialization_marker.stderr +++ b/src/test/ui/specialization/min_specialization/specialization_marker.stderr @@ -8,7 +8,7 @@ error[E0714]: marker traits cannot have associated items --> $DIR/specialization_marker.rs:13:5 | LL | type X; - | ^^^^^^^ + | ^^^^^^ error: aborting due to 2 previous errors diff --git a/src/test/ui/specialization/min_specialization/specialization_super_trait.stderr b/src/test/ui/specialization/min_specialization/specialization_super_trait.stderr index 5782ad01b39..e935786624b 100644 --- a/src/test/ui/specialization/min_specialization/specialization_super_trait.stderr +++ b/src/test/ui/specialization/min_specialization/specialization_super_trait.stderr @@ -1,11 +1,8 @@ error: cannot specialize on trait `Default` - --> $DIR/specialization_super_trait.rs:13:1 + --> $DIR/specialization_super_trait.rs:13:9 | -LL | / impl<T: Default> SpecMarker for T { -LL | | -LL | | fn f() {} -LL | | } - | |_^ +LL | impl<T: Default> SpecMarker for T { + | ^^^^^^^ error: aborting due to previous error diff --git a/src/test/ui/specialization/min_specialization/specialization_trait.stderr b/src/test/ui/specialization/min_specialization/specialization_trait.stderr index 8a70d6cc1bf..bc87ae0f8b8 100644 --- a/src/test/ui/specialization/min_specialization/specialization_trait.stderr +++ b/src/test/ui/specialization/min_specialization/specialization_trait.stderr @@ -1,29 +1,20 @@ error: cannot specialize on `'static` lifetime --> $DIR/specialization_trait.rs:11:1 | -LL | / impl SpecMarker for &'static u8 { -LL | | -LL | | fn f() {} -LL | | } - | |_^ +LL | impl SpecMarker for &'static u8 { + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ error: specializing impl repeats parameter `T` --> $DIR/specialization_trait.rs:16:1 | -LL | / impl<T> SpecMarker for (T, T) { -LL | | -LL | | fn f() {} -LL | | } - | |_^ +LL | impl<T> SpecMarker for (T, T) { + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ error: cannot specialize on trait `Clone` - --> $DIR/specialization_trait.rs:21:1 + --> $DIR/specialization_trait.rs:21:9 | -LL | / impl<T: Clone> SpecMarker for [T] { -LL | | -LL | | fn f() {} -LL | | } - | |_^ +LL | impl<T: Clone> SpecMarker for [T] { + | ^^^^^ error: aborting due to 3 previous errors diff --git a/src/test/ui/specialization/min_specialization/specialize_on_static.stderr b/src/test/ui/specialization/min_specialization/specialize_on_static.stderr index d1809d6dfbb..9a16798f15c 100644 --- a/src/test/ui/specialization/min_specialization/specialize_on_static.stderr +++ b/src/test/ui/specialization/min_specialization/specialize_on_static.stderr @@ -1,11 +1,8 @@ error: cannot specialize on `'static` lifetime --> $DIR/specialize_on_static.rs:13:1 | -LL | / impl X for &'static u8 { -LL | | -LL | | fn f() {} -LL | | } - | |_^ +LL | impl X for &'static u8 { + | ^^^^^^^^^^^^^^^^^^^^^^ error: aborting due to previous error diff --git a/src/test/ui/specialization/min_specialization/specialize_on_trait.stderr b/src/test/ui/specialization/min_specialization/specialize_on_trait.stderr index 35445fd09b9..7b79c7eb4ad 100644 --- a/src/test/ui/specialization/min_specialization/specialize_on_trait.stderr +++ b/src/test/ui/specialization/min_specialization/specialize_on_trait.stderr @@ -1,11 +1,8 @@ error: cannot specialize on trait `SpecMarker` - --> $DIR/specialize_on_trait.rs:15:1 + --> $DIR/specialize_on_trait.rs:15:9 | -LL | / impl<T: SpecMarker> X for T { -LL | | -LL | | fn f() {} -LL | | } - | |_^ +LL | impl<T: SpecMarker> X for T { + | ^^^^^^^^^^ error: aborting due to previous error diff --git a/src/test/ui/specialization/non-defaulted-item-fail.stderr b/src/test/ui/specialization/non-defaulted-item-fail.stderr index 85ccbd809b0..8b7d6797275 100644 --- a/src/test/ui/specialization/non-defaulted-item-fail.stderr +++ b/src/test/ui/specialization/non-defaulted-item-fail.stderr @@ -11,45 +11,33 @@ LL | #![feature(specialization, associated_type_defaults)] error[E0520]: `Ty` specializes an item from a parent `impl`, but that item is not marked `default` --> $DIR/non-defaulted-item-fail.rs:30:5 | -LL | / impl<T> Foo for Box<T> { -LL | | type Ty = bool; -LL | | const CONST: u8 = 0; -LL | | fn foo(&self) -> bool { false } -LL | | } - | |_- parent `impl` is here +LL | impl<T> Foo for Box<T> { + | ---------------------- parent `impl` is here ... -LL | type Ty = Vec<()>; - | ^^^^^^^^^^^^^^^^^^ cannot specialize default item `Ty` +LL | type Ty = Vec<()>; + | ^^^^^^^^^^^^^^^^^^ cannot specialize default item `Ty` | = note: to specialize, `Ty` in the parent `impl` must be marked `default` error[E0520]: `CONST` specializes an item from a parent `impl`, but that item is not marked `default` --> $DIR/non-defaulted-item-fail.rs:32:5 | -LL | / impl<T> Foo for Box<T> { -LL | | type Ty = bool; -LL | | const CONST: u8 = 0; -LL | | fn foo(&self) -> bool { false } -LL | | } - | |_- parent `impl` is here +LL | impl<T> Foo for Box<T> { + | ---------------------- parent `impl` is here ... -LL | const CONST: u8 = 42; - | ^^^^^^^^^^^^^^^^^^^^^ cannot specialize default item `CONST` +LL | const CONST: u8 = 42; + | ^^^^^^^^^^^^^^^^^^^^^ cannot specialize default item `CONST` | = note: to specialize, `CONST` in the parent `impl` must be marked `default` error[E0520]: `foo` specializes an item from a parent `impl`, but that item is not marked `default` --> $DIR/non-defaulted-item-fail.rs:34:5 | -LL | / impl<T> Foo for Box<T> { -LL | | type Ty = bool; -LL | | const CONST: u8 = 0; -LL | | fn foo(&self) -> bool { false } -LL | | } - | |_- parent `impl` is here +LL | impl<T> Foo for Box<T> { + | ---------------------- parent `impl` is here ... -LL | fn foo(&self) -> bool { true } - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ cannot specialize default item `foo` +LL | fn foo(&self) -> bool { true } + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ cannot specialize default item `foo` | = note: to specialize, `foo` in the parent `impl` must be marked `default` @@ -57,7 +45,7 @@ error[E0520]: `Ty` specializes an item from a parent `impl`, but that item is no --> $DIR/non-defaulted-item-fail.rs:46:5 | LL | impl<T> Foo for Vec<T> {} - | ------------------------- parent `impl` is here + | ---------------------- parent `impl` is here ... LL | type Ty = Vec<()>; | ^^^^^^^^^^^^^^^^^^ cannot specialize default item `Ty` @@ -68,7 +56,7 @@ error[E0520]: `CONST` specializes an item from a parent `impl`, but that item is --> $DIR/non-defaulted-item-fail.rs:48:5 | LL | impl<T> Foo for Vec<T> {} - | ------------------------- parent `impl` is here + | ---------------------- parent `impl` is here ... LL | const CONST: u8 = 42; | ^^^^^^^^^^^^^^^^^^^^^ cannot specialize default item `CONST` @@ -79,7 +67,7 @@ error[E0520]: `foo` specializes an item from a parent `impl`, but that item is n --> $DIR/non-defaulted-item-fail.rs:50:5 | LL | impl<T> Foo for Vec<T> {} - | ------------------------- parent `impl` is here + | ---------------------- parent `impl` is here ... LL | fn foo(&self) -> bool { true } | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ cannot specialize default item `foo` diff --git a/src/test/ui/specialization/specialization-no-default.stderr b/src/test/ui/specialization/specialization-no-default.stderr index 711c1fda149..28c869a7055 100644 --- a/src/test/ui/specialization/specialization-no-default.stderr +++ b/src/test/ui/specialization/specialization-no-default.stderr @@ -11,67 +11,55 @@ LL | #![feature(specialization)] error[E0520]: `foo` specializes an item from a parent `impl`, but that item is not marked `default` --> $DIR/specialization-no-default.rs:20:5 | -LL | / impl<T> Foo for T { -LL | | fn foo(&self) {} -LL | | fn bar(&self) {} -LL | | } - | |_- parent `impl` is here +LL | impl<T> Foo for T { + | ----------------- parent `impl` is here ... -LL | fn foo(&self) {} - | ^^^^^^^^^^^^^^^^ cannot specialize default item `foo` +LL | fn foo(&self) {} + | ^^^^^^^^^^^^^^^^ cannot specialize default item `foo` | = note: to specialize, `foo` in the parent `impl` must be marked `default` error[E0520]: `bar` specializes an item from a parent `impl`, but that item is not marked `default` --> $DIR/specialization-no-default.rs:23:5 | -LL | / impl<T> Foo for T { -LL | | fn foo(&self) {} -LL | | fn bar(&self) {} -LL | | } - | |_- parent `impl` is here +LL | impl<T> Foo for T { + | ----------------- parent `impl` is here ... -LL | fn bar(&self) {} - | ^^^^^^^^^^^^^^^^ cannot specialize default item `bar` +LL | fn bar(&self) {} + | ^^^^^^^^^^^^^^^^ cannot specialize default item `bar` | = note: to specialize, `bar` in the parent `impl` must be marked `default` error[E0520]: `T` specializes an item from a parent `impl`, but that item is not marked `default` --> $DIR/specialization-no-default.rs:37:5 | -LL | / impl<T> Bar for T { -LL | | type T = u8; -LL | | } - | |_- parent `impl` is here +LL | impl<T> Bar for T { + | ----------------- parent `impl` is here ... -LL | type T = (); - | ^^^^^^^^^^^^ cannot specialize default item `T` +LL | type T = (); + | ^^^^^^^^^^^^ cannot specialize default item `T` | = note: to specialize, `T` in the parent `impl` must be marked `default` error[E0520]: `baz` specializes an item from a parent `impl`, but that item is not marked `default` --> $DIR/specialization-no-default.rs:55:5 | -LL | / impl<T: Clone> Baz for T { -LL | | fn baz(&self) {} -LL | | } - | |_- parent `impl` is here +LL | impl<T: Clone> Baz for T { + | ------------------------ parent `impl` is here ... -LL | fn baz(&self) {} - | ^^^^^^^^^^^^^^^^ cannot specialize default item `baz` +LL | fn baz(&self) {} + | ^^^^^^^^^^^^^^^^ cannot specialize default item `baz` | = note: to specialize, `baz` in the parent `impl` must be marked `default` error[E0520]: `redundant` specializes an item from a parent `impl`, but that item is not marked `default` --> $DIR/specialization-no-default.rs:74:5 | -LL | / impl<T: Clone> Redundant for T { -LL | | fn redundant(&self) {} -LL | | } - | |_- parent `impl` is here +LL | impl<T: Clone> Redundant for T { + | ------------------------------ parent `impl` is here ... -LL | default fn redundant(&self) {} - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ cannot specialize default item `redundant` +LL | default fn redundant(&self) {} + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ cannot specialize default item `redundant` | = note: to specialize, `redundant` in the parent `impl` must be marked `default` diff --git a/src/test/ui/static/static-priv-by-default2.stderr b/src/test/ui/static/static-priv-by-default2.stderr index d731da79246..b14e096d62a 100644 --- a/src/test/ui/static/static-priv-by-default2.stderr +++ b/src/test/ui/static/static-priv-by-default2.stderr @@ -20,7 +20,7 @@ note: the static `private` is defined here --> $DIR/auxiliary/static_priv_by_default.rs:3:1 | LL | static private: isize = 0; - | ^^^^^^^^^^^^^^^^^^^^^^^^^^ + | ^^^^^^^^^^^^^^^^^^^^^ error: aborting due to 2 previous errors diff --git a/src/test/ui/statics/uninhabited-static.stderr b/src/test/ui/statics/uninhabited-static.stderr index 855e5dca92a..10b86bb4986 100644 --- a/src/test/ui/statics/uninhabited-static.stderr +++ b/src/test/ui/statics/uninhabited-static.stderr @@ -27,7 +27,7 @@ error: static of uninhabited type --> $DIR/uninhabited-static.rs:12:1 | LL | static VOID2: Void = unsafe { std::mem::transmute(()) }; - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | ^^^^^^^^^^^^^^^^^^ | = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release! = note: for more information, see issue #74840 <https://github.com/rust-lang/rust/issues/74840> @@ -37,7 +37,7 @@ error: static of uninhabited type --> $DIR/uninhabited-static.rs:16:1 | LL | static NEVER2: Void = unsafe { std::mem::transmute(()) }; - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | ^^^^^^^^^^^^^^^^^^^ | = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release! = note: for more information, see issue #74840 <https://github.com/rust-lang/rust/issues/74840> diff --git a/src/test/ui/suggestions/attribute-typos.stderr b/src/test/ui/suggestions/attribute-typos.stderr index d6163a5a7cf..54122cb7360 100644 --- a/src/test/ui/suggestions/attribute-typos.stderr +++ b/src/test/ui/suggestions/attribute-typos.stderr @@ -19,7 +19,7 @@ LL | #[tests] ::: $SRC_DIR/core/src/macros/mod.rs:LL:COL | LL | pub macro test($item:item) { - | -------------------------- similarly named attribute macro `test` defined here + | -------------- similarly named attribute macro `test` defined here error: cannot find attribute `deprcated` in this scope --> $DIR/attribute-typos.rs:1:3 diff --git a/src/test/ui/suggestions/const-in-struct-pat.stderr b/src/test/ui/suggestions/const-in-struct-pat.stderr index 784f1bdb6cf..c8b93f3dc48 100644 --- a/src/test/ui/suggestions/const-in-struct-pat.stderr +++ b/src/test/ui/suggestions/const-in-struct-pat.stderr @@ -2,7 +2,7 @@ error[E0308]: mismatched types --> $DIR/const-in-struct-pat.rs:8:17 | LL | struct foo; - | ----------- unit struct defined here + | ---------- unit struct defined here ... LL | let Thing { foo } = t; | ^^^ - this expression has type `Thing` diff --git a/src/test/ui/suggestions/const-pat-non-exaustive-let-new-var.stderr b/src/test/ui/suggestions/const-pat-non-exaustive-let-new-var.stderr index af64c09d5ca..618bcaca14c 100644 --- a/src/test/ui/suggestions/const-pat-non-exaustive-let-new-var.stderr +++ b/src/test/ui/suggestions/const-pat-non-exaustive-let-new-var.stderr @@ -8,7 +8,7 @@ LL | let A = 3; | help: introduce a variable instead: `a_var` ... LL | const A: i32 = 2; - | ----------------- constant defined here + | ------------ constant defined here | = note: the matched value is of type `i32` diff --git a/src/test/ui/suggestions/derive-trait-for-method-call.stderr b/src/test/ui/suggestions/derive-trait-for-method-call.stderr index 65167ce4a29..0ec57fabdad 100644 --- a/src/test/ui/suggestions/derive-trait-for-method-call.stderr +++ b/src/test/ui/suggestions/derive-trait-for-method-call.stderr @@ -23,14 +23,8 @@ LL | let y = x.test(); note: the following trait must be implemented --> $SRC_DIR/core/src/default.rs:LL:COL | -LL | / pub trait Default: Sized { -LL | | /// Returns the "default value" for a type. -LL | | /// -LL | | /// Default values are often some kind of initial value, identity value, or anything else that -... | -LL | | fn default() -> Self; -LL | | } - | |_^ +LL | pub trait Default: Sized { + | ^^^^^^^^^^^^^^^^^^^^^^^^ help: consider annotating `Enum` with `#[derive(Clone)]` | LL | #[derive(Clone)] @@ -79,7 +73,7 @@ LL | let y = x.test(); ::: $SRC_DIR/std/src/time.rs:LL:COL | LL | pub struct Instant(time::Instant); - | ---------------------------------- doesn't satisfy `Instant: Default` + | ------------------ doesn't satisfy `Instant: Default` | ::: $SRC_DIR/alloc/src/vec/mod.rs:LL:COL | diff --git a/src/test/ui/suggestions/fn-or-tuple-struct-without-args.stderr b/src/test/ui/suggestions/fn-or-tuple-struct-without-args.stderr index 25ce458f6d8..505ed2ad7b3 100644 --- a/src/test/ui/suggestions/fn-or-tuple-struct-without-args.stderr +++ b/src/test/ui/suggestions/fn-or-tuple-struct-without-args.stderr @@ -40,7 +40,7 @@ error[E0308]: mismatched types --> $DIR/fn-or-tuple-struct-without-args.rs:30:16 | LL | struct S(usize, usize); - | ----------------------- fn(usize, usize) -> S {S} defined here + | -------- fn(usize, usize) -> S {S} defined here ... LL | let _: S = S; | - ^ expected struct `S`, found fn item @@ -76,7 +76,7 @@ error[E0308]: mismatched types --> $DIR/fn-or-tuple-struct-without-args.rs:32:16 | LL | struct V(); - | ----------- fn() -> V {V} defined here + | -------- fn() -> V {V} defined here ... LL | let _: V = V; | - ^ expected struct `V`, found fn item diff --git a/src/test/ui/suggestions/invalid-bin-op.stderr b/src/test/ui/suggestions/invalid-bin-op.stderr index 94bd2d41565..08502dfeb2d 100644 --- a/src/test/ui/suggestions/invalid-bin-op.stderr +++ b/src/test/ui/suggestions/invalid-bin-op.stderr @@ -10,7 +10,7 @@ note: an implementation of `PartialEq<_>` might be missing for `S<T>` --> $DIR/invalid-bin-op.rs:5:1 | LL | struct S<T>(T); - | ^^^^^^^^^^^^^^^ must implement `PartialEq<_>` + | ^^^^^^^^^^^ must implement `PartialEq<_>` help: consider annotating `S<T>` with `#[derive(PartialEq)]` | LL | #[derive(PartialEq)] diff --git a/src/test/ui/suggestions/missing-assoc-fn-applicable-suggestions.stderr b/src/test/ui/suggestions/missing-assoc-fn-applicable-suggestions.stderr index ee29a56f3f8..4c75fbe4c78 100644 --- a/src/test/ui/suggestions/missing-assoc-fn-applicable-suggestions.stderr +++ b/src/test/ui/suggestions/missing-assoc-fn-applicable-suggestions.stderr @@ -2,7 +2,7 @@ error[E0046]: not all trait items implemented, missing: `Type`, `bar`, `baz` --> $DIR/missing-assoc-fn-applicable-suggestions.rs:15:1 | LL | type Type; - | ---------- `Type` from trait + | --------- `Type` from trait LL | fn bar<T>(_: T) -> Self; | ------------------------ `bar` from trait LL | fn baz<T>(_: T) -> Self where T: TraitB, <T as TraitB>::Item: Copy; diff --git a/src/test/ui/suggestions/suggest-blanket-impl-local-trait.rs b/src/test/ui/suggestions/suggest-blanket-impl-local-trait.rs new file mode 100644 index 00000000000..7cf536f7966 --- /dev/null +++ b/src/test/ui/suggestions/suggest-blanket-impl-local-trait.rs @@ -0,0 +1,58 @@ +// Ensure that the compiler include the blanklet implementation suggestion +// when inside a `impl` statment are used two local traits. +// +// edition:2021 +use std::fmt; + +trait LocalTraitOne { } + +trait LocalTraitTwo { } + +trait GenericTrait<T> {} + +impl LocalTraitTwo for LocalTraitOne {} +//~^ ERROR trait objects must include the `dyn` keyword +//~| HELP add `dyn` keyword before this trait +//~| HELP alternatively use a blanket implementation to implement `LocalTraitTwo` for all types that also implement `LocalTraitOne` + +impl fmt::Display for LocalTraitOne { +//~^ ERROR trait objects must include the `dyn` keyword +//~| HELP add `dyn` keyword before this trait + fn fmt(&self, _f: &mut fmt::Formatter<'_>) -> fmt::Result { + todo!(); + } +} + +impl fmt::Display for LocalTraitTwo + Send { +//~^ ERROR trait objects must include the `dyn` keyword +//~| HELP add `dyn` keyword before this trait + fn fmt(&self, _f: &mut fmt::Formatter<'_>) -> fmt::Result { + todo!(); + } +} + +impl LocalTraitOne for fmt::Display {} +//~^ ERROR trait objects must include the `dyn` keyword +//~| HELP add `dyn` keyword before this trait +//~| HELP alternatively use a blanket implementation to implement `LocalTraitOne` for all types that also implement `fmt::Display` + + +impl LocalTraitOne for fmt::Display + Send {} +//~^ ERROR trait objects must include the `dyn` keyword +//~| HELP add `dyn` keyword before this trait +//~| HELP alternatively use a blanket implementation to implement `LocalTraitOne` for all types that also implement `fmt::Display + Send` + + +impl<E> GenericTrait<E> for LocalTraitOne {} +//~^ ERROR trait objects must include the `dyn` keyword +//~| HELP add `dyn` keyword before this trait +//~| HELP alternatively use a blanket implementation to implement `GenericTrait<E>` for all types that also implement `LocalTraitOne` + +trait GenericTraitTwo<T> {} + +impl<T, E> GenericTraitTwo<E> for GenericTrait<T> {} +//~^ ERROR trait objects must include the `dyn` keyword +//~| HELP add `dyn` keyword before this trait +//~| HELP alternatively use a blanket implementation to implement `GenericTraitTwo<E>` for all types that also implement `GenericTrait<T>` + +fn main() {} diff --git a/src/test/ui/suggestions/suggest-blanket-impl-local-trait.stderr b/src/test/ui/suggestions/suggest-blanket-impl-local-trait.stderr new file mode 100644 index 00000000000..d739a8272f1 --- /dev/null +++ b/src/test/ui/suggestions/suggest-blanket-impl-local-trait.stderr @@ -0,0 +1,107 @@ +error[E0782]: trait objects must include the `dyn` keyword + --> $DIR/suggest-blanket-impl-local-trait.rs:13:24 + | +LL | impl LocalTraitTwo for LocalTraitOne {} + | ^^^^^^^^^^^^^ + | +help: add `dyn` keyword before this trait + | +LL - impl LocalTraitTwo for LocalTraitOne {} +LL + impl LocalTraitTwo for dyn LocalTraitOne {} + | +help: alternatively use a blanket implementation to implement `LocalTraitTwo` for all types that also implement `LocalTraitOne` + | +LL | impl<T: LocalTraitOne> LocalTraitTwo for T {} + | ++++++++++++++++++ ~ + +error[E0782]: trait objects must include the `dyn` keyword + --> $DIR/suggest-blanket-impl-local-trait.rs:18:23 + | +LL | impl fmt::Display for LocalTraitOne { + | ^^^^^^^^^^^^^ + | +help: add `dyn` keyword before this trait + | +LL - impl fmt::Display for LocalTraitOne { +LL + impl fmt::Display for dyn LocalTraitOne { + | + +error[E0782]: trait objects must include the `dyn` keyword + --> $DIR/suggest-blanket-impl-local-trait.rs:26:23 + | +LL | impl fmt::Display for LocalTraitTwo + Send { + | ^^^^^^^^^^^^^^^^^^^^ + | +help: add `dyn` keyword before this trait + | +LL - impl fmt::Display for LocalTraitTwo + Send { +LL + impl fmt::Display for dyn LocalTraitTwo + Send { + | + +error[E0782]: trait objects must include the `dyn` keyword + --> $DIR/suggest-blanket-impl-local-trait.rs:34:24 + | +LL | impl LocalTraitOne for fmt::Display {} + | ^^^^^^^^^^^^ + | +help: add `dyn` keyword before this trait + | +LL - impl LocalTraitOne for fmt::Display {} +LL + impl LocalTraitOne for dyn fmt::Display {} + | +help: alternatively use a blanket implementation to implement `LocalTraitOne` for all types that also implement `fmt::Display` + | +LL | impl<T: fmt::Display> LocalTraitOne for T {} + | +++++++++++++++++ ~ + +error[E0782]: trait objects must include the `dyn` keyword + --> $DIR/suggest-blanket-impl-local-trait.rs:40:24 + | +LL | impl LocalTraitOne for fmt::Display + Send {} + | ^^^^^^^^^^^^^^^^^^^ + | +help: add `dyn` keyword before this trait + | +LL - impl LocalTraitOne for fmt::Display + Send {} +LL + impl LocalTraitOne for dyn fmt::Display + Send {} + | +help: alternatively use a blanket implementation to implement `LocalTraitOne` for all types that also implement `fmt::Display + Send` + | +LL | impl<T: fmt::Display + Send> LocalTraitOne for T {} + | ++++++++++++++++++++++++ ~ + +error[E0782]: trait objects must include the `dyn` keyword + --> $DIR/suggest-blanket-impl-local-trait.rs:46:29 + | +LL | impl<E> GenericTrait<E> for LocalTraitOne {} + | ^^^^^^^^^^^^^ + | +help: add `dyn` keyword before this trait + | +LL - impl<E> GenericTrait<E> for LocalTraitOne {} +LL + impl<E> GenericTrait<E> for dyn LocalTraitOne {} + | +help: alternatively use a blanket implementation to implement `GenericTrait<E>` for all types that also implement `LocalTraitOne` + | +LL | impl<E, T: LocalTraitOne> GenericTrait<E> for T {} + | ++++++++++++++++++ ~ + +error[E0782]: trait objects must include the `dyn` keyword + --> $DIR/suggest-blanket-impl-local-trait.rs:53:35 + | +LL | impl<T, E> GenericTraitTwo<E> for GenericTrait<T> {} + | ^^^^^^^^^^^^^^^ + | +help: add `dyn` keyword before this trait + | +LL - impl<T, E> GenericTraitTwo<E> for GenericTrait<T> {} +LL + impl<T, E> GenericTraitTwo<E> for dyn GenericTrait<T> {} + | +help: alternatively use a blanket implementation to implement `GenericTraitTwo<E>` for all types that also implement `GenericTrait<T>` + | +LL | impl<T, E, U: GenericTrait<T>> GenericTraitTwo<E> for U {} + | ++++++++++++++++++++ ~ + +error: aborting due to 7 previous errors + +For more information about this error, try `rustc --explain E0782`. diff --git a/src/test/ui/suggestions/suggest-closure-return-type-1.stderr b/src/test/ui/suggestions/suggest-closure-return-type-1.stderr index 3116211b52c..f4c2eb7ff34 100644 --- a/src/test/ui/suggestions/suggest-closure-return-type-1.stderr +++ b/src/test/ui/suggestions/suggest-closure-return-type-1.stderr @@ -2,7 +2,7 @@ error[E0282]: type annotations needed for `[_; 0]` --> $DIR/suggest-closure-return-type-1.rs:4:18 | LL | unbound_drop(|| -> _ { [] }); - | ^^^^^^^ + | ^^^^^^^ -- type must be known at this point | help: try giving this closure an explicit return type | diff --git a/src/test/ui/suggestions/suggest-closure-return-type-2.stderr b/src/test/ui/suggestions/suggest-closure-return-type-2.stderr index f368e7de467..88bf263043d 100644 --- a/src/test/ui/suggestions/suggest-closure-return-type-2.stderr +++ b/src/test/ui/suggestions/suggest-closure-return-type-2.stderr @@ -2,7 +2,7 @@ error[E0282]: type annotations needed for `[_; 0]` --> $DIR/suggest-closure-return-type-2.rs:4:18 | LL | unbound_drop(|| { [] }) - | ^^ + | ^^ -- type must be known at this point | help: try giving this closure an explicit return type | diff --git a/src/test/ui/suggestions/suggest-closure-return-type-3.stderr b/src/test/ui/suggestions/suggest-closure-return-type-3.stderr index 41769321533..bc4107528d2 100644 --- a/src/test/ui/suggestions/suggest-closure-return-type-3.stderr +++ b/src/test/ui/suggestions/suggest-closure-return-type-3.stderr @@ -2,7 +2,7 @@ error[E0282]: type annotations needed for `[_; 0]` --> $DIR/suggest-closure-return-type-3.rs:4:18 | LL | unbound_drop(|| []); - | ^^ + | ^^ -- type must be known at this point | help: try giving this closure an explicit return type | diff --git a/src/test/ui/suggestions/suggest-on-bare-closure-call.rs b/src/test/ui/suggestions/suggest-on-bare-closure-call.rs index 355708c08ec..496c305bc2a 100644 --- a/src/test/ui/suggestions/suggest-on-bare-closure-call.rs +++ b/src/test/ui/suggestions/suggest-on-bare-closure-call.rs @@ -1,4 +1,11 @@ +// edition:2021 + +#![feature(async_closure)] + fn main() { let _ = ||{}(); //~^ ERROR expected function, found `()` + + let _ = async ||{}(); + //~^ ERROR expected function, found `()` } diff --git a/src/test/ui/suggestions/suggest-on-bare-closure-call.stderr b/src/test/ui/suggestions/suggest-on-bare-closure-call.stderr index 81f2e498fe5..e65a6eb4939 100644 --- a/src/test/ui/suggestions/suggest-on-bare-closure-call.stderr +++ b/src/test/ui/suggestions/suggest-on-bare-closure-call.stderr @@ -1,5 +1,5 @@ error[E0618]: expected function, found `()` - --> $DIR/suggest-on-bare-closure-call.rs:2:15 + --> $DIR/suggest-on-bare-closure-call.rs:6:15 | LL | let _ = ||{}(); | ^^-- @@ -11,6 +11,19 @@ help: if you meant to create this closure and immediately call it, surround the LL | let _ = (||{})(); | + + -error: aborting due to previous error +error[E0618]: expected function, found `()` + --> $DIR/suggest-on-bare-closure-call.rs:9:21 + | +LL | let _ = async ||{}(); + | ^^-- + | | + | call expression requires function + | +help: if you meant to create this closure and immediately call it, surround the closure with parentheses + | +LL | let _ = (async ||{})(); + | + + + +error: aborting due to 2 previous errors For more information about this error, try `rustc --explain E0618`. diff --git a/src/test/ui/suggestions/suggest-trait-items.stderr b/src/test/ui/suggestions/suggest-trait-items.stderr index 4abc3446610..8bc3df7b817 100644 --- a/src/test/ui/suggestions/suggest-trait-items.stderr +++ b/src/test/ui/suggestions/suggest-trait-items.stderr @@ -47,7 +47,7 @@ error[E0046]: not all trait items implemented, missing: `Type`, `foo`, `bar`, `q --> $DIR/suggest-trait-items.rs:11:1 | LL | type Type; - | ---------- `Type` from trait + | --------- `Type` from trait LL | LL | fn foo(); | --------- `foo` from trait @@ -63,7 +63,7 @@ error[E0046]: not all trait items implemented, missing: `Const` --> $DIR/suggest-trait-items.rs:40:1 | LL | const Const: i32; - | ----------------- `Const` from trait + | ---------------- `Const` from trait ... LL | impl Bar for B { | ^^^^^^^^^^^^^^ missing `Const` in implementation diff --git a/src/test/ui/suggestions/use-type-argument-instead-of-assoc-type.stderr b/src/test/ui/suggestions/use-type-argument-instead-of-assoc-type.stderr index 5409e32c436..7038a572bec 100644 --- a/src/test/ui/suggestions/use-type-argument-instead-of-assoc-type.stderr +++ b/src/test/ui/suggestions/use-type-argument-instead-of-assoc-type.stderr @@ -18,10 +18,10 @@ error[E0191]: the value of the associated types `A` (from trait `T`), `C` (from --> $DIR/use-type-argument-instead-of-assoc-type.rs:7:16 | LL | type A; - | ------- `A` defined here + | ------ `A` defined here LL | type B; LL | type C; - | ------- `C` defined here + | ------ `C` defined here ... LL | i: Box<dyn T<usize, usize, usize, usize, B=usize>>, | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ associated types `A`, `C` must be specified 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 deleted file mode 100644 index fd975aaaee4..00000000000 --- a/src/test/ui/trait-bounds/select-param-env-instead-of-blanket.rs +++ /dev/null @@ -1,43 +0,0 @@ -// known-bug: #93008 -// build-fail -// failure-status: 101 -// compile-flags:--crate-type=lib -Zmir-opt-level=3 -// rustc-env:RUST_BACKTRACE=0 - -// normalize-stderr-test "thread 'rustc' panicked.*" -> "thread 'rustc' panicked" -// normalize-stderr-test "note:.*RUST_BACKTRACE=1.*\n" -> "" -// normalize-stderr-test "error: internal compiler error.*" -> "error: internal compiler error" -// normalize-stderr-test "encountered.*with incompatible types:" "encountered ... with incompatible types:" -// normalize-stderr-test "note:.*unexpectedly panicked.*\n\n" -> "" -// normalize-stderr-test "note: we would appreciate a bug report.*\n\n" -> "" -// normalize-stderr-test "note: compiler flags.*\n\n" -> "" -// normalize-stderr-test "note: rustc.*running on.*\n\n" -> "" -// normalize-stderr-test "query stack during panic:\n" -> "" -// normalize-stderr-test "we're just showing a limited slice of the query stack\n" -> "" -// normalize-stderr-test "end of query stack\n" -> "" -// normalize-stderr-test "#.*\n" -> "" - -// This is a known bug that @compiler-errors tried to fix in #94238, -// but the solution was probably not correct. - -pub trait Factory<T> { - type Item; -} - -pub struct IntFactory; - -impl<T> Factory<T> for IntFactory { - type Item = usize; -} - -pub fn foo<T>() -where - IntFactory: Factory<T>, -{ - let mut x: <IntFactory as Factory<T>>::Item = bar::<T>(); -} - -#[inline] -pub fn bar<T>() -> <IntFactory as Factory<T>>::Item { - 0usize -} diff --git a/src/test/ui/trait-bounds/select-param-env-instead-of-blanket.stderr b/src/test/ui/trait-bounds/select-param-env-instead-of-blanket.stderr deleted file mode 100644 index 56cc5c93c96..00000000000 --- a/src/test/ui/trait-bounds/select-param-env-instead-of-blanket.stderr +++ /dev/null @@ -1,18 +0,0 @@ -error: internal compiler error - -error: internal compiler error - encountered ... with incompatible types: - left-hand side has type: <IntFactory as Factory<T>>::Item - right-hand side has type: usize - --> $DIR/select-param-env-instead-of-blanket.rs:42:5 - | -LL | let mut x: <IntFactory as Factory<T>>::Item = bar::<T>(); - | ---------- in this inlined function call -... -LL | 0usize - | ^^^^^^ - | - = note: delayed at compiler/rustc_const_eval/src/transform/validate.rs:128:36 - -thread 'rustc' panicked - diff --git a/src/test/ui/traits/alias/only-maybe-bound.stderr b/src/test/ui/traits/alias/only-maybe-bound.stderr index 06c707e4332..175ec8120ec 100644 --- a/src/test/ui/traits/alias/only-maybe-bound.stderr +++ b/src/test/ui/traits/alias/only-maybe-bound.stderr @@ -2,7 +2,7 @@ error[E0224]: at least one trait is required for an object type --> $DIR/only-maybe-bound.rs:13:12 | LL | trait _1 = _0; - | -------------- this alias does not contain a trait + | -------- this alias does not contain a trait ... LL | type _T0 = dyn _1; | ^^^^^^ @@ -11,7 +11,7 @@ error[E0224]: at least one trait is required for an object type --> $DIR/only-maybe-bound.rs:19:12 | LL | trait _2 = _1 + _1; - | ------------------- this alias does not contain a trait + | -------- this alias does not contain a trait LL | LL | type _T1 = dyn _2; | ^^^^^^ diff --git a/src/test/ui/traits/bound/same-crate-name.stderr b/src/test/ui/traits/bound/same-crate-name.stderr index ef39a70066d..f66cad77fcd 100644 --- a/src/test/ui/traits/bound/same-crate-name.stderr +++ b/src/test/ui/traits/bound/same-crate-name.stderr @@ -10,7 +10,7 @@ help: trait impl with same name found --> $DIR/auxiliary/crate_a2.rs:5:1 | LL | impl Bar for Foo {} - | ^^^^^^^^^^^^^^^^^^^ + | ^^^^^^^^^^^^^^^^ = note: perhaps two different versions of crate `crate_a2` are being used? = help: the trait `main::a::Bar` is implemented for `ImplementsTraitForUsize<usize>` note: required by a bound in `try_foo` @@ -46,7 +46,7 @@ help: trait impl with same name found --> $DIR/auxiliary/crate_a2.rs:13:1 | LL | impl Bar for ImplementsWrongTraitConditionally<isize> {} - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ = note: perhaps two different versions of crate `crate_a2` are being used? = help: the trait `main::a::Bar` is implemented for `ImplementsTraitForUsize<usize>` note: required by a bound in `try_foo` diff --git a/src/test/ui/traits/copy-impl-cannot-normalize.stderr b/src/test/ui/traits/copy-impl-cannot-normalize.stderr index cc540ea905a..afdad160919 100644 --- a/src/test/ui/traits/copy-impl-cannot-normalize.stderr +++ b/src/test/ui/traits/copy-impl-cannot-normalize.stderr @@ -2,7 +2,7 @@ error[E0277]: the trait bound `T: TraitFoo` is not satisfied --> $DIR/copy-impl-cannot-normalize.rs:22:1 | LL | impl<T> Copy for Foo<T> {} - | ^^^^^^^^^^^^^^^^^^^^^^^^^^ the trait `TraitFoo` is not implemented for `T` + | ^^^^^^^^^^^^^^^^^^^^^^^ the trait `TraitFoo` is not implemented for `T` | help: consider restricting type parameter `T` | diff --git a/src/test/ui/traits/issue-33140-hack-boundaries.stderr b/src/test/ui/traits/issue-33140-hack-boundaries.stderr index c87f1ff1f3f..62cfca545b2 100644 --- a/src/test/ui/traits/issue-33140-hack-boundaries.stderr +++ b/src/test/ui/traits/issue-33140-hack-boundaries.stderr @@ -60,7 +60,7 @@ error[E0119]: conflicting implementations of trait `Trait5` for type `(dyn std:: LL | impl Trait5 for dyn Send {} | ------------------------ first implementation here LL | impl Trait5 for dyn Send where u32: Copy {} - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ conflicting implementation for `(dyn std::marker::Send + 'static)` + | ^^^^^^^^^^^^^^^^^^^^^^^^ conflicting implementation for `(dyn std::marker::Send + 'static)` error: aborting due to 8 previous errors diff --git a/src/test/ui/traits/issue-65673.stderr b/src/test/ui/traits/issue-65673.stderr index 71f3a0e7c7c..8f01d7c53e7 100644 --- a/src/test/ui/traits/issue-65673.stderr +++ b/src/test/ui/traits/issue-65673.stderr @@ -2,7 +2,7 @@ error[E0224]: at least one trait is required for an object type --> $DIR/issue-65673.rs:9:16 | LL | trait Alias<T> = where T: Trait; - | -------------------------------- this alias does not contain a trait + | -------------- this alias does not contain a trait ... LL | type Ctx = dyn Alias<T>; | ^^^^^^^^^^^^ diff --git a/src/test/ui/traits/issue-71036.stderr b/src/test/ui/traits/issue-71036.stderr index db1f6946660..3ee6db40e87 100644 --- a/src/test/ui/traits/issue-71036.stderr +++ b/src/test/ui/traits/issue-71036.stderr @@ -2,7 +2,7 @@ error[E0277]: the trait bound `&'a T: Unsize<&'a U>` is not satisfied --> $DIR/issue-71036.rs:11:1 | LL | impl<'a, T: ?Sized + Unsize<U>, U: ?Sized> DispatchFromDyn<Foo<'a, U>> for Foo<'a, T> {} - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ the trait `Unsize<&'a U>` is not implemented for `&'a T` + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ the trait `Unsize<&'a U>` is not implemented for `&'a T` | = note: all implementations of `Unsize` are provided automatically by the compiler, see <https://doc.rust-lang.org/stable/std/marker/trait.Unsize.html> for more information = note: required because of the requirements on the impl of `DispatchFromDyn<&'a &'a U>` for `&'a &'a T` diff --git a/src/test/ui/traits/issue-77982.stderr b/src/test/ui/traits/issue-77982.stderr index 5aa42b5b1d3..a2d23c4e9df 100644 --- a/src/test/ui/traits/issue-77982.stderr +++ b/src/test/ui/traits/issue-77982.stderr @@ -26,7 +26,9 @@ error[E0283]: type annotations needed --> $DIR/issue-77982.rs:8:10 | LL | opts.get(opt.as_ref()); - | ^^^ cannot infer type of the type parameter `Q` declared on the associated function `get` + | ^^^ ------ type must be known at this point + | | + | cannot infer type of the type parameter `Q` declared on the associated function `get` | = note: multiple `impl`s satisfying `String: AsRef<_>` found in the following crates: `alloc`, `std`: - impl AsRef<OsStr> for String; @@ -42,7 +44,9 @@ error[E0283]: type annotations needed --> $DIR/issue-77982.rs:13:59 | LL | let ips: Vec<_> = (0..100_000).map(|_| u32::from(0u32.into())).collect(); - | ^^^^ + | --------- ^^^^ + | | + | type must be known at this point | = note: multiple `impl`s satisfying `u32: From<_>` found in the following crates: `core`, `std`: - impl From<Ipv4Addr> for u32; @@ -59,7 +63,7 @@ error[E0283]: type annotations needed for `Box<T>` --> $DIR/issue-77982.rs:36:9 | LL | let _ = ().foo(); - | ^ + | ^ --- type must be known at this point | note: multiple `impl`s satisfying `(): Foo<'_, _>` found --> $DIR/issue-77982.rs:29:1 @@ -77,7 +81,7 @@ error[E0283]: type annotations needed for `Box<T>` --> $DIR/issue-77982.rs:40:9 | LL | let _ = (&()).bar(); - | ^ + | ^ --- type must be known at this point | note: multiple `impl`s satisfying `&(): Bar<'_, _>` found --> $DIR/issue-77982.rs:32:1 diff --git a/src/test/ui/traits/issue-78372.stderr b/src/test/ui/traits/issue-78372.stderr index 7574c9107d9..7e781016e1f 100644 --- a/src/test/ui/traits/issue-78372.stderr +++ b/src/test/ui/traits/issue-78372.stderr @@ -54,7 +54,7 @@ error[E0378]: the trait `DispatchFromDyn` may only be implemented for a coercion --> $DIR/issue-78372.rs:3:1 | LL | impl<T> DispatchFromDyn<Smaht<U, MISC>> for T {} - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ error: aborting due to 6 previous errors diff --git a/src/test/ui/traits/issue-85735.rs b/src/test/ui/traits/issue-85735.rs index 16e874ee21e..fb387a9c909 100644 --- a/src/test/ui/traits/issue-85735.rs +++ b/src/test/ui/traits/issue-85735.rs @@ -5,7 +5,7 @@ trait Foo {} impl<'a, 'b, T> Foo for T where T: FnMut(&'a ()), - //~^ ERROR: type annotations needed [E0283] + //~^ ERROR: type annotations needed T: FnMut(&'b ()), { } diff --git a/src/test/ui/traits/issue-85735.stderr b/src/test/ui/traits/issue-85735.stderr index 33b12ef09ec..fa280135beb 100644 --- a/src/test/ui/traits/issue-85735.stderr +++ b/src/test/ui/traits/issue-85735.stderr @@ -1,8 +1,8 @@ -error[E0283]: type annotations needed +error[E0283]: type annotations needed: cannot satisfy `T: FnMut<(&'a (),)>` --> $DIR/issue-85735.rs:7:8 | LL | T: FnMut(&'a ()), - | ^^^^^^^^^^^^^ cannot infer type for type parameter `T` + | ^^^^^^^^^^^^^ | = note: cannot satisfy `T: FnMut<(&'a (),)>` diff --git a/src/test/ui/traits/issue-91949-hangs-on-recursion.rs b/src/test/ui/traits/issue-91949-hangs-on-recursion.rs index cf2218fe522..499a64f2816 100644 --- a/src/test/ui/traits/issue-91949-hangs-on-recursion.rs +++ b/src/test/ui/traits/issue-91949-hangs-on-recursion.rs @@ -1,4 +1,5 @@ // build-fail +// compile-flags: -Zinline-mir=no // error-pattern: overflow evaluating the requirement `(): Sized` // error-pattern: function cannot return without recursing diff --git a/src/test/ui/traits/issue-91949-hangs-on-recursion.stderr b/src/test/ui/traits/issue-91949-hangs-on-recursion.stderr index 6c04616344f..f34e7d270f9 100644 --- a/src/test/ui/traits/issue-91949-hangs-on-recursion.stderr +++ b/src/test/ui/traits/issue-91949-hangs-on-recursion.stderr @@ -1,5 +1,5 @@ warning: function cannot return without recursing - --> $DIR/issue-91949-hangs-on-recursion.rs:21:1 + --> $DIR/issue-91949-hangs-on-recursion.rs:22:1 | LL | / fn recurse<T>(elements: T) -> Vec<char> LL | | where @@ -18,7 +18,7 @@ error[E0275]: overflow evaluating the requirement `(): Sized` = help: consider increasing the recursion limit by adding a `#![recursion_limit = "512"]` attribute to your crate (`issue_91949_hangs_on_recursion`) = note: required because of the requirements on the impl of `Iterator` for `std::iter::Empty<()>` = note: 171 redundant requirements hidden - = note: required because of the requirements on the impl of `Iterator` for `IteratorOfWrapped<(), Map<IteratorOfWrapped<(), Map<IteratorOfWrapped<(), Map<IteratorOfWrapped<(), Map<IteratorOfWrapped<(), Map<IteratorOfWrapped<(), Map<IteratorOfWrapped<(), Map<IteratorOfWrapped<(), Map<IteratorOfWrapped<(), Map<IteratorOfWrapped<(), Map<IteratorOfWrapped<(), Map<IteratorOfWrapped<(), Map<IteratorOfWrapped<(), Map<IteratorOfWrapped<(), Map<IteratorOfWrapped<(), Map<IteratorOfWrapped<(), Map<IteratorOfWrapped<(), Map<IteratorOfWrapped<(), Map<IteratorOfWrapped<(), Map<IteratorOfWrapped<(), Map<IteratorOfWrapped<(), Map<IteratorOfWrapped<(), Map<IteratorOfWrapped<(), Map<IteratorOfWrapped<(), Map<IteratorOfWrapped<(), Map<IteratorOfWrapped<(), Map<IteratorOfWrapped<(), Map<IteratorOfWrapped<(), Map<IteratorOfWrapped<(), Map<IteratorOfWrapped<(), Map<IteratorOfWrapped<(), Map<IteratorOfWrapped<(), Map<IteratorOfWrapped<(), Map<IteratorOfWrapped<(), Map<IteratorOfWrapped<(), Map<IteratorOfWrapped<(), Map<IteratorOfWrapped<(), Map<IteratorOfWrapped<(), Map<IteratorOfWrapped<(), Map<IteratorOfWrapped<(), Map<IteratorOfWrapped<(), Map<IteratorOfWrapped<(), Map<IteratorOfWrapped<(), Map<IteratorOfWrapped<(), Map<IteratorOfWrapped<(), Map<IteratorOfWrapped<(), Map<IteratorOfWrapped<(), Map<IteratorOfWrapped<(), Map<IteratorOfWrapped<(), Map<IteratorOfWrapped<(), Map<IteratorOfWrapped<(), Map<IteratorOfWrapped<(), Map<IteratorOfWrapped<(), Map<IteratorOfWrapped<(), Map<IteratorOfWrapped<(), Map<IteratorOfWrapped<(), Map<IteratorOfWrapped<(), Map<IteratorOfWrapped<(), Map<IteratorOfWrapped<(), Map<IteratorOfWrapped<(), Map<IteratorOfWrapped<(), Map<IteratorOfWrapped<(), Map<IteratorOfWrapped<(), Map<IteratorOfWrapped<(), Map<IteratorOfWrapped<(), Map<IteratorOfWrapped<(), Map<IteratorOfWrapped<(), Map<IteratorOfWrapped<(), Map<IteratorOfWrapped<(), Map<IteratorOfWrapped<(), Map<IteratorOfWrapped<(), Map<IteratorOfWrapped<(), Map<IteratorOfWrapped<(), Map<IteratorOfWrapped<(), Map<IteratorOfWrapped<(), Map<IteratorOfWrapped<(), Map<IteratorOfWrapped<(), Map<IteratorOfWrapped<(), Map<IteratorOfWrapped<(), Map<IteratorOfWrapped<(), Map<IteratorOfWrapped<(), Map<IteratorOfWrapped<(), Map<IteratorOfWrapped<(), Map<IteratorOfWrapped<(), Map<IteratorOfWrapped<(), Map<IteratorOfWrapped<(), std::iter::Empty<()>>, [closure@$DIR/issue-91949-hangs-on-recursion.rs:25:45: 25:52]>>, [closure@$DIR/issue-91949-hangs-on-recursion.rs:25:45: 25:52]>>, [closure@$DIR/issue-91949-hangs-on-recursion.rs:25:45: 25:52]>>, [closure@$DIR/issue-91949-hangs-on-recursion.rs:25:45: 25:52]>>, [closure@$DIR/issue-91949-hangs-on-recursion.rs:25:45: 25:52]>>, [closure@$DIR/issue-91949-hangs-on-recursion.rs:25:45: 25:52]>>, [closure@$DIR/issue-91949-hangs-on-recursion.rs:25:45: 25:52]>>, [closure@$DIR/issue-91949-hangs-on-recursion.rs:25:45: 25:52]>>, [closure@$DIR/issue-91949-hangs-on-recursion.rs:25:45: 25:52]>>, [closure@$DIR/issue-91949-hangs-on-recursion.rs:25:45: 25:52]>>, [closure@$DIR/issue-91949-hangs-on-recursion.rs:25:45: 25:52]>>, [closure@$DIR/issue-91949-hangs-on-recursion.rs:25:45: 25:52]>>, [closure@$DIR/issue-91949-hangs-on-recursion.rs:25:45: 25:52]>>, [closure@$DIR/issue-91949-hangs-on-recursion.rs:25:45: 25:52]>>, [closure@$DIR/issue-91949-hangs-on-recursion.rs:25:45: 25:52]>>, [closure@$DIR/issue-91949-hangs-on-recursion.rs:25:45: 25:52]>>, [closure@$DIR/issue-91949-hangs-on-recursion.rs:25:45: 25:52]>>, [closure@$DIR/issue-91949-hangs-on-recursion.rs:25:45: 25:52]>>, [closure@$DIR/issue-91949-hangs-on-recursion.rs:25:45: 25:52]>>, [closure@$DIR/issue-91949-hangs-on-recursion.rs:25:45: 25:52]>>, [closure@$DIR/issue-91949-hangs-on-recursion.rs:25:45: 25:52]>>, [closure@$DIR/issue-91949-hangs-on-recursion.rs:25:45: 25:52]>>, [closure@$DIR/issue-91949-hangs-on-recursion.rs:25:45: 25:52]>>, [closure@$DIR/issue-91949-hangs-on-recursion.rs:25:45: 25:52]>>, [closure@$DIR/issue-91949-hangs-on-recursion.rs:25:45: 25:52]>>, [closure@$DIR/issue-91949-hangs-on-recursion.rs:25:45: 25:52]>>, [closure@$DIR/issue-91949-hangs-on-recursion.rs:25:45: 25:52]>>, [closure@$DIR/issue-91949-hangs-on-recursion.rs:25:45: 25:52]>>, [closure@$DIR/issue-91949-hangs-on-recursion.rs:25:45: 25:52]>>, [closure@$DIR/issue-91949-hangs-on-recursion.rs:25:45: 25:52]>>, [closure@$DIR/issue-91949-hangs-on-recursion.rs:25:45: 25:52]>>, [closure@$DIR/issue-91949-hangs-on-recursion.rs:25:45: 25:52]>>, [closure@$DIR/issue-91949-hangs-on-recursion.rs:25:45: 25:52]>>, [closure@$DIR/issue-91949-hangs-on-recursion.rs:25:45: 25:52]>>, [closure@$DIR/issue-91949-hangs-on-recursion.rs:25:45: 25:52]>>, [closure@$DIR/issue-91949-hangs-on-recursion.rs:25:45: 25:52]>>, [closure@$DIR/issue-91949-hangs-on-recursion.rs:25:45: 25:52]>>, [closure@$DIR/issue-91949-hangs-on-recursion.rs:25:45: 25:52]>>, [closure@$DIR/issue-91949-hangs-on-recursion.rs:25:45: 25:52]>>, [closure@$DIR/issue-91949-hangs-on-recursion.rs:25:45: 25:52]>>, [closure@$DIR/issue-91949-hangs-on-recursion.rs:25:45: 25:52]>>, [closure@$DIR/issue-91949-hangs-on-recursion.rs:25:45: 25:52]>>, [closure@$DIR/issue-91949-hangs-on-recursion.rs:25:45: 25:52]>>, [closure@$DIR/issue-91949-hangs-on-recursion.rs:25:45: 25:52]>>, [closure@$DIR/issue-91949-hangs-on-recursion.rs:25:45: 25:52]>>, [closure@$DIR/issue-91949-hangs-on-recursion.rs:25:45: 25:52]>>, [closure@$DIR/issue-91949-hangs-on-recursion.rs:25:45: 25:52]>>, [closure@$DIR/issue-91949-hangs-on-recursion.rs:25:45: 25:52]>>, [closure@$DIR/issue-91949-hangs-on-recursion.rs:25:45: 25:52]>>, [closure@$DIR/issue-91949-hangs-on-recursion.rs:25:45: 25:52]>>, [closure@$DIR/issue-91949-hangs-on-recursion.rs:25:45: 25:52]>>, [closure@$DIR/issue-91949-hangs-on-recursion.rs:25:45: 25:52]>>, [closure@$DIR/issue-91949-hangs-on-recursion.rs:25:45: 25:52]>>, [closure@$DIR/issue-91949-hangs-on-recursion.rs:25:45: 25:52]>>, [closure@$DIR/issue-91949-hangs-on-recursion.rs:25:45: 25:52]>>, [closure@$DIR/issue-91949-hangs-on-recursion.rs:25:45: 25:52]>>, [closure@$DIR/issue-91949-hangs-on-recursion.rs:25:45: 25:52]>>, [closure@$DIR/issue-91949-hangs-on-recursion.rs:25:45: 25:52]>>, [closure@$DIR/issue-91949-hangs-on-recursion.rs:25:45: 25:52]>>, [closure@$DIR/issue-91949-hangs-on-recursion.rs:25:45: 25:52]>>, [closure@$DIR/issue-91949-hangs-on-recursion.rs:25:45: 25:52]>>, [closure@$DIR/issue-91949-hangs-on-recursion.rs:25:45: 25:52]>>, [closure@$DIR/issue-91949-hangs-on-recursion.rs:25:45: 25:52]>>, [closure@$DIR/issue-91949-hangs-on-recursion.rs:25:45: 25:52]>>, [closure@$DIR/issue-91949-hangs-on-recursion.rs:25:45: 25:52]>>, [closure@$DIR/issue-91949-hangs-on-recursion.rs:25:45: 25:52]>>, [closure@$DIR/issue-91949-hangs-on-recursion.rs:25:45: 25:52]>>, [closure@$DIR/issue-91949-hangs-on-recursion.rs:25:45: 25:52]>>, [closure@$DIR/issue-91949-hangs-on-recursion.rs:25:45: 25:52]>>, [closure@$DIR/issue-91949-hangs-on-recursion.rs:25:45: 25:52]>>, [closure@$DIR/issue-91949-hangs-on-recursion.rs:25:45: 25:52]>>, [closure@$DIR/issue-91949-hangs-on-recursion.rs:25:45: 25:52]>>, [closure@$DIR/issue-91949-hangs-on-recursion.rs:25:45: 25:52]>>, [closure@$DIR/issue-91949-hangs-on-recursion.rs:25:45: 25:52]>>, [closure@$DIR/issue-91949-hangs-on-recursion.rs:25:45: 25:52]>>, [closure@$DIR/issue-91949-hangs-on-recursion.rs:25:45: 25:52]>>, [closure@$DIR/issue-91949-hangs-on-recursion.rs:25:45: 25:52]>>, [closure@$DIR/issue-91949-hangs-on-recursion.rs:25:45: 25:52]>>, [closure@$DIR/issue-91949-hangs-on-recursion.rs:25:45: 25:52]>>, [closure@$DIR/issue-91949-hangs-on-recursion.rs:25:45: 25:52]>>, [closure@$DIR/issue-91949-hangs-on-recursion.rs:25:45: 25:52]>>, [closure@$DIR/issue-91949-hangs-on-recursion.rs:25:45: 25:52]>>, [closure@$DIR/issue-91949-hangs-on-recursion.rs:25:45: 25:52]>>, [closure@$DIR/issue-91949-hangs-on-recursion.rs:25:45: 25:52]>>, [closure@$DIR/issue-91949-hangs-on-recursion.rs:25:45: 25:52]>>` + = note: required because of the requirements on the impl of `Iterator` for `IteratorOfWrapped<(), Map<IteratorOfWrapped<(), Map<IteratorOfWrapped<(), Map<IteratorOfWrapped<(), Map<IteratorOfWrapped<(), Map<IteratorOfWrapped<(), Map<IteratorOfWrapped<(), Map<IteratorOfWrapped<(), Map<IteratorOfWrapped<(), Map<IteratorOfWrapped<(), Map<IteratorOfWrapped<(), Map<IteratorOfWrapped<(), Map<IteratorOfWrapped<(), Map<IteratorOfWrapped<(), Map<IteratorOfWrapped<(), Map<IteratorOfWrapped<(), Map<IteratorOfWrapped<(), Map<IteratorOfWrapped<(), Map<IteratorOfWrapped<(), Map<IteratorOfWrapped<(), Map<IteratorOfWrapped<(), Map<IteratorOfWrapped<(), Map<IteratorOfWrapped<(), Map<IteratorOfWrapped<(), Map<IteratorOfWrapped<(), Map<IteratorOfWrapped<(), Map<IteratorOfWrapped<(), Map<IteratorOfWrapped<(), Map<IteratorOfWrapped<(), Map<IteratorOfWrapped<(), Map<IteratorOfWrapped<(), Map<IteratorOfWrapped<(), Map<IteratorOfWrapped<(), Map<IteratorOfWrapped<(), Map<IteratorOfWrapped<(), Map<IteratorOfWrapped<(), Map<IteratorOfWrapped<(), Map<IteratorOfWrapped<(), Map<IteratorOfWrapped<(), Map<IteratorOfWrapped<(), Map<IteratorOfWrapped<(), Map<IteratorOfWrapped<(), Map<IteratorOfWrapped<(), Map<IteratorOfWrapped<(), Map<IteratorOfWrapped<(), Map<IteratorOfWrapped<(), Map<IteratorOfWrapped<(), Map<IteratorOfWrapped<(), Map<IteratorOfWrapped<(), Map<IteratorOfWrapped<(), Map<IteratorOfWrapped<(), Map<IteratorOfWrapped<(), Map<IteratorOfWrapped<(), Map<IteratorOfWrapped<(), Map<IteratorOfWrapped<(), Map<IteratorOfWrapped<(), Map<IteratorOfWrapped<(), Map<IteratorOfWrapped<(), Map<IteratorOfWrapped<(), Map<IteratorOfWrapped<(), Map<IteratorOfWrapped<(), Map<IteratorOfWrapped<(), Map<IteratorOfWrapped<(), Map<IteratorOfWrapped<(), Map<IteratorOfWrapped<(), Map<IteratorOfWrapped<(), Map<IteratorOfWrapped<(), Map<IteratorOfWrapped<(), Map<IteratorOfWrapped<(), Map<IteratorOfWrapped<(), Map<IteratorOfWrapped<(), Map<IteratorOfWrapped<(), Map<IteratorOfWrapped<(), Map<IteratorOfWrapped<(), Map<IteratorOfWrapped<(), Map<IteratorOfWrapped<(), Map<IteratorOfWrapped<(), Map<IteratorOfWrapped<(), Map<IteratorOfWrapped<(), Map<IteratorOfWrapped<(), Map<IteratorOfWrapped<(), Map<IteratorOfWrapped<(), Map<IteratorOfWrapped<(), Map<IteratorOfWrapped<(), Map<IteratorOfWrapped<(), Map<IteratorOfWrapped<(), std::iter::Empty<()>>, [closure@$DIR/issue-91949-hangs-on-recursion.rs:26:45: 26:52]>>, [closure@$DIR/issue-91949-hangs-on-recursion.rs:26:45: 26:52]>>, [closure@$DIR/issue-91949-hangs-on-recursion.rs:26:45: 26:52]>>, [closure@$DIR/issue-91949-hangs-on-recursion.rs:26:45: 26:52]>>, [closure@$DIR/issue-91949-hangs-on-recursion.rs:26:45: 26:52]>>, [closure@$DIR/issue-91949-hangs-on-recursion.rs:26:45: 26:52]>>, [closure@$DIR/issue-91949-hangs-on-recursion.rs:26:45: 26:52]>>, [closure@$DIR/issue-91949-hangs-on-recursion.rs:26:45: 26:52]>>, [closure@$DIR/issue-91949-hangs-on-recursion.rs:26:45: 26:52]>>, [closure@$DIR/issue-91949-hangs-on-recursion.rs:26:45: 26:52]>>, [closure@$DIR/issue-91949-hangs-on-recursion.rs:26:45: 26:52]>>, [closure@$DIR/issue-91949-hangs-on-recursion.rs:26:45: 26:52]>>, [closure@$DIR/issue-91949-hangs-on-recursion.rs:26:45: 26:52]>>, [closure@$DIR/issue-91949-hangs-on-recursion.rs:26:45: 26:52]>>, [closure@$DIR/issue-91949-hangs-on-recursion.rs:26:45: 26:52]>>, [closure@$DIR/issue-91949-hangs-on-recursion.rs:26:45: 26:52]>>, [closure@$DIR/issue-91949-hangs-on-recursion.rs:26:45: 26:52]>>, [closure@$DIR/issue-91949-hangs-on-recursion.rs:26:45: 26:52]>>, [closure@$DIR/issue-91949-hangs-on-recursion.rs:26:45: 26:52]>>, [closure@$DIR/issue-91949-hangs-on-recursion.rs:26:45: 26:52]>>, [closure@$DIR/issue-91949-hangs-on-recursion.rs:26:45: 26:52]>>, [closure@$DIR/issue-91949-hangs-on-recursion.rs:26:45: 26:52]>>, [closure@$DIR/issue-91949-hangs-on-recursion.rs:26:45: 26:52]>>, [closure@$DIR/issue-91949-hangs-on-recursion.rs:26:45: 26:52]>>, [closure@$DIR/issue-91949-hangs-on-recursion.rs:26:45: 26:52]>>, [closure@$DIR/issue-91949-hangs-on-recursion.rs:26:45: 26:52]>>, [closure@$DIR/issue-91949-hangs-on-recursion.rs:26:45: 26:52]>>, [closure@$DIR/issue-91949-hangs-on-recursion.rs:26:45: 26:52]>>, [closure@$DIR/issue-91949-hangs-on-recursion.rs:26:45: 26:52]>>, [closure@$DIR/issue-91949-hangs-on-recursion.rs:26:45: 26:52]>>, [closure@$DIR/issue-91949-hangs-on-recursion.rs:26:45: 26:52]>>, [closure@$DIR/issue-91949-hangs-on-recursion.rs:26:45: 26:52]>>, [closure@$DIR/issue-91949-hangs-on-recursion.rs:26:45: 26:52]>>, [closure@$DIR/issue-91949-hangs-on-recursion.rs:26:45: 26:52]>>, [closure@$DIR/issue-91949-hangs-on-recursion.rs:26:45: 26:52]>>, [closure@$DIR/issue-91949-hangs-on-recursion.rs:26:45: 26:52]>>, [closure@$DIR/issue-91949-hangs-on-recursion.rs:26:45: 26:52]>>, [closure@$DIR/issue-91949-hangs-on-recursion.rs:26:45: 26:52]>>, [closure@$DIR/issue-91949-hangs-on-recursion.rs:26:45: 26:52]>>, [closure@$DIR/issue-91949-hangs-on-recursion.rs:26:45: 26:52]>>, [closure@$DIR/issue-91949-hangs-on-recursion.rs:26:45: 26:52]>>, [closure@$DIR/issue-91949-hangs-on-recursion.rs:26:45: 26:52]>>, [closure@$DIR/issue-91949-hangs-on-recursion.rs:26:45: 26:52]>>, [closure@$DIR/issue-91949-hangs-on-recursion.rs:26:45: 26:52]>>, [closure@$DIR/issue-91949-hangs-on-recursion.rs:26:45: 26:52]>>, [closure@$DIR/issue-91949-hangs-on-recursion.rs:26:45: 26:52]>>, [closure@$DIR/issue-91949-hangs-on-recursion.rs:26:45: 26:52]>>, [closure@$DIR/issue-91949-hangs-on-recursion.rs:26:45: 26:52]>>, [closure@$DIR/issue-91949-hangs-on-recursion.rs:26:45: 26:52]>>, [closure@$DIR/issue-91949-hangs-on-recursion.rs:26:45: 26:52]>>, [closure@$DIR/issue-91949-hangs-on-recursion.rs:26:45: 26:52]>>, [closure@$DIR/issue-91949-hangs-on-recursion.rs:26:45: 26:52]>>, [closure@$DIR/issue-91949-hangs-on-recursion.rs:26:45: 26:52]>>, [closure@$DIR/issue-91949-hangs-on-recursion.rs:26:45: 26:52]>>, [closure@$DIR/issue-91949-hangs-on-recursion.rs:26:45: 26:52]>>, [closure@$DIR/issue-91949-hangs-on-recursion.rs:26:45: 26:52]>>, [closure@$DIR/issue-91949-hangs-on-recursion.rs:26:45: 26:52]>>, [closure@$DIR/issue-91949-hangs-on-recursion.rs:26:45: 26:52]>>, [closure@$DIR/issue-91949-hangs-on-recursion.rs:26:45: 26:52]>>, [closure@$DIR/issue-91949-hangs-on-recursion.rs:26:45: 26:52]>>, [closure@$DIR/issue-91949-hangs-on-recursion.rs:26:45: 26:52]>>, [closure@$DIR/issue-91949-hangs-on-recursion.rs:26:45: 26:52]>>, [closure@$DIR/issue-91949-hangs-on-recursion.rs:26:45: 26:52]>>, [closure@$DIR/issue-91949-hangs-on-recursion.rs:26:45: 26:52]>>, [closure@$DIR/issue-91949-hangs-on-recursion.rs:26:45: 26:52]>>, [closure@$DIR/issue-91949-hangs-on-recursion.rs:26:45: 26:52]>>, [closure@$DIR/issue-91949-hangs-on-recursion.rs:26:45: 26:52]>>, [closure@$DIR/issue-91949-hangs-on-recursion.rs:26:45: 26:52]>>, [closure@$DIR/issue-91949-hangs-on-recursion.rs:26:45: 26:52]>>, [closure@$DIR/issue-91949-hangs-on-recursion.rs:26:45: 26:52]>>, [closure@$DIR/issue-91949-hangs-on-recursion.rs:26:45: 26:52]>>, [closure@$DIR/issue-91949-hangs-on-recursion.rs:26:45: 26:52]>>, [closure@$DIR/issue-91949-hangs-on-recursion.rs:26:45: 26:52]>>, [closure@$DIR/issue-91949-hangs-on-recursion.rs:26:45: 26:52]>>, [closure@$DIR/issue-91949-hangs-on-recursion.rs:26:45: 26:52]>>, [closure@$DIR/issue-91949-hangs-on-recursion.rs:26:45: 26:52]>>, [closure@$DIR/issue-91949-hangs-on-recursion.rs:26:45: 26:52]>>, [closure@$DIR/issue-91949-hangs-on-recursion.rs:26:45: 26:52]>>, [closure@$DIR/issue-91949-hangs-on-recursion.rs:26:45: 26:52]>>, [closure@$DIR/issue-91949-hangs-on-recursion.rs:26:45: 26:52]>>, [closure@$DIR/issue-91949-hangs-on-recursion.rs:26:45: 26:52]>>, [closure@$DIR/issue-91949-hangs-on-recursion.rs:26:45: 26:52]>>, [closure@$DIR/issue-91949-hangs-on-recursion.rs:26:45: 26:52]>>, [closure@$DIR/issue-91949-hangs-on-recursion.rs:26:45: 26:52]>>, [closure@$DIR/issue-91949-hangs-on-recursion.rs:26:45: 26:52]>>` error: aborting due to previous error; 1 warning emitted diff --git a/src/test/ui/traits/item-privacy.stderr b/src/test/ui/traits/item-privacy.stderr index a7954f7b245..06ed5ac081d 100644 --- a/src/test/ui/traits/item-privacy.stderr +++ b/src/test/ui/traits/item-privacy.stderr @@ -116,7 +116,7 @@ error[E0624]: associated constant `A` is private --> $DIR/item-privacy.rs:101:14 | LL | const A: u8 = 0; - | ---------------- private associated constant defined here + | ----------- private associated constant defined here ... LL | <dyn C>::A; | ^ private associated constant diff --git a/src/test/ui/traits/object/with-self-in-projection-output-bad.stderr b/src/test/ui/traits/object/with-self-in-projection-output-bad.stderr index 45978a84068..641bfe23666 100644 --- a/src/test/ui/traits/object/with-self-in-projection-output-bad.stderr +++ b/src/test/ui/traits/object/with-self-in-projection-output-bad.stderr @@ -2,7 +2,7 @@ error[E0191]: the value of the associated type `Output` (from trait `Base`) must --> $DIR/with-self-in-projection-output-bad.rs:45:21 | LL | type Output; - | ------------ `Output` defined here + | ----------- `Output` defined here ... LL | let _x: Box<dyn Helper<Target=i32>> = Box::new(2u32); | ^^^^^^^^^^^^^^^^^^ help: specify the associated type: `Helper<Target=i32, Output = Type>` @@ -11,7 +11,7 @@ error[E0191]: the value of the associated type `Output` (from trait `Base`) must --> $DIR/with-self-in-projection-output-bad.rs:48:21 | LL | type Output; - | ------------ `Output` defined here + | ----------- `Output` defined here ... LL | let _y: Box<dyn NormalizableHelper<Target=i32>> = Box::new(2u32); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: specify the associated type: `NormalizableHelper<Target=i32, Output = Type>` diff --git a/src/test/ui/traits/vtable/vtable-diamond.stderr b/src/test/ui/traits/vtable/vtable-diamond.stderr index f71bed84d56..f3718c5d852 100644 --- a/src/test/ui/traits/vtable/vtable-diamond.stderr +++ b/src/test/ui/traits/vtable/vtable-diamond.stderr @@ -10,11 +10,8 @@ error: vtable entries for `<S as D>`: [ ] --> $DIR/vtable-diamond.rs:21:1 | -LL | / trait D: B + C { -LL | | -LL | | fn foo_d(&self) {} -LL | | } - | |_^ +LL | trait D: B + C { + | ^^^^^^^^^^^^^^ error: vtable entries for `<S as C>`: [ MetadataDropInPlace, @@ -25,11 +22,8 @@ error: vtable entries for `<S as C>`: [ ] --> $DIR/vtable-diamond.rs:15:1 | -LL | / trait C: A { -LL | | -LL | | fn foo_c(&self) {} -LL | | } - | |_^ +LL | trait C: A { + | ^^^^^^^^^^ error: aborting due to 2 previous errors diff --git a/src/test/ui/traits/vtable/vtable-multi-level.stderr b/src/test/ui/traits/vtable/vtable-multi-level.stderr index 915fd701b03..d4d7a8fa3a4 100644 --- a/src/test/ui/traits/vtable/vtable-multi-level.stderr +++ b/src/test/ui/traits/vtable/vtable-multi-level.stderr @@ -31,11 +31,8 @@ error: vtable entries for `<S as O>`: [ ] --> $DIR/vtable-multi-level.rs:95:1 | -LL | / trait O: G + N { -LL | | -LL | | fn foo_o(&self) {} -LL | | } - | |_^ +LL | trait O: G + N { + | ^^^^^^^^^^^^^^ error: vtable entries for `<S as B>`: [ MetadataDropInPlace, @@ -45,11 +42,8 @@ error: vtable entries for `<S as B>`: [ ] --> $DIR/vtable-multi-level.rs:19:1 | -LL | / trait B { -LL | | -LL | | fn foo_b(&self) {} -LL | | } - | |_^ +LL | trait B { + | ^^^^^^^ error: vtable entries for `<S as D>`: [ MetadataDropInPlace, @@ -59,11 +53,8 @@ error: vtable entries for `<S as D>`: [ ] --> $DIR/vtable-multi-level.rs:30:1 | -LL | / trait D { -LL | | -LL | | fn foo_d(&self) {} -LL | | } - | |_^ +LL | trait D { + | ^^^^^^^ error: vtable entries for `<S as E>`: [ MetadataDropInPlace, @@ -73,11 +64,8 @@ error: vtable entries for `<S as E>`: [ ] --> $DIR/vtable-multi-level.rs:36:1 | -LL | / trait E { -LL | | -LL | | fn foo_e(&self) {} -LL | | } - | |_^ +LL | trait E { + | ^^^^^^^ error: vtable entries for `<S as F>`: [ MetadataDropInPlace, @@ -90,11 +78,8 @@ error: vtable entries for `<S as F>`: [ ] --> $DIR/vtable-multi-level.rs:42:1 | -LL | / trait F: D + E { -LL | | -LL | | fn foo_f(&self) {} -LL | | } - | |_^ +LL | trait F: D + E { + | ^^^^^^^^^^^^^^ error: vtable entries for `<S as H>`: [ MetadataDropInPlace, @@ -104,11 +89,8 @@ error: vtable entries for `<S as H>`: [ ] --> $DIR/vtable-multi-level.rs:53:1 | -LL | / trait H { -LL | | -LL | | fn foo_h(&self) {} -LL | | } - | |_^ +LL | trait H { + | ^^^^^^^ error: vtable entries for `<S as I>`: [ MetadataDropInPlace, @@ -118,11 +100,8 @@ error: vtable entries for `<S as I>`: [ ] --> $DIR/vtable-multi-level.rs:59:1 | -LL | / trait I { -LL | | -LL | | fn foo_i(&self) {} -LL | | } - | |_^ +LL | trait I { + | ^^^^^^^ error: vtable entries for `<S as J>`: [ MetadataDropInPlace, @@ -135,11 +114,8 @@ error: vtable entries for `<S as J>`: [ ] --> $DIR/vtable-multi-level.rs:65:1 | -LL | / trait J: H + I { -LL | | -LL | | fn foo_j(&self) {} -LL | | } - | |_^ +LL | trait J: H + I { + | ^^^^^^^^^^^^^^ error: vtable entries for `<S as K>`: [ MetadataDropInPlace, @@ -149,11 +125,8 @@ error: vtable entries for `<S as K>`: [ ] --> $DIR/vtable-multi-level.rs:71:1 | -LL | / trait K { -LL | | -LL | | fn foo_k(&self) {} -LL | | } - | |_^ +LL | trait K { + | ^^^^^^^ error: vtable entries for `<S as L>`: [ MetadataDropInPlace, @@ -163,11 +136,8 @@ error: vtable entries for `<S as L>`: [ ] --> $DIR/vtable-multi-level.rs:77:1 | -LL | / trait L { -LL | | -LL | | fn foo_l(&self) {} -LL | | } - | |_^ +LL | trait L { + | ^^^^^^^ error: vtable entries for `<S as M>`: [ MetadataDropInPlace, @@ -180,11 +150,8 @@ error: vtable entries for `<S as M>`: [ ] --> $DIR/vtable-multi-level.rs:83:1 | -LL | / trait M: K + L { -LL | | -LL | | fn foo_m(&self) {} -LL | | } - | |_^ +LL | trait M: K + L { + | ^^^^^^^^^^^^^^ error: vtable entries for `<S as N>`: [ MetadataDropInPlace, @@ -204,11 +171,8 @@ error: vtable entries for `<S as N>`: [ ] --> $DIR/vtable-multi-level.rs:89:1 | -LL | / trait N: J + M { -LL | | -LL | | fn foo_n(&self) {} -LL | | } - | |_^ +LL | trait N: J + M { + | ^^^^^^^^^^^^^^ error: aborting due to 12 previous errors diff --git a/src/test/ui/traits/vtable/vtable-multiple.stderr b/src/test/ui/traits/vtable/vtable-multiple.stderr index f1c8947f906..0dcd8443309 100644 --- a/src/test/ui/traits/vtable/vtable-multiple.stderr +++ b/src/test/ui/traits/vtable/vtable-multiple.stderr @@ -9,11 +9,8 @@ error: vtable entries for `<S as C>`: [ ] --> $DIR/vtable-multiple.rs:16:1 | -LL | / trait C: A + B { -LL | | -LL | | fn foo_c(&self) {} -LL | | } - | |_^ +LL | trait C: A + B { + | ^^^^^^^^^^^^^^ error: vtable entries for `<S as B>`: [ MetadataDropInPlace, @@ -23,11 +20,8 @@ error: vtable entries for `<S as B>`: [ ] --> $DIR/vtable-multiple.rs:10:1 | -LL | / trait B { -LL | | -LL | | fn foo_b(&self) {} -LL | | } - | |_^ +LL | trait B { + | ^^^^^^^ error: aborting due to 2 previous errors diff --git a/src/test/ui/traits/vtable/vtable-non-object-safe.stderr b/src/test/ui/traits/vtable/vtable-non-object-safe.stderr index bbfbde222f3..9345c271197 100644 --- a/src/test/ui/traits/vtable/vtable-non-object-safe.stderr +++ b/src/test/ui/traits/vtable/vtable-non-object-safe.stderr @@ -10,7 +10,7 @@ error: vtable entries for `<std::vec::IntoIter<u8> as A>`: [ --> $DIR/vtable-non-object-safe.rs:8:1 | LL | trait A: Iterator {} - | ^^^^^^^^^^^^^^^^^^^^ + | ^^^^^^^^^^^^^^^^^ error: aborting due to previous error diff --git a/src/test/ui/traits/vtable/vtable-vacant.stderr b/src/test/ui/traits/vtable/vtable-vacant.stderr index c8cf5839972..5346a702716 100644 --- a/src/test/ui/traits/vtable/vtable-vacant.stderr +++ b/src/test/ui/traits/vtable/vtable-vacant.stderr @@ -9,12 +9,8 @@ error: vtable entries for `<S as B>`: [ ] --> $DIR/vtable-vacant.rs:15:1 | -LL | / trait B: A { -LL | | -LL | | fn foo_b1(&self) {} -LL | | fn foo_b2(&self) where Self: Send {} -LL | | } - | |_^ +LL | trait B: A { + | ^^^^^^^^^^ error: aborting due to previous error diff --git a/src/test/ui/type-alias-enum-variants/enum-variant-priority-lint-ambiguous_associated_items.stderr b/src/test/ui/type-alias-enum-variants/enum-variant-priority-lint-ambiguous_associated_items.stderr index f007f71a73c..aaa3159e0b0 100644 --- a/src/test/ui/type-alias-enum-variants/enum-variant-priority-lint-ambiguous_associated_items.stderr +++ b/src/test/ui/type-alias-enum-variants/enum-variant-priority-lint-ambiguous_associated_items.stderr @@ -16,7 +16,7 @@ note: `V` could also refer to the associated type defined here --> $DIR/enum-variant-priority-lint-ambiguous_associated_items.rs:26:5 | LL | type V; - | ^^^^^^^ + | ^^^^^^ error: ambiguous associated item --> $DIR/enum-variant-priority-lint-ambiguous_associated_items.rs:32:15 @@ -35,7 +35,7 @@ note: `V` could also refer to the associated type defined here --> $DIR/enum-variant-priority-lint-ambiguous_associated_items.rs:26:5 | LL | type V; - | ^^^^^^^ + | ^^^^^^ error: aborting due to 2 previous errors diff --git a/src/test/ui/type-alias-impl-trait/closures_in_branches.stderr b/src/test/ui/type-alias-impl-trait/closures_in_branches.stderr index b7a7871143c..48b7946ea82 100644 --- a/src/test/ui/type-alias-impl-trait/closures_in_branches.stderr +++ b/src/test/ui/type-alias-impl-trait/closures_in_branches.stderr @@ -2,9 +2,8 @@ error[E0282]: type annotations needed --> $DIR/closures_in_branches.rs:7:10 | LL | |x| x.len() - | ^ + | ^ - type must be known at this point | - = note: type must be known at this point help: consider giving this closure parameter an explicit type | LL | |x: _| x.len() @@ -14,9 +13,8 @@ error[E0282]: type annotations needed --> $DIR/closures_in_branches.rs:21:10 | LL | |x| x.len() - | ^ + | ^ - type must be known at this point | - = note: type must be known at this point help: consider giving this closure parameter an explicit type | LL | |x: _| x.len() diff --git a/src/test/ui/type-alias-impl-trait/fallback.stderr b/src/test/ui/type-alias-impl-trait/fallback.stderr index e009399a60a..e767bfdb08b 100644 --- a/src/test/ui/type-alias-impl-trait/fallback.stderr +++ b/src/test/ui/type-alias-impl-trait/fallback.stderr @@ -1,6 +1,8 @@ error[E0283]: type annotations needed --> $DIR/fallback.rs:24:5 | +LL | fn unconstrained_foo() -> Wrapper<Foo> { + | ------------ type must be known at this point LL | Wrapper::Second | ^^^^^^^^^^^^^^^ cannot infer type of the type parameter `T` declared on the enum `Wrapper` | diff --git a/src/test/ui/type-alias-impl-trait/issue-53092-2.stderr b/src/test/ui/type-alias-impl-trait/issue-53092-2.stderr index f4a0cdb1625..6745b8ef69c 100644 --- a/src/test/ui/type-alias-impl-trait/issue-53092-2.stderr +++ b/src/test/ui/type-alias-impl-trait/issue-53092-2.stderr @@ -8,7 +8,7 @@ note: ...which requires type-checking `CONST_BUG`... --> $DIR/issue-53092-2.rs:6:1 | LL | const CONST_BUG: Bug<u8, ()> = unsafe { std::mem::transmute(|_: u8| ()) }; - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ = note: ...which requires computing layout of `Bug<u8, ()>`... = note: ...which requires normalizing `Bug<u8, ()>`... = note: ...which again requires computing type of `Bug::{opaque#0}`, completing the cycle diff --git a/src/test/ui/type-alias-impl-trait/issue-72793.rs b/src/test/ui/type-alias-impl-trait/issue-72793.rs new file mode 100644 index 00000000000..828c871143a --- /dev/null +++ b/src/test/ui/type-alias-impl-trait/issue-72793.rs @@ -0,0 +1,25 @@ +// check-pass +// compile-flags: -Zmir-opt-level=3 + +#![feature(type_alias_impl_trait)] + +trait T { type Item; } + +type Alias<'a> = impl T<Item = &'a ()>; + +struct S; +impl<'a> T for &'a S { + type Item = &'a (); +} + +fn filter_positive<'a>() -> Alias<'a> { + &S +} + +fn with_positive(fun: impl Fn(Alias<'_>)) { + fun(filter_positive()); +} + +fn main() { + with_positive(|_| ()); +} diff --git a/src/test/ui/type/type-ascription-precedence.stderr b/src/test/ui/type/type-ascription-precedence.stderr index ebce257b278..a8139063db1 100644 --- a/src/test/ui/type/type-ascription-precedence.stderr +++ b/src/test/ui/type/type-ascription-precedence.stderr @@ -32,18 +32,12 @@ note: an implementation of `std::ops::Neg` might be missing for `Z` --> $DIR/type-ascription-precedence.rs:9:1 | LL | struct Z; - | ^^^^^^^^^ must implement `std::ops::Neg` + | ^^^^^^^^ must implement `std::ops::Neg` note: the following trait must be implemented --> $SRC_DIR/core/src/ops/arith.rs:LL:COL | -LL | / pub trait Neg { -LL | | /// The resulting type after applying the `-` operator. -LL | | #[stable(feature = "rust1", since = "1.0.0")] -LL | | type Output; -... | -LL | | fn neg(self) -> Self::Output; -LL | | } - | |_^ +LL | pub trait Neg { + | ^^^^^^^^^^^^^ error[E0308]: mismatched types --> $DIR/type-ascription-precedence.rs:45:5 diff --git a/src/test/ui/type/type-check/cannot_infer_local_or_array.stderr b/src/test/ui/type/type-check/cannot_infer_local_or_array.stderr index d68d5e5d40b..e823bad2668 100644 --- a/src/test/ui/type/type-check/cannot_infer_local_or_array.stderr +++ b/src/test/ui/type/type-check/cannot_infer_local_or_array.stderr @@ -2,7 +2,7 @@ error[E0282]: type annotations needed for `[_; 0]` --> $DIR/cannot_infer_local_or_array.rs:2:9 | LL | let x = []; - | ^ + | ^ -- type must be known at this point | help: consider giving `x` an explicit type, where the placeholders `_` are specified | diff --git a/src/test/ui/type/type-check/issue-40294.stderr b/src/test/ui/type/type-check/issue-40294.stderr index 6d1e490bcf3..75feb5698eb 100644 --- a/src/test/ui/type/type-check/issue-40294.stderr +++ b/src/test/ui/type/type-check/issue-40294.stderr @@ -1,8 +1,8 @@ -error[E0283]: type annotations needed +error[E0283]: type annotations needed: cannot satisfy `&'a T: Foo` --> $DIR/issue-40294.rs:6:19 | LL | where &'a T : Foo, - | ^^^ cannot infer type for reference `&'a T` + | ^^^ | = note: cannot satisfy `&'a T: Foo` diff --git a/src/test/ui/type/type-parameter-defaults-referencing-Self.stderr b/src/test/ui/type/type-parameter-defaults-referencing-Self.stderr index ea259cf3d37..67a4745b399 100644 --- a/src/test/ui/type/type-parameter-defaults-referencing-Self.stderr +++ b/src/test/ui/type/type-parameter-defaults-referencing-Self.stderr @@ -1,13 +1,11 @@ error[E0393]: the type parameter `T` must be explicitly specified --> $DIR/type-parameter-defaults-referencing-Self.rs:8:16 | -LL | / trait Foo<T=Self> { -LL | | fn method(&self); -LL | | } - | |_- type parameter `T` must be specified for this -LL | -LL | fn foo(x: &dyn Foo) { } - | ^^^ help: set the type parameter to the desired type: `Foo<T>` +LL | trait Foo<T=Self> { + | ----------------- type parameter `T` must be specified for this +... +LL | fn foo(x: &dyn Foo) { } + | ^^^ help: set the type parameter to the desired type: `Foo<T>` | = note: because of the default `Self` reference, type parameters must be specified on object types diff --git a/src/test/ui/type/type-params-in-different-spaces-1.stderr b/src/test/ui/type/type-params-in-different-spaces-1.stderr index eeb09a9f02e..4e73e10a301 100644 --- a/src/test/ui/type/type-params-in-different-spaces-1.stderr +++ b/src/test/ui/type/type-params-in-different-spaces-1.stderr @@ -1,16 +1,12 @@ error[E0308]: mismatched types --> $DIR/type-params-in-different-spaces-1.rs:5:17 | -LL | / trait BrokenAdd: Copy + Add<Output=Self> { -LL | | fn broken_add<T>(&self, rhs: T) -> Self { - | | - found type parameter -LL | | *self + rhs - | | ^^^ expected type parameter `Self`, found type parameter `T` -LL | | -... | -LL | | } -LL | | } - | |_- expected type parameter +LL | trait BrokenAdd: Copy + Add<Output=Self> { + | ---------------------------------------- expected type parameter +LL | fn broken_add<T>(&self, rhs: T) -> Self { + | - found type parameter +LL | *self + rhs + | ^^^ expected type parameter `Self`, found type parameter `T` | = note: expected type parameter `Self` found type parameter `T` diff --git a/src/test/ui/type/type-params-in-different-spaces-3.stderr b/src/test/ui/type/type-params-in-different-spaces-3.stderr index 880c138d287..c538d67316c 100644 --- a/src/test/ui/type/type-params-in-different-spaces-3.stderr +++ b/src/test/ui/type/type-params-in-different-spaces-3.stderr @@ -1,16 +1,14 @@ error[E0308]: mismatched types --> $DIR/type-params-in-different-spaces-3.rs:3:9 | -LL | / trait Tr : Sized { -LL | | fn test<X>(u: X) -> Self { - | | - ---- expected `Self` because of return type - | | | - | | found type parameter -LL | | u - | | ^ expected type parameter `Self`, found type parameter `X` -LL | | } -LL | | } - | |_- expected type parameter +LL | trait Tr : Sized { + | ---------------- expected type parameter +LL | fn test<X>(u: X) -> Self { + | - ---- expected `Self` because of return type + | | + | found type parameter +LL | u + | ^ expected type parameter `Self`, found type parameter `X` | = note: expected type parameter `Self` found type parameter `X` diff --git a/src/test/ui/type/type-recursive.stderr b/src/test/ui/type/type-recursive.stderr index 04392f7390d..3202710286e 100644 --- a/src/test/ui/type/type-recursive.stderr +++ b/src/test/ui/type/type-recursive.stderr @@ -42,9 +42,8 @@ error[E0072]: recursive type `T4` has infinite size --> $DIR/type-recursive.rs:16:1 | LL | struct T4(Option<T4>); - | ^^^^^^^^^^----------^^ - | | | - | | recursive without indirection + | ^^^^^^^^^ ---------- recursive without indirection + | | | recursive type has infinite size | help: insert some indirection (e.g., a `Box`, `Rc`, or `&`) to make `T4` representable diff --git a/src/test/ui/type_length_limit.rs b/src/test/ui/type_length_limit.rs index c1f3acbecf9..ce6fdf81121 100644 --- a/src/test/ui/type_length_limit.rs +++ b/src/test/ui/type_length_limit.rs @@ -1,8 +1,10 @@ // build-fail // error-pattern: reached the type-length limit while instantiating +// compile-flags: -Copt-level=0 // normalize-stderr-test: ".nll/" -> "/" // Test that the type length limit can be changed. +// The exact type depends on optimizations, so disable them. #![allow(dead_code)] #![type_length_limit="4"] diff --git a/src/test/ui/typeck/issue-65611.stderr b/src/test/ui/typeck/issue-65611.stderr index 5f831291a38..003c630790d 100644 --- a/src/test/ui/typeck/issue-65611.stderr +++ b/src/test/ui/typeck/issue-65611.stderr @@ -3,8 +3,6 @@ error[E0282]: type annotations needed | LL | let x = buffer.last().unwrap().0.clone(); | ^^^^^^^^^^^^^^^^^^^^^^^^ cannot infer type for type parameter `T` - | - = note: type must be known at this point error[E0609]: no field `0` on type `&_` --> $DIR/issue-65611.rs:59:36 diff --git a/src/test/ui/unboxed-closures/unboxed-closures-failed-recursive-fn-2.stderr b/src/test/ui/unboxed-closures/unboxed-closures-failed-recursive-fn-2.stderr index 666ab79b65c..ff2a597bed0 100644 --- a/src/test/ui/unboxed-closures/unboxed-closures-failed-recursive-fn-2.stderr +++ b/src/test/ui/unboxed-closures/unboxed-closures-failed-recursive-fn-2.stderr @@ -3,8 +3,10 @@ error[E0282]: type annotations needed for `Option<T>` | LL | let mut closure0 = None; | ^^^^^^^^^^^^ +... +LL | return c(); + | --- type must be known at this point | - = note: type must be known at this point help: consider giving `closure0` an explicit type, where the placeholders `_` are specified | LL | let mut closure0: Option<T> = None; diff --git a/src/test/ui/uninhabited/uninhabited-matches-feature-gated.stderr b/src/test/ui/uninhabited/uninhabited-matches-feature-gated.stderr index 74216d265d0..2c107b1f7a4 100644 --- a/src/test/ui/uninhabited/uninhabited-matches-feature-gated.stderr +++ b/src/test/ui/uninhabited/uninhabited-matches-feature-gated.stderr @@ -7,15 +7,11 @@ LL | let _ = match x { note: `Result<u32, &Void>` defined here --> $SRC_DIR/core/src/result.rs:LL:COL | -LL | / pub enum Result<T, E> { -LL | | /// Contains the success value -LL | | #[lang = "Ok"] -LL | | #[stable(feature = "rust1", since = "1.0.0")] -... | -LL | | Err(#[stable(feature = "rust1", since = "1.0.0")] E), - | | ^^^ not covered -LL | | } - | |_- +LL | pub enum Result<T, E> { + | --------------------- +... +LL | Err(#[stable(feature = "rust1", since = "1.0.0")] E), + | ^^^ not covered = note: the matched value is of type `Result<u32, &Void>` help: ensure that all possible cases are being handled by adding a match arm with a wildcard pattern or an explicit pattern as shown | @@ -93,15 +89,11 @@ LL | let _ = match x { note: `Result<u32, Void>` defined here --> $SRC_DIR/core/src/result.rs:LL:COL | -LL | / pub enum Result<T, E> { -LL | | /// Contains the success value -LL | | #[lang = "Ok"] -LL | | #[stable(feature = "rust1", since = "1.0.0")] -... | -LL | | Err(#[stable(feature = "rust1", since = "1.0.0")] E), - | | ^^^ not covered -LL | | } - | |_- +LL | pub enum Result<T, E> { + | --------------------- +... +LL | Err(#[stable(feature = "rust1", since = "1.0.0")] E), + | ^^^ not covered = note: the matched value is of type `Result<u32, Void>` help: ensure that all possible cases are being handled by adding a match arm with a wildcard pattern or an explicit pattern as shown | @@ -120,15 +112,11 @@ LL | let Ok(x) = x; note: `Result<u32, Void>` defined here --> $SRC_DIR/core/src/result.rs:LL:COL | -LL | / pub enum Result<T, E> { -LL | | /// Contains the success value -LL | | #[lang = "Ok"] -LL | | #[stable(feature = "rust1", since = "1.0.0")] -... | -LL | | Err(#[stable(feature = "rust1", since = "1.0.0")] E), - | | ^^^ not covered -LL | | } - | |_- +LL | pub enum Result<T, E> { + | --------------------- +... +LL | Err(#[stable(feature = "rust1", since = "1.0.0")] E), + | ^^^ not covered = note: the matched value is of type `Result<u32, Void>` help: you might want to use `if let` to ignore the variant that isn't matched | diff --git a/src/test/ui/union/union-derive-clone.mirunsafeck.stderr b/src/test/ui/union/union-derive-clone.mirunsafeck.stderr index b5c72aa5247..c277d5b761d 100644 --- a/src/test/ui/union/union-derive-clone.mirunsafeck.stderr +++ b/src/test/ui/union/union-derive-clone.mirunsafeck.stderr @@ -8,7 +8,7 @@ LL | union U5<T> { | doesn't satisfy `U5<CloneNoCopy>: Clone` ... LL | struct CloneNoCopy; - | ------------------- doesn't satisfy `CloneNoCopy: Copy` + | ------------------ doesn't satisfy `CloneNoCopy: Copy` ... LL | let w = u.clone(); | ^^^^^ method cannot be called on `U5<CloneNoCopy>` due to unsatisfied trait bounds diff --git a/src/test/ui/union/union-derive-clone.thirunsafeck.stderr b/src/test/ui/union/union-derive-clone.thirunsafeck.stderr index b5c72aa5247..c277d5b761d 100644 --- a/src/test/ui/union/union-derive-clone.thirunsafeck.stderr +++ b/src/test/ui/union/union-derive-clone.thirunsafeck.stderr @@ -8,7 +8,7 @@ LL | union U5<T> { | doesn't satisfy `U5<CloneNoCopy>: Clone` ... LL | struct CloneNoCopy; - | ------------------- doesn't satisfy `CloneNoCopy: Copy` + | ------------------ doesn't satisfy `CloneNoCopy: Copy` ... LL | let w = u.clone(); | ^^^^^ method cannot be called on `U5<CloneNoCopy>` due to unsatisfied trait bounds diff --git a/src/test/ui/union/union-fields-1.mirunsafeck.stderr b/src/test/ui/union/union-fields-1.mirunsafeck.stderr index 5b932b9626c..0c9981c69fc 100644 --- a/src/test/ui/union/union-fields-1.mirunsafeck.stderr +++ b/src/test/ui/union/union-fields-1.mirunsafeck.stderr @@ -5,7 +5,7 @@ LL | union U1 { | -- field in this union ... LL | c: u8, - | ^^^^^ + | ^ | note: the lint level is defined here --> $DIR/union-fields-1.rs:4:9 @@ -19,13 +19,13 @@ error: field `a` is never read LL | union U2 { | -- field in this union LL | a: u8, - | ^^^^^ + | ^ error: field `a` is never read --> $DIR/union-fields-1.rs:16:20 | LL | union NoDropLike { a: u8 } - | ---------- ^^^^^ + | ---------- ^ | | | field in this union @@ -36,7 +36,7 @@ LL | union U { | - field in this union ... LL | c: u8, - | ^^^^^ + | ^ error: aborting due to 4 previous errors diff --git a/src/test/ui/union/union-fields-1.thirunsafeck.stderr b/src/test/ui/union/union-fields-1.thirunsafeck.stderr index 5b932b9626c..0c9981c69fc 100644 --- a/src/test/ui/union/union-fields-1.thirunsafeck.stderr +++ b/src/test/ui/union/union-fields-1.thirunsafeck.stderr @@ -5,7 +5,7 @@ LL | union U1 { | -- field in this union ... LL | c: u8, - | ^^^^^ + | ^ | note: the lint level is defined here --> $DIR/union-fields-1.rs:4:9 @@ -19,13 +19,13 @@ error: field `a` is never read LL | union U2 { | -- field in this union LL | a: u8, - | ^^^^^ + | ^ error: field `a` is never read --> $DIR/union-fields-1.rs:16:20 | LL | union NoDropLike { a: u8 } - | ---------- ^^^^^ + | ---------- ^ | | | field in this union @@ -36,7 +36,7 @@ LL | union U { | - field in this union ... LL | c: u8, - | ^^^^^ + | ^ error: aborting due to 4 previous errors diff --git a/src/test/ui/union/union-lint-dead-code.mirunsafeck.stderr b/src/test/ui/union/union-lint-dead-code.mirunsafeck.stderr index f6e515f8400..6e21584c37c 100644 --- a/src/test/ui/union/union-lint-dead-code.mirunsafeck.stderr +++ b/src/test/ui/union/union-lint-dead-code.mirunsafeck.stderr @@ -5,7 +5,7 @@ LL | union Foo { | --- field in this union LL | x: usize, LL | b: bool, - | ^^^^^^^ + | ^ | note: the lint level is defined here --> $DIR/union-lint-dead-code.rs:4:9 diff --git a/src/test/ui/union/union-lint-dead-code.thirunsafeck.stderr b/src/test/ui/union/union-lint-dead-code.thirunsafeck.stderr index f6e515f8400..6e21584c37c 100644 --- a/src/test/ui/union/union-lint-dead-code.thirunsafeck.stderr +++ b/src/test/ui/union/union-lint-dead-code.thirunsafeck.stderr @@ -5,7 +5,7 @@ LL | union Foo { | --- field in this union LL | x: usize, LL | b: bool, - | ^^^^^^^ + | ^ | note: the lint level is defined here --> $DIR/union-lint-dead-code.rs:4:9 diff --git a/src/test/ui/union/union-repr-c.stderr b/src/test/ui/union/union-repr-c.stderr index ae84cc7811b..9abf440f735 100644 --- a/src/test/ui/union/union-repr-c.stderr +++ b/src/test/ui/union/union-repr-c.stderr @@ -14,10 +14,8 @@ LL | #![deny(improper_ctypes)] note: the type is defined here --> $DIR/union-repr-c.rs:9:1 | -LL | / union W { -LL | | a: u8, -LL | | } - | |_^ +LL | union W { + | ^^^^^^^ error: aborting due to previous error diff --git a/src/test/ui/unique-object-noncopyable.stderr b/src/test/ui/unique-object-noncopyable.stderr index 5c40787febf..98a9bd07ed2 100644 --- a/src/test/ui/unique-object-noncopyable.stderr +++ b/src/test/ui/unique-object-noncopyable.stderr @@ -16,7 +16,7 @@ LL | / pub struct Box< LL | | T: ?Sized, LL | | #[unstable(feature = "allocator_api", issue = "32838")] A: Allocator = Global, LL | | >(Unique<T>, A); - | |________________- doesn't satisfy `Box<dyn Foo>: Clone` + | |_- doesn't satisfy `Box<dyn Foo>: Clone` | = note: the following trait bounds were not satisfied: `dyn Foo: Sized` diff --git a/src/test/ui/unique-pinned-nocopy.stderr b/src/test/ui/unique-pinned-nocopy.stderr index 02ce371c8d5..7af9c684b72 100644 --- a/src/test/ui/unique-pinned-nocopy.stderr +++ b/src/test/ui/unique-pinned-nocopy.stderr @@ -13,7 +13,7 @@ LL | / pub struct Box< LL | | T: ?Sized, LL | | #[unstable(feature = "allocator_api", issue = "32838")] A: Allocator = Global, LL | | >(Unique<T>, A); - | |________________- doesn't satisfy `Box<R>: Clone` + | |_- doesn't satisfy `Box<R>: Clone` | = note: the following trait bounds were not satisfied: `R: Clone` diff --git a/src/test/ui/unspecified-self-in-trait-ref.stderr b/src/test/ui/unspecified-self-in-trait-ref.stderr index 2ba92187157..7869176bb3a 100644 --- a/src/test/ui/unspecified-self-in-trait-ref.stderr +++ b/src/test/ui/unspecified-self-in-trait-ref.stderr @@ -91,13 +91,11 @@ LL | let e = <dyn Bar::<usize>>::lol(); error[E0393]: the type parameter `A` must be explicitly specified --> $DIR/unspecified-self-in-trait-ref.rs:26:13 | -LL | / pub trait Bar<X=usize, A=Self> { -LL | | fn foo(&self); -LL | | } - | |_- type parameter `A` must be specified for this +LL | pub trait Bar<X=usize, A=Self> { + | ------------------------------ type parameter `A` must be specified for this ... -LL | let e = Bar::<usize>::lol(); - | ^^^^^^^^^^^^ missing reference to `A` +LL | let e = Bar::<usize>::lol(); + | ^^^^^^^^^^^^ missing reference to `A` | = note: because of the default `Self` reference, type parameters must be specified on object types diff --git a/src/test/ui/unwind-abis/feature-gate-c-unwind.rs b/src/test/ui/unwind-abis/feature-gate-c-unwind.rs index f02a368d4e0..ba72f74f20c 100644 --- a/src/test/ui/unwind-abis/feature-gate-c-unwind.rs +++ b/src/test/ui/unwind-abis/feature-gate-c-unwind.rs @@ -1,6 +1,10 @@ // Test that the "C-unwind" ABI is feature-gated, and cannot be used when the // `c_unwind` feature gate is not used. +#![allow(ffi_unwind_calls)] +//~^ WARNING unknown lint: `ffi_unwind_calls` +//~| WARNING unknown lint: `ffi_unwind_calls` + extern "C-unwind" fn f() {} //~^ ERROR C-unwind ABI is experimental and subject to change [E0658] diff --git a/src/test/ui/unwind-abis/feature-gate-c-unwind.stderr b/src/test/ui/unwind-abis/feature-gate-c-unwind.stderr index f4c785a235f..a67f46cd2e3 100644 --- a/src/test/ui/unwind-abis/feature-gate-c-unwind.stderr +++ b/src/test/ui/unwind-abis/feature-gate-c-unwind.stderr @@ -1,5 +1,16 @@ +warning: unknown lint: `ffi_unwind_calls` + --> $DIR/feature-gate-c-unwind.rs:4:1 + | +LL | #![allow(ffi_unwind_calls)] + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | + = note: `#[warn(unknown_lints)]` on by default + = note: the `ffi_unwind_calls` lint is unstable + = note: see issue #74990 <https://github.com/rust-lang/rust/issues/74990> for more information + = help: add `#![feature(c_unwind)]` to the crate attributes to enable + error[E0658]: C-unwind ABI is experimental and subject to change - --> $DIR/feature-gate-c-unwind.rs:4:8 + --> $DIR/feature-gate-c-unwind.rs:8:8 | LL | extern "C-unwind" fn f() {} | ^^^^^^^^^^ @@ -7,6 +18,16 @@ LL | extern "C-unwind" fn f() {} = note: see issue #74990 <https://github.com/rust-lang/rust/issues/74990> for more information = help: add `#![feature(c_unwind)]` to the crate attributes to enable -error: aborting due to previous error +warning: unknown lint: `ffi_unwind_calls` + --> $DIR/feature-gate-c-unwind.rs:4:1 + | +LL | #![allow(ffi_unwind_calls)] + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | + = note: the `ffi_unwind_calls` lint is unstable + = note: see issue #74990 <https://github.com/rust-lang/rust/issues/74990> for more information + = help: add `#![feature(c_unwind)]` to the crate attributes to enable + +error: aborting due to previous error; 2 warnings emitted For more information about this error, try `rustc --explain E0658`. diff --git a/src/test/ui/unwind-abis/ffi-unwind-calls-lint.rs b/src/test/ui/unwind-abis/ffi-unwind-calls-lint.rs new file mode 100644 index 00000000000..dadf4b12187 --- /dev/null +++ b/src/test/ui/unwind-abis/ffi-unwind-calls-lint.rs @@ -0,0 +1,27 @@ +// build-pass +// needs-unwind +// ignore-wasm32-bare compiled with panic=abort by default + +#![feature(c_unwind)] +#![warn(ffi_unwind_calls)] + +mod foo { + #[no_mangle] + pub extern "C-unwind" fn foo() {} +} + +extern "C-unwind" { + fn foo(); +} + +fn main() { + // Call to Rust function is fine. + foo::foo(); + // Call to foreign function should warn. + unsafe { foo(); } + //~^ WARNING call to foreign function with FFI-unwind ABI + let ptr: extern "C-unwind" fn() = foo::foo; + // Call to function pointer should also warn. + ptr(); + //~^ WARNING call to function pointer with FFI-unwind ABI +} diff --git a/src/test/ui/unwind-abis/ffi-unwind-calls-lint.stderr b/src/test/ui/unwind-abis/ffi-unwind-calls-lint.stderr new file mode 100644 index 00000000000..ed41cb74623 --- /dev/null +++ b/src/test/ui/unwind-abis/ffi-unwind-calls-lint.stderr @@ -0,0 +1,20 @@ +warning: call to foreign function with FFI-unwind ABI + --> $DIR/ffi-unwind-calls-lint.rs:21:14 + | +LL | unsafe { foo(); } + | ^^^^^ call to foreign function with FFI-unwind ABI + | +note: the lint level is defined here + --> $DIR/ffi-unwind-calls-lint.rs:6:9 + | +LL | #![warn(ffi_unwind_calls)] + | ^^^^^^^^^^^^^^^^ + +warning: call to function pointer with FFI-unwind ABI + --> $DIR/ffi-unwind-calls-lint.rs:25:5 + | +LL | ptr(); + | ^^^^^ call to function pointer with FFI-unwind ABI + +warning: 2 warnings emitted + diff --git a/src/test/ui/use/use-from-trait-xc.stderr b/src/test/ui/use/use-from-trait-xc.stderr index 14523afbdac..4c4c2f6225f 100644 --- a/src/test/ui/use/use-from-trait-xc.stderr +++ b/src/test/ui/use/use-from-trait-xc.stderr @@ -50,7 +50,7 @@ note: the struct `Foo` is defined here --> $DIR/auxiliary/use-from-trait-xc.rs:9:1 | LL | struct Foo; - | ^^^^^^^^^^^ + | ^^^^^^^^^^ error[E0603]: struct `Foo` is private --> $DIR/use-from-trait-xc.rs:17:24 @@ -62,7 +62,7 @@ note: the struct `Foo` is defined here --> $DIR/auxiliary/use-from-trait-xc.rs:9:1 | LL | struct Foo; - | ^^^^^^^^^^^ + | ^^^^^^^^^^ error: aborting due to 9 previous errors diff --git a/src/test/ui/variance/variance-associated-consts.stderr b/src/test/ui/variance/variance-associated-consts.stderr index d1bf34781df..219f5bca9e3 100644 --- a/src/test/ui/variance/variance-associated-consts.stderr +++ b/src/test/ui/variance/variance-associated-consts.stderr @@ -1,10 +1,8 @@ error[E0208]: [o] --> $DIR/variance-associated-consts.rs:13:1 | -LL | / struct Foo<T: Trait> { -LL | | field: [u8; <T as Trait>::Const] -LL | | } - | |_^ +LL | struct Foo<T: Trait> { + | ^^^^^^^^^^^^^^^^^^^^ error: aborting due to previous error diff --git a/src/test/ui/variance/variance-associated-types.stderr b/src/test/ui/variance/variance-associated-types.stderr index b9aa9695f62..94f770eda33 100644 --- a/src/test/ui/variance/variance-associated-types.stderr +++ b/src/test/ui/variance/variance-associated-types.stderr @@ -1,18 +1,14 @@ error[E0208]: [-, +] --> $DIR/variance-associated-types.rs:13:1 | -LL | / struct Foo<'a, T : Trait<'a>> { -LL | | field: (T, &'a ()) -LL | | } - | |_^ +LL | struct Foo<'a, T : Trait<'a>> { + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ error[E0208]: [o, o] --> $DIR/variance-associated-types.rs:18:1 | -LL | / struct Bar<'a, T : Trait<'a>> { -LL | | field: <T as Trait<'a>>::Type -LL | | } - | |_^ +LL | struct Bar<'a, T : Trait<'a>> { + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ error: aborting due to 2 previous errors diff --git a/src/test/ui/variance/variance-object-types.stderr b/src/test/ui/variance/variance-object-types.stderr index 2a5d8f91e1e..ceee53aff10 100644 --- a/src/test/ui/variance/variance-object-types.stderr +++ b/src/test/ui/variance/variance-object-types.stderr @@ -1,10 +1,8 @@ error[E0208]: [o] --> $DIR/variance-object-types.rs:7:1 | -LL | / struct Foo<'a> { -LL | | x: Box<dyn Fn(i32) -> &'a i32 + 'static> -LL | | } - | |_^ +LL | struct Foo<'a> { + | ^^^^^^^^^^^^^^ error: aborting due to previous error diff --git a/src/test/ui/variance/variance-regions-direct.stderr b/src/test/ui/variance/variance-regions-direct.stderr index 8c9c89955bd..25fb2273215 100644 --- a/src/test/ui/variance/variance-regions-direct.stderr +++ b/src/test/ui/variance/variance-regions-direct.stderr @@ -1,64 +1,44 @@ error[E0208]: [-, -, -] --> $DIR/variance-regions-direct.rs:9:1 | -LL | / struct Test2<'a, 'b, 'c> { -LL | | x: &'a isize, -LL | | y: &'b [isize], -LL | | c: &'c str -LL | | } - | |_^ +LL | struct Test2<'a, 'b, 'c> { + | ^^^^^^^^^^^^^^^^^^^^^^^^ error[E0208]: [+, +, +] --> $DIR/variance-regions-direct.rs:18:1 | -LL | / struct Test3<'a, 'b, 'c> { -LL | | x: extern "Rust" fn(&'a isize), -LL | | y: extern "Rust" fn(&'b [isize]), -LL | | c: extern "Rust" fn(&'c str), -LL | | } - | |_^ +LL | struct Test3<'a, 'b, 'c> { + | ^^^^^^^^^^^^^^^^^^^^^^^^ error[E0208]: [-, o] --> $DIR/variance-regions-direct.rs:27:1 | -LL | / struct Test4<'a, 'b:'a> { -LL | | x: &'a mut &'b isize, -LL | | } - | |_^ +LL | struct Test4<'a, 'b:'a> { + | ^^^^^^^^^^^^^^^^^^^^^^^ error[E0208]: [+, o] --> $DIR/variance-regions-direct.rs:35:1 | -LL | / struct Test5<'a, 'b:'a> { -LL | | x: extern "Rust" fn(&'a mut &'b isize), -LL | | } - | |_^ +LL | struct Test5<'a, 'b:'a> { + | ^^^^^^^^^^^^^^^^^^^^^^^ error[E0208]: [-, o] --> $DIR/variance-regions-direct.rs:45:1 | -LL | / struct Test6<'a, 'b:'a> { -LL | | x: &'a mut extern "Rust" fn(&'b isize), -LL | | } - | |_^ +LL | struct Test6<'a, 'b:'a> { + | ^^^^^^^^^^^^^^^^^^^^^^^ error[E0208]: [*] --> $DIR/variance-regions-direct.rs:52:1 | -LL | / struct Test7<'a> { -LL | | x: isize -LL | | } - | |_^ +LL | struct Test7<'a> { + | ^^^^^^^^^^^^^^^^ error[E0208]: [+, -, o] --> $DIR/variance-regions-direct.rs:59:1 | -LL | / enum Test8<'a, 'b, 'c:'b> { -LL | | Test8A(extern "Rust" fn(&'a isize)), -LL | | Test8B(&'b [isize]), -LL | | Test8C(&'b mut &'c str), -LL | | } - | |_^ +LL | enum Test8<'a, 'b, 'c:'b> { + | ^^^^^^^^^^^^^^^^^^^^^^^^^ error: aborting due to 7 previous errors diff --git a/src/test/ui/variance/variance-regions-indirect.stderr b/src/test/ui/variance/variance-regions-indirect.stderr index 17efc6231d5..fc52492d7ef 100644 --- a/src/test/ui/variance/variance-regions-indirect.stderr +++ b/src/test/ui/variance/variance-regions-indirect.stderr @@ -1,44 +1,32 @@ error[E0208]: [+, -, o, *] --> $DIR/variance-regions-indirect.rs:8:1 | -LL | / enum Base<'a, 'b, 'c:'b, 'd> { -LL | | Test8A(extern "Rust" fn(&'a isize)), -LL | | Test8B(&'b [isize]), -LL | | Test8C(&'b mut &'c str), -LL | | } - | |_^ +LL | enum Base<'a, 'b, 'c:'b, 'd> { + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ error[E0208]: [*, o, -, +] --> $DIR/variance-regions-indirect.rs:15:1 | -LL | / struct Derived1<'w, 'x:'y, 'y, 'z> { -LL | | f: Base<'z, 'y, 'x, 'w> -LL | | } - | |_^ +LL | struct Derived1<'w, 'x:'y, 'y, 'z> { + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ error[E0208]: [o, o, *] --> $DIR/variance-regions-indirect.rs:20:1 | -LL | / struct Derived2<'a, 'b:'a, 'c> { -LL | | f: Base<'a, 'a, 'b, 'c> -LL | | } - | |_^ +LL | struct Derived2<'a, 'b:'a, 'c> { + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ error[E0208]: [o, -, *] --> $DIR/variance-regions-indirect.rs:25:1 | -LL | / struct Derived3<'a:'b, 'b, 'c> { -LL | | f: Base<'a, 'b, 'a, 'c> -LL | | } - | |_^ +LL | struct Derived3<'a:'b, 'b, 'c> { + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ error[E0208]: [+, -, o] --> $DIR/variance-regions-indirect.rs:30:1 | -LL | / struct Derived4<'a, 'b, 'c:'b> { -LL | | f: Base<'a, 'b, 'c, 'a> -LL | | } - | |_^ +LL | struct Derived4<'a, 'b, 'c:'b> { + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ error: aborting due to 5 previous errors diff --git a/src/test/ui/variance/variance-trait-bounds.stderr b/src/test/ui/variance/variance-trait-bounds.stderr index 98bc1b003c3..e3ef339f423 100644 --- a/src/test/ui/variance/variance-trait-bounds.stderr +++ b/src/test/ui/variance/variance-trait-bounds.stderr @@ -1,34 +1,26 @@ error[E0208]: [+, +] --> $DIR/variance-trait-bounds.rs:16:1 | -LL | / struct TestStruct<U,T:Setter<U>> { -LL | | t: T, u: U -LL | | } - | |_^ +LL | struct TestStruct<U,T:Setter<U>> { + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ error[E0208]: [*, +] --> $DIR/variance-trait-bounds.rs:21:1 | -LL | / enum TestEnum<U,T:Setter<U>> { -LL | | Foo(T) -LL | | } - | |_^ +LL | enum TestEnum<U,T:Setter<U>> { + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ error[E0208]: [*, +] --> $DIR/variance-trait-bounds.rs:26:1 | -LL | / struct TestContraStruct<U,T:Setter<U>> { -LL | | t: T -LL | | } - | |_^ +LL | struct TestContraStruct<U,T:Setter<U>> { + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ error[E0208]: [*, +] --> $DIR/variance-trait-bounds.rs:31:1 | -LL | / struct TestBox<U,T:Getter<U>+Setter<U>> { -LL | | t: T -LL | | } - | |_^ +LL | struct TestBox<U,T:Getter<U>+Setter<U>> { + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ error: aborting due to 4 previous errors diff --git a/src/test/ui/variance/variance-trait-object-bound.stderr b/src/test/ui/variance/variance-trait-object-bound.stderr index fb0fab1950c..c86cf1f82b4 100644 --- a/src/test/ui/variance/variance-trait-object-bound.stderr +++ b/src/test/ui/variance/variance-trait-object-bound.stderr @@ -1,10 +1,8 @@ error[E0208]: [-] --> $DIR/variance-trait-object-bound.rs:14:1 | -LL | / struct TOption<'a> { -LL | | v: Option<Box<dyn T + 'a>>, -LL | | } - | |_^ +LL | struct TOption<'a> { + | ^^^^^^^^^^^^^^^^^^ error: aborting due to previous error diff --git a/src/test/ui/variance/variance-types-bounds.stderr b/src/test/ui/variance/variance-types-bounds.stderr index 5cffdffc7f2..dbe8af75d51 100644 --- a/src/test/ui/variance/variance-types-bounds.stderr +++ b/src/test/ui/variance/variance-types-bounds.stderr @@ -1,46 +1,32 @@ error[E0208]: [+, +] --> $DIR/variance-types-bounds.rs:7:1 | -LL | / struct TestImm<A, B> { -LL | | x: A, -LL | | y: B, -LL | | } - | |_^ +LL | struct TestImm<A, B> { + | ^^^^^^^^^^^^^^^^^^^^ error[E0208]: [+, o] --> $DIR/variance-types-bounds.rs:13:1 | -LL | / struct TestMut<A, B:'static> { -LL | | x: A, -LL | | y: &'static mut B, -LL | | } - | |_^ +LL | struct TestMut<A, B:'static> { + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ error[E0208]: [+, o] --> $DIR/variance-types-bounds.rs:19:1 | -LL | / struct TestIndirect<A:'static, B:'static> { -LL | | m: TestMut<A, B> -LL | | } - | |_^ +LL | struct TestIndirect<A:'static, B:'static> { + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ error[E0208]: [o, o] --> $DIR/variance-types-bounds.rs:24:1 | -LL | / struct TestIndirect2<A:'static, B:'static> { -LL | | n: TestMut<A, B>, -LL | | m: TestMut<B, A> -LL | | } - | |_^ +LL | struct TestIndirect2<A:'static, B:'static> { + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ error[E0208]: [o, o] --> $DIR/variance-types-bounds.rs:38:1 | -LL | / struct TestObject<A, R> { -LL | | n: Box<dyn Setter<A>+Send>, -LL | | m: Box<dyn Getter<R>+Send>, -LL | | } - | |_^ +LL | struct TestObject<A, R> { + | ^^^^^^^^^^^^^^^^^^^^^^^ error: aborting due to 5 previous errors diff --git a/src/test/ui/variance/variance-types.stderr b/src/test/ui/variance/variance-types.stderr index 05bd4747cf1..8358b18b73c 100644 --- a/src/test/ui/variance/variance-types.stderr +++ b/src/test/ui/variance/variance-types.stderr @@ -1,52 +1,38 @@ error[E0208]: [-, o, o] --> $DIR/variance-types.rs:10:1 | -LL | / struct InvariantMut<'a,A:'a,B:'a> { -LL | | t: &'a mut (A,B) -LL | | } - | |_^ +LL | struct InvariantMut<'a,A:'a,B:'a> { + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ error[E0208]: [o] --> $DIR/variance-types.rs:15:1 | -LL | / struct InvariantCell<A> { -LL | | t: Cell<A> -LL | | } - | |_^ +LL | struct InvariantCell<A> { + | ^^^^^^^^^^^^^^^^^^^^^^^ error[E0208]: [o] --> $DIR/variance-types.rs:20:1 | -LL | / struct InvariantIndirect<A> { -LL | | t: InvariantCell<A> -LL | | } - | |_^ +LL | struct InvariantIndirect<A> { + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^ error[E0208]: [+] --> $DIR/variance-types.rs:25:1 | -LL | / struct Covariant<A> { -LL | | t: A, u: fn() -> A -LL | | } - | |_^ +LL | struct Covariant<A> { + | ^^^^^^^^^^^^^^^^^^^ error[E0208]: [-] --> $DIR/variance-types.rs:30:1 | -LL | / struct Contravariant<A> { -LL | | t: fn(A) -LL | | } - | |_^ +LL | struct Contravariant<A> { + | ^^^^^^^^^^^^^^^^^^^^^^^ error[E0208]: [+, -, o] --> $DIR/variance-types.rs:35:1 | -LL | / enum Enum<A,B,C> { -LL | | Foo(Covariant<A>), -LL | | Bar(Contravariant<B>), -LL | | Zed(Covariant<C>,Contravariant<C>) -LL | | } - | |_^ +LL | enum Enum<A,B,C> { + | ^^^^^^^^^^^^^^^^ error: aborting due to 6 previous errors diff --git a/src/test/ui/wasm-custom-section-relocations.stderr b/src/test/ui/wasm-custom-section-relocations.stderr index eb8ab2644a3..a37edc51d19 100644 --- a/src/test/ui/wasm-custom-section-relocations.stderr +++ b/src/test/ui/wasm-custom-section-relocations.stderr @@ -2,13 +2,13 @@ error: statics with a custom `#[link_section]` must be a simple list of bytes on --> $DIR/wasm-custom-section-relocations.rs:4:1 | LL | pub static A: &[u8] = &[1]; - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | ^^^^^^^^^^^^^^^^^^^ error: statics with a custom `#[link_section]` must be a simple list of bytes on the wasm target with no extra levels of indirection such as references --> $DIR/wasm-custom-section-relocations.rs:13:1 | LL | pub static D: &usize = &C; - | ^^^^^^^^^^^^^^^^^^^^^^^^^^ + | ^^^^^^^^^^^^^^^^^^^^ error: aborting due to 2 previous errors diff --git a/src/test/ui/wf/wf-in-foreign-fn-decls-issue-80468.stderr b/src/test/ui/wf/wf-in-foreign-fn-decls-issue-80468.stderr index 16d19872552..f976466841c 100644 --- a/src/test/ui/wf/wf-in-foreign-fn-decls-issue-80468.stderr +++ b/src/test/ui/wf/wf-in-foreign-fn-decls-issue-80468.stderr @@ -25,12 +25,12 @@ note: the anonymous lifetime #1 defined here... --> $DIR/wf-in-foreign-fn-decls-issue-80468.rs:16:5 | LL | pub fn repro(_: Wrapper<Ref>); - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ note: ...does not necessarily outlive the static lifetime introduced by the compatible `impl` --> $DIR/wf-in-foreign-fn-decls-issue-80468.rs:13:1 | LL | impl Trait for Ref {} - | ^^^^^^^^^^^^^^^^^^^^^ + | ^^^^^^^^^^^^^^^^^^ error: aborting due to 2 previous errors diff --git a/src/test/ui/xcrate/xcrate-private-by-default.stderr b/src/test/ui/xcrate/xcrate-private-by-default.stderr index a97f55de5f8..0bdd4002f40 100644 --- a/src/test/ui/xcrate/xcrate-private-by-default.stderr +++ b/src/test/ui/xcrate/xcrate-private-by-default.stderr @@ -8,7 +8,7 @@ note: the static `j` is defined here --> $DIR/auxiliary/static_priv_by_default.rs:47:1 | LL | static j: isize = 0; - | ^^^^^^^^^^^^^^^^^^^^ + | ^^^^^^^^^^^^^^^ error[E0603]: function `k` is private --> $DIR/xcrate-private-by-default.rs:25:29 @@ -32,7 +32,7 @@ note: the unit struct `l` is defined here --> $DIR/auxiliary/static_priv_by_default.rs:49:1 | LL | struct l; - | ^^^^^^^^^ + | ^^^^^^^^ error[E0603]: enum `m` is private --> $DIR/xcrate-private-by-default.rs:29:35 @@ -56,7 +56,7 @@ note: the type alias `n` is defined here --> $DIR/auxiliary/static_priv_by_default.rs:51:1 | LL | type n = isize; - | ^^^^^^^^^^^^^^^ + | ^^^^^^ error[E0603]: module `foo` is private --> $DIR/xcrate-private-by-default.rs:35:29 diff --git a/src/tools/build-manifest/src/main.rs b/src/tools/build-manifest/src/main.rs index 6338e467055..efe3f2b618b 100644 --- a/src/tools/build-manifest/src/main.rs +++ b/src/tools/build-manifest/src/main.rs @@ -184,7 +184,7 @@ static PKG_INSTALLERS: &[&str] = &["x86_64-apple-darwin", "aarch64-apple-darwin" static MINGW: &[&str] = &["i686-pc-windows-gnu", "x86_64-pc-windows-gnu"]; -static NIGHTLY_ONLY_COMPONENTS: &[&str] = &["miri-preview", "rust-analyzer-preview"]; +static NIGHTLY_ONLY_COMPONENTS: &[&str] = &["miri-preview"]; macro_rules! t { ($e:expr) => { @@ -403,6 +403,7 @@ impl Builder { rename("rustfmt", "rustfmt-preview"); rename("clippy", "clippy-preview"); rename("miri", "miri-preview"); + rename("rust-analyzer", "rust-analyzer-preview"); } fn rust_package(&mut self, manifest: &Manifest) -> Package { diff --git a/src/tools/cargo b/src/tools/cargo -Subproject dbff32b27893b899ae2397f3d56d1be111041d5 +Subproject c0bbd42ce5e83fe2a93e817c3f9b955492d3130 diff --git a/src/tools/clippy/.github/workflows/remark.yml b/src/tools/clippy/.github/workflows/remark.yml index ff471207b65..81ef072bbb0 100644 --- a/src/tools/clippy/.github/workflows/remark.yml +++ b/src/tools/clippy/.github/workflows/remark.yml @@ -21,7 +21,7 @@ jobs: - name: Setup Node.js uses: actions/setup-node@v1.4.4 with: - node-version: '12.x' + node-version: '14.x' - name: Install remark run: npm install remark-cli remark-lint remark-lint-maximum-line-length remark-preset-lint-recommended remark-gfm diff --git a/src/tools/clippy/CHANGELOG.md b/src/tools/clippy/CHANGELOG.md index 6aaf12ed932..9bc93c1cb42 100644 --- a/src/tools/clippy/CHANGELOG.md +++ b/src/tools/clippy/CHANGELOG.md @@ -3348,6 +3348,7 @@ Released 2018-09-13 [`debug_assert_with_mut_call`]: https://rust-lang.github.io/rust-clippy/master/index.html#debug_assert_with_mut_call [`decimal_literal_representation`]: https://rust-lang.github.io/rust-clippy/master/index.html#decimal_literal_representation [`declare_interior_mutable_const`]: https://rust-lang.github.io/rust-clippy/master/index.html#declare_interior_mutable_const +[`default_instead_of_iter_empty`]: https://rust-lang.github.io/rust-clippy/master/index.html#default_instead_of_iter_empty [`default_numeric_fallback`]: https://rust-lang.github.io/rust-clippy/master/index.html#default_numeric_fallback [`default_trait_access`]: https://rust-lang.github.io/rust-clippy/master/index.html#default_trait_access [`default_union_representation`]: https://rust-lang.github.io/rust-clippy/master/index.html#default_union_representation @@ -3399,6 +3400,7 @@ Released 2018-09-13 [`expect_fun_call`]: https://rust-lang.github.io/rust-clippy/master/index.html#expect_fun_call [`expect_used`]: https://rust-lang.github.io/rust-clippy/master/index.html#expect_used [`expl_impl_clone_on_copy`]: https://rust-lang.github.io/rust-clippy/master/index.html#expl_impl_clone_on_copy +[`explicit_auto_deref`]: https://rust-lang.github.io/rust-clippy/master/index.html#explicit_auto_deref [`explicit_counter_loop`]: https://rust-lang.github.io/rust-clippy/master/index.html#explicit_counter_loop [`explicit_deref_methods`]: https://rust-lang.github.io/rust-clippy/master/index.html#explicit_deref_methods [`explicit_into_iter_loop`]: https://rust-lang.github.io/rust-clippy/master/index.html#explicit_into_iter_loop @@ -3519,6 +3521,7 @@ Released 2018-09-13 [`manual_async_fn`]: https://rust-lang.github.io/rust-clippy/master/index.html#manual_async_fn [`manual_bits`]: https://rust-lang.github.io/rust-clippy/master/index.html#manual_bits [`manual_filter_map`]: https://rust-lang.github.io/rust-clippy/master/index.html#manual_filter_map +[`manual_find`]: https://rust-lang.github.io/rust-clippy/master/index.html#manual_find [`manual_find_map`]: https://rust-lang.github.io/rust-clippy/master/index.html#manual_find_map [`manual_flatten`]: https://rust-lang.github.io/rust-clippy/master/index.html#manual_flatten [`manual_map`]: https://rust-lang.github.io/rust-clippy/master/index.html#manual_map @@ -3526,6 +3529,8 @@ Released 2018-09-13 [`manual_non_exhaustive`]: https://rust-lang.github.io/rust-clippy/master/index.html#manual_non_exhaustive [`manual_ok_or`]: https://rust-lang.github.io/rust-clippy/master/index.html#manual_ok_or [`manual_range_contains`]: https://rust-lang.github.io/rust-clippy/master/index.html#manual_range_contains +[`manual_rem_euclid`]: https://rust-lang.github.io/rust-clippy/master/index.html#manual_rem_euclid +[`manual_retain`]: https://rust-lang.github.io/rust-clippy/master/index.html#manual_retain [`manual_saturating_arithmetic`]: https://rust-lang.github.io/rust-clippy/master/index.html#manual_saturating_arithmetic [`manual_split_once`]: https://rust-lang.github.io/rust-clippy/master/index.html#manual_split_once [`manual_str_repeat`]: https://rust-lang.github.io/rust-clippy/master/index.html#manual_str_repeat diff --git a/src/tools/clippy/Cargo.toml b/src/tools/clippy/Cargo.toml index e4060ce29a7..644ca6318f6 100644 --- a/src/tools/clippy/Cargo.toml +++ b/src/tools/clippy/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "clippy" -version = "0.1.63" +version = "0.1.64" description = "A bunch of helpful lints to avoid common pitfalls in Rust" repository = "https://github.com/rust-lang/rust-clippy" readme = "README.md" @@ -31,6 +31,7 @@ termize = "0.1" compiletest_rs = { version = "0.8", features = ["tmp"] } tester = "0.9" regex = "1.5" +toml = "0.5" # This is used by the `collect-metadata` alias. filetime = "0.2" diff --git a/src/tools/clippy/README.md b/src/tools/clippy/README.md index edbc626e354..2c3defeaa83 100644 --- a/src/tools/clippy/README.md +++ b/src/tools/clippy/README.md @@ -5,7 +5,7 @@ A collection of lints to catch common mistakes and improve your [Rust](https://github.com/rust-lang/rust) code. -[There are over 500 lints included in this crate!](https://rust-lang.github.io/rust-clippy/master/index.html) +[There are over 550 lints included in this crate!](https://rust-lang.github.io/rust-clippy/master/index.html) Lints are divided into categories, each with a default [lint level](https://doc.rust-lang.org/rustc/lints/levels.html). You can choose how much Clippy is supposed to ~~annoy~~ help you by changing the lint level by category. @@ -214,6 +214,14 @@ specifying the minimum supported Rust version (MSRV) in the clippy configuration msrv = "1.30.0" ``` +Alternatively, the [`rust-version` field](https://doc.rust-lang.org/cargo/reference/manifest.html#the-rust-version-field) +in the `Cargo.toml` can be used. + +```toml +# Cargo.toml +rust-version = "1.30" +``` + The MSRV can also be specified as an inner attribute, like below. ```rust diff --git a/src/tools/clippy/book/src/README.md b/src/tools/clippy/book/src/README.md index de1f70d7e96..d941f8b65e8 100644 --- a/src/tools/clippy/book/src/README.md +++ b/src/tools/clippy/book/src/README.md @@ -6,7 +6,7 @@ A collection of lints to catch common mistakes and improve your [Rust](https://github.com/rust-lang/rust) code. -[There are over 500 lints included in this crate!](https://rust-lang.github.io/rust-clippy/master/index.html) +[There are over 550 lints included in this crate!](https://rust-lang.github.io/rust-clippy/master/index.html) Lints are divided into categories, each with a default [lint level](https://doc.rust-lang.org/rustc/lints/levels.html). You can choose how diff --git a/src/tools/clippy/clippy_dev/Cargo.toml b/src/tools/clippy/clippy_dev/Cargo.toml index b0d470a2124..2ac3b4fe2ed 100644 --- a/src/tools/clippy/clippy_dev/Cargo.toml +++ b/src/tools/clippy/clippy_dev/Cargo.toml @@ -5,7 +5,7 @@ edition = "2021" [dependencies] aho-corasick = "0.7" -clap = "3.1" +clap = "3.2" indoc = "1.0" itertools = "0.10.1" opener = "0.5" diff --git a/src/tools/clippy/clippy_dev/src/main.rs b/src/tools/clippy/clippy_dev/src/main.rs index 2c27a0bcaf9..243a901503f 100644 --- a/src/tools/clippy/clippy_dev/src/main.rs +++ b/src/tools/clippy/clippy_dev/src/main.rs @@ -5,6 +5,7 @@ use clap::{Arg, ArgAction, ArgMatches, Command, PossibleValue}; use clippy_dev::{bless, fmt, lint, new_lint, serve, setup, update_lints}; use indoc::indoc; + fn main() { let matches = get_clap_config(); @@ -85,6 +86,11 @@ fn main() { let uplift = matches.contains_id("uplift"); update_lints::rename(old_name, new_name, uplift); }, + Some(("deprecate", matches)) => { + let name = matches.get_one::<String>("name").unwrap(); + let reason = matches.get_one("reason"); + update_lints::deprecate(name, reason); + }, _ => {}, } } @@ -266,6 +272,18 @@ fn get_clap_config() -> ArgMatches { .long("uplift") .help("This lint will be uplifted into rustc"), ]), + Command::new("deprecate").about("Deprecates the given lint").args([ + Arg::new("name") + .index(1) + .required(true) + .help("The name of the lint to deprecate"), + Arg::new("reason") + .long("reason") + .short('r') + .required(false) + .takes_value(true) + .help("The reason for deprecation"), + ]), ]) .get_matches() } diff --git a/src/tools/clippy/clippy_dev/src/new_lint.rs b/src/tools/clippy/clippy_dev/src/new_lint.rs index 748d73c0801..7d7e760ef44 100644 --- a/src/tools/clippy/clippy_dev/src/new_lint.rs +++ b/src/tools/clippy/clippy_dev/src/new_lint.rs @@ -138,7 +138,7 @@ fn to_camel_case(name: &str) -> String { .collect() } -fn get_stabilization_version() -> String { +pub(crate) fn get_stabilization_version() -> String { fn parse_manifest(contents: &str) -> Option<String> { let version = contents .lines() diff --git a/src/tools/clippy/clippy_dev/src/update_lints.rs b/src/tools/clippy/clippy_dev/src/update_lints.rs index 1bbd9a45b61..2e0659f42d7 100644 --- a/src/tools/clippy/clippy_dev/src/update_lints.rs +++ b/src/tools/clippy/clippy_dev/src/update_lints.rs @@ -1,16 +1,17 @@ +use crate::clippy_project_root; use aho_corasick::AhoCorasickBuilder; -use core::fmt::Write as _; +use indoc::writedoc; use itertools::Itertools; use rustc_lexer::{tokenize, unescape, LiteralKind, TokenKind}; use std::collections::{HashMap, HashSet}; use std::ffi::OsStr; -use std::fs; -use std::io::{self, Read as _, Seek as _, Write as _}; +use std::fmt::Write; +use std::fs::{self, OpenOptions}; +use std::io::{self, Read, Seek, SeekFrom, Write as _}; +use std::ops::Range; use std::path::{Path, PathBuf}; use walkdir::{DirEntry, WalkDir}; -use crate::clippy_project_root; - const GENERATED_FILE_COMMENT: &str = "// This file was generated by `cargo dev update_lints`.\n\ // Use that command to update this file and do not edit by hand.\n\ // Manual edits will be overwritten.\n\n"; @@ -326,6 +327,200 @@ pub fn rename(old_name: &str, new_name: &str, uplift: bool) { println!("note: `cargo uitest` still needs to be run to update the test results"); } +const DEFAULT_DEPRECATION_REASON: &str = "default deprecation note"; +/// Runs the `deprecate` command +/// +/// This does the following: +/// * Adds an entry to `deprecated_lints.rs`. +/// * Removes the lint declaration (and the entire file if applicable) +/// +/// # Panics +/// +/// If a file path could not read from or written to +pub fn deprecate(name: &str, reason: Option<&String>) { + fn finish( + (lints, mut deprecated_lints, renamed_lints): (Vec<Lint>, Vec<DeprecatedLint>, Vec<RenamedLint>), + name: &str, + reason: &str, + ) { + deprecated_lints.push(DeprecatedLint { + name: name.to_string(), + reason: reason.to_string(), + declaration_range: Range::default(), + }); + + generate_lint_files(UpdateMode::Change, &lints, &deprecated_lints, &renamed_lints); + println!("info: `{}` has successfully been deprecated", name); + + if reason == DEFAULT_DEPRECATION_REASON { + println!("note: the deprecation reason must be updated in `clippy_lints/src/deprecated_lints.rs`"); + } + println!("note: you must run `cargo uitest` to update the test results"); + } + + let reason = reason.map_or(DEFAULT_DEPRECATION_REASON, String::as_str); + let name_lower = name.to_lowercase(); + let name_upper = name.to_uppercase(); + + let (mut lints, deprecated_lints, renamed_lints) = gather_all(); + let Some(lint) = lints.iter().find(|l| l.name == name_lower) else { eprintln!("error: failed to find lint `{}`", name); return; }; + + let mod_path = { + let mut mod_path = PathBuf::from(format!("clippy_lints/src/{}", lint.module)); + if mod_path.is_dir() { + mod_path = mod_path.join("mod"); + } + + mod_path.set_extension("rs"); + mod_path + }; + + let deprecated_lints_path = &*clippy_project_root().join("clippy_lints/src/deprecated_lints.rs"); + + if remove_lint_declaration(&name_lower, &mod_path, &mut lints).unwrap_or(false) { + declare_deprecated(&name_upper, deprecated_lints_path, reason).unwrap(); + finish((lints, deprecated_lints, renamed_lints), name, reason); + return; + } + + eprintln!("error: lint not found"); +} + +fn remove_lint_declaration(name: &str, path: &Path, lints: &mut Vec<Lint>) -> io::Result<bool> { + fn remove_lint(name: &str, lints: &mut Vec<Lint>) { + lints.iter().position(|l| l.name == name).map(|pos| lints.remove(pos)); + } + + fn remove_test_assets(name: &str) { + let test_file_stem = format!("tests/ui/{}", name); + let path = Path::new(&test_file_stem); + + // Some lints have their own directories, delete them + if path.is_dir() { + fs::remove_dir_all(path).ok(); + return; + } + + // Remove all related test files + fs::remove_file(path.with_extension("rs")).ok(); + fs::remove_file(path.with_extension("stderr")).ok(); + fs::remove_file(path.with_extension("fixed")).ok(); + } + + fn remove_impl_lint_pass(lint_name_upper: &str, content: &mut String) { + let impl_lint_pass_start = content.find("impl_lint_pass!").unwrap_or_else(|| { + content + .find("declare_lint_pass!") + .unwrap_or_else(|| panic!("failed to find `impl_lint_pass`")) + }); + let mut impl_lint_pass_end = content[impl_lint_pass_start..] + .find(']') + .expect("failed to find `impl_lint_pass` terminator"); + + impl_lint_pass_end += impl_lint_pass_start; + if let Some(lint_name_pos) = content[impl_lint_pass_start..impl_lint_pass_end].find(&lint_name_upper) { + let mut lint_name_end = impl_lint_pass_start + (lint_name_pos + lint_name_upper.len()); + for c in content[lint_name_end..impl_lint_pass_end].chars() { + // Remove trailing whitespace + if c == ',' || c.is_whitespace() { + lint_name_end += 1; + } else { + break; + } + } + + content.replace_range(impl_lint_pass_start + lint_name_pos..lint_name_end, ""); + } + } + + if path.exists() { + if let Some(lint) = lints.iter().find(|l| l.name == name) { + if lint.module == name { + // The lint name is the same as the file, we can just delete the entire file + fs::remove_file(path)?; + } else { + // We can't delete the entire file, just remove the declaration + + if let Some(Some("mod.rs")) = path.file_name().map(OsStr::to_str) { + // Remove clippy_lints/src/some_mod/some_lint.rs + let mut lint_mod_path = path.to_path_buf(); + lint_mod_path.set_file_name(name); + lint_mod_path.set_extension("rs"); + + fs::remove_file(lint_mod_path).ok(); + } + + let mut content = + fs::read_to_string(&path).unwrap_or_else(|_| panic!("failed to read `{}`", path.to_string_lossy())); + + eprintln!( + "warn: you will have to manually remove any code related to `{}` from `{}`", + name, + path.display() + ); + + assert!( + content[lint.declaration_range.clone()].contains(&name.to_uppercase()), + "error: `{}` does not contain lint `{}`'s declaration", + path.display(), + lint.name + ); + + // Remove lint declaration (declare_clippy_lint!) + content.replace_range(lint.declaration_range.clone(), ""); + + // Remove the module declaration (mod xyz;) + let mod_decl = format!("\nmod {};", name); + content = content.replacen(&mod_decl, "", 1); + + remove_impl_lint_pass(&lint.name.to_uppercase(), &mut content); + fs::write(path, content).unwrap_or_else(|_| panic!("failed to write to `{}`", path.to_string_lossy())); + } + + remove_test_assets(name); + remove_lint(name, lints); + return Ok(true); + } + } + + Ok(false) +} + +fn declare_deprecated(name: &str, path: &Path, reason: &str) -> io::Result<()> { + let mut file = OpenOptions::new().write(true).open(path)?; + + file.seek(SeekFrom::End(0))?; + + let version = crate::new_lint::get_stabilization_version(); + let deprecation_reason = if reason == DEFAULT_DEPRECATION_REASON { + "TODO" + } else { + reason + }; + + writedoc!( + file, + " + + declare_deprecated_lint! {{ + /// ### What it does + /// Nothing. This lint has been deprecated. + /// + /// ### Deprecation reason + /// {} + #[clippy::version = \"{}\"] + pub {}, + \"{}\" + }} + + ", + deprecation_reason, + version, + name, + reason, + ) +} + /// Replace substrings if they aren't bordered by identifier characters. Returns `None` if there /// were no replacements. fn replace_ident_like(contents: &str, replacements: &[(&str, &str)]) -> Option<String> { @@ -393,16 +588,18 @@ struct Lint { group: String, desc: String, module: String, + declaration_range: Range<usize>, } impl Lint { #[must_use] - fn new(name: &str, group: &str, desc: &str, module: &str) -> Self { + fn new(name: &str, group: &str, desc: &str, module: &str, declaration_range: Range<usize>) -> Self { Self { name: name.to_lowercase(), group: group.into(), desc: remove_line_splices(desc), module: module.into(), + declaration_range, } } @@ -433,12 +630,14 @@ impl Lint { struct DeprecatedLint { name: String, reason: String, + declaration_range: Range<usize>, } impl DeprecatedLint { - fn new(name: &str, reason: &str) -> Self { + fn new(name: &str, reason: &str, declaration_range: Range<usize>) -> Self { Self { name: name.to_lowercase(), reason: remove_line_splices(reason), + declaration_range, } } } @@ -610,7 +809,11 @@ fn clippy_lints_src_files() -> impl Iterator<Item = (PathBuf, DirEntry)> { macro_rules! match_tokens { ($iter:ident, $($token:ident $({$($fields:tt)*})? $(($capture:ident))?)*) => { { - $($(let $capture =)? if let Some((TokenKind::$token $({$($fields)*})?, _x)) = $iter.next() { + $($(let $capture =)? if let Some(LintDeclSearchResult { + token_kind: TokenKind::$token $({$($fields)*})?, + content: _x, + .. + }) = $iter.next() { _x } else { continue; @@ -621,40 +824,72 @@ macro_rules! match_tokens { } } +struct LintDeclSearchResult<'a> { + token_kind: TokenKind, + content: &'a str, + range: Range<usize>, +} + /// Parse a source file looking for `declare_clippy_lint` macro invocations. fn parse_contents(contents: &str, module: &str, lints: &mut Vec<Lint>) { let mut offset = 0usize; let mut iter = tokenize(contents).map(|t| { let range = offset..offset + t.len; offset = range.end; - (t.kind, &contents[range]) + + LintDeclSearchResult { + token_kind: t.kind, + content: &contents[range.clone()], + range, + } }); - while iter.any(|(kind, s)| kind == TokenKind::Ident && s == "declare_clippy_lint") { + while let Some(LintDeclSearchResult { range, .. }) = iter.find( + |LintDeclSearchResult { + token_kind, content, .. + }| token_kind == &TokenKind::Ident && *content == "declare_clippy_lint", + ) { + let start = range.start; + let mut iter = iter .by_ref() - .filter(|&(kind, _)| !matches!(kind, TokenKind::Whitespace | TokenKind::LineComment { .. })); + .filter(|t| !matches!(t.token_kind, TokenKind::Whitespace | TokenKind::LineComment { .. })); // matches `!{` match_tokens!(iter, Bang OpenBrace); match iter.next() { // #[clippy::version = "version"] pub - Some((TokenKind::Pound, _)) => { + Some(LintDeclSearchResult { + token_kind: TokenKind::Pound, + .. + }) => { match_tokens!(iter, OpenBracket Ident Colon Colon Ident Eq Literal{..} CloseBracket Ident); }, // pub - Some((TokenKind::Ident, _)) => (), + Some(LintDeclSearchResult { + token_kind: TokenKind::Ident, + .. + }) => (), _ => continue, } + let (name, group, desc) = match_tokens!( iter, // LINT_NAME Ident(name) Comma // group, Ident(group) Comma - // "description" } - Literal{..}(desc) CloseBrace + // "description" + Literal{..}(desc) ); - lints.push(Lint::new(name, group, desc, module)); + + if let Some(LintDeclSearchResult { + token_kind: TokenKind::CloseBrace, + range, + .. + }) = iter.next() + { + lints.push(Lint::new(name, group, desc, module, start..range.end)); + } } } @@ -664,12 +899,24 @@ fn parse_deprecated_contents(contents: &str, lints: &mut Vec<DeprecatedLint>) { let mut iter = tokenize(contents).map(|t| { let range = offset..offset + t.len; offset = range.end; - (t.kind, &contents[range]) + + LintDeclSearchResult { + token_kind: t.kind, + content: &contents[range.clone()], + range, + } }); - while iter.any(|(kind, s)| kind == TokenKind::Ident && s == "declare_deprecated_lint") { - let mut iter = iter - .by_ref() - .filter(|&(kind, _)| !matches!(kind, TokenKind::Whitespace | TokenKind::LineComment { .. })); + + while let Some(LintDeclSearchResult { range, .. }) = iter.find( + |LintDeclSearchResult { + token_kind, content, .. + }| token_kind == &TokenKind::Ident && *content == "declare_deprecated_lint", + ) { + let start = range.start; + + let mut iter = iter.by_ref().filter(|LintDeclSearchResult { ref token_kind, .. }| { + !matches!(token_kind, TokenKind::Whitespace | TokenKind::LineComment { .. }) + }); let (name, reason) = match_tokens!( iter, // !{ @@ -680,10 +927,16 @@ fn parse_deprecated_contents(contents: &str, lints: &mut Vec<DeprecatedLint>) { Ident Ident(name) Comma // "description" Literal{kind: LiteralKind::Str{..},..}(reason) - // } - CloseBrace ); - lints.push(DeprecatedLint::new(name, reason)); + + if let Some(LintDeclSearchResult { + token_kind: TokenKind::CloseBrace, + range, + .. + }) = iter.next() + { + lints.push(DeprecatedLint::new(name, reason, start..range.end)); + } } } @@ -693,8 +946,14 @@ fn parse_renamed_contents(contents: &str, lints: &mut Vec<RenamedLint>) { let mut iter = tokenize(line).map(|t| { let range = offset..offset + t.len; offset = range.end; - (t.kind, &line[range]) + + LintDeclSearchResult { + token_kind: t.kind, + content: &line[range.clone()], + range, + } }); + let (old_name, new_name) = match_tokens!( iter, // ("old_name", @@ -844,10 +1103,25 @@ mod tests { "#; let mut result = Vec::new(); parse_contents(CONTENTS, "module_name", &mut result); + for r in &mut result { + r.declaration_range = Range::default(); + } let expected = vec![ - Lint::new("ptr_arg", "style", "\"really long text\"", "module_name"), - Lint::new("doc_markdown", "pedantic", "\"single line\"", "module_name"), + Lint::new( + "ptr_arg", + "style", + "\"really long text\"", + "module_name", + Range::default(), + ), + Lint::new( + "doc_markdown", + "pedantic", + "\"single line\"", + "module_name", + Range::default(), + ), ]; assert_eq!(expected, result); } @@ -865,10 +1139,14 @@ mod tests { let mut result = Vec::new(); parse_deprecated_contents(DEPRECATED_CONTENTS, &mut result); + for r in &mut result { + r.declaration_range = Range::default(); + } let expected = vec![DeprecatedLint::new( "should_assert_eq", "\"`assert!()` will be more flexible with RFC 2011\"", + Range::default(), )]; assert_eq!(expected, result); } @@ -876,15 +1154,34 @@ mod tests { #[test] fn test_usable_lints() { let lints = vec![ - Lint::new("should_assert_eq2", "Not Deprecated", "\"abc\"", "module_name"), - Lint::new("should_assert_eq2", "internal", "\"abc\"", "module_name"), - Lint::new("should_assert_eq2", "internal_style", "\"abc\"", "module_name"), + Lint::new( + "should_assert_eq2", + "Not Deprecated", + "\"abc\"", + "module_name", + Range::default(), + ), + Lint::new( + "should_assert_eq2", + "internal", + "\"abc\"", + "module_name", + Range::default(), + ), + Lint::new( + "should_assert_eq2", + "internal_style", + "\"abc\"", + "module_name", + Range::default(), + ), ]; let expected = vec![Lint::new( "should_assert_eq2", "Not Deprecated", "\"abc\"", "module_name", + Range::default(), )]; assert_eq!(expected, Lint::usable_lints(&lints)); } @@ -892,21 +1189,33 @@ mod tests { #[test] fn test_by_lint_group() { let lints = vec![ - Lint::new("should_assert_eq", "group1", "\"abc\"", "module_name"), - Lint::new("should_assert_eq2", "group2", "\"abc\"", "module_name"), - Lint::new("incorrect_match", "group1", "\"abc\"", "module_name"), + Lint::new("should_assert_eq", "group1", "\"abc\"", "module_name", Range::default()), + Lint::new( + "should_assert_eq2", + "group2", + "\"abc\"", + "module_name", + Range::default(), + ), + Lint::new("incorrect_match", "group1", "\"abc\"", "module_name", Range::default()), ]; let mut expected: HashMap<String, Vec<Lint>> = HashMap::new(); expected.insert( "group1".to_string(), vec![ - Lint::new("should_assert_eq", "group1", "\"abc\"", "module_name"), - Lint::new("incorrect_match", "group1", "\"abc\"", "module_name"), + Lint::new("should_assert_eq", "group1", "\"abc\"", "module_name", Range::default()), + Lint::new("incorrect_match", "group1", "\"abc\"", "module_name", Range::default()), ], ); expected.insert( "group2".to_string(), - vec![Lint::new("should_assert_eq2", "group2", "\"abc\"", "module_name")], + vec![Lint::new( + "should_assert_eq2", + "group2", + "\"abc\"", + "module_name", + Range::default(), + )], ); assert_eq!(expected, Lint::by_lint_group(lints.into_iter())); } @@ -914,8 +1223,12 @@ mod tests { #[test] fn test_gen_deprecated() { let lints = vec![ - DeprecatedLint::new("should_assert_eq", "\"has been superseded by should_assert_eq2\""), - DeprecatedLint::new("another_deprecated", "\"will be removed\""), + DeprecatedLint::new( + "should_assert_eq", + "\"has been superseded by should_assert_eq2\"", + Range::default(), + ), + DeprecatedLint::new("another_deprecated", "\"will be removed\"", Range::default()), ]; let expected = GENERATED_FILE_COMMENT.to_string() @@ -940,9 +1253,9 @@ mod tests { #[test] fn test_gen_lint_group_list() { let lints = vec![ - Lint::new("abc", "group1", "\"abc\"", "module_name"), - Lint::new("should_assert_eq", "group1", "\"abc\"", "module_name"), - Lint::new("internal", "internal_style", "\"abc\"", "module_name"), + Lint::new("abc", "group1", "\"abc\"", "module_name", Range::default()), + Lint::new("should_assert_eq", "group1", "\"abc\"", "module_name", Range::default()), + Lint::new("internal", "internal_style", "\"abc\"", "module_name", Range::default()), ]; let expected = GENERATED_FILE_COMMENT.to_string() + &[ diff --git a/src/tools/clippy/clippy_lints/Cargo.toml b/src/tools/clippy/clippy_lints/Cargo.toml index 4d5bf47833f..79a56dc405d 100644 --- a/src/tools/clippy/clippy_lints/Cargo.toml +++ b/src/tools/clippy/clippy_lints/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "clippy_lints" -version = "0.1.63" +version = "0.1.64" description = "A bunch of helpful lints to avoid common pitfalls in Rust" repository = "https://github.com/rust-lang/rust-clippy" readme = "README.md" @@ -10,7 +10,6 @@ edition = "2021" [dependencies] cargo_metadata = "0.14" -clippy_dev = { path = "../clippy_dev", optional = true } clippy_utils = { path = "../clippy_utils" } if_chain = "1.0" itertools = "0.10.1" @@ -32,7 +31,7 @@ url = { version = "2.2", features = ["serde"] } [features] deny-warnings = ["clippy_utils/deny-warnings"] # build clippy with internal lints enabled, off by default -internal = ["clippy_utils/internal", "serde_json", "tempfile", "clippy_dev"] +internal = ["clippy_utils/internal", "serde_json", "tempfile"] [package.metadata.rust-analyzer] # This crate uses #[feature(rustc_private)] diff --git a/src/tools/clippy/clippy_lints/src/assign_ops.rs b/src/tools/clippy/clippy_lints/src/assign_ops.rs deleted file mode 100644 index f81da2d4223..00000000000 --- a/src/tools/clippy/clippy_lints/src/assign_ops.rs +++ /dev/null @@ -1,235 +0,0 @@ -use clippy_utils::diagnostics::span_lint_and_then; -use clippy_utils::source::snippet_opt; -use clippy_utils::ty::implements_trait; -use clippy_utils::{binop_traits, sugg}; -use clippy_utils::{eq_expr_value, trait_ref_of_method}; -use if_chain::if_chain; -use rustc_errors::Applicability; -use rustc_hir as hir; -use rustc_hir::intravisit::{walk_expr, Visitor}; -use rustc_lint::{LateContext, LateLintPass}; -use rustc_session::{declare_lint_pass, declare_tool_lint}; - -declare_clippy_lint! { - /// ### What it does - /// Checks for `a = a op b` or `a = b commutative_op a` - /// patterns. - /// - /// ### Why is this bad? - /// These can be written as the shorter `a op= b`. - /// - /// ### Known problems - /// While forbidden by the spec, `OpAssign` traits may have - /// implementations that differ from the regular `Op` impl. - /// - /// ### Example - /// ```rust - /// let mut a = 5; - /// let b = 0; - /// // ... - /// - /// a = a + b; - /// ``` - /// - /// Use instead: - /// ```rust - /// let mut a = 5; - /// let b = 0; - /// // ... - /// - /// a += b; - /// ``` - #[clippy::version = "pre 1.29.0"] - pub ASSIGN_OP_PATTERN, - style, - "assigning the result of an operation on a variable to that same variable" -} - -declare_clippy_lint! { - /// ### What it does - /// Checks for `a op= a op b` or `a op= b op a` patterns. - /// - /// ### Why is this bad? - /// Most likely these are bugs where one meant to write `a - /// op= b`. - /// - /// ### Known problems - /// Clippy cannot know for sure if `a op= a op b` should have - /// been `a = a op a op b` or `a = a op b`/`a op= b`. Therefore, it suggests both. - /// If `a op= a op b` is really the correct behavior it should be - /// written as `a = a op a op b` as it's less confusing. - /// - /// ### Example - /// ```rust - /// let mut a = 5; - /// let b = 2; - /// // ... - /// a += a + b; - /// ``` - #[clippy::version = "pre 1.29.0"] - pub MISREFACTORED_ASSIGN_OP, - suspicious, - "having a variable on both sides of an assign op" -} - -declare_lint_pass!(AssignOps => [ASSIGN_OP_PATTERN, MISREFACTORED_ASSIGN_OP]); - -impl<'tcx> LateLintPass<'tcx> for AssignOps { - #[allow(clippy::too_many_lines)] - fn check_expr(&mut self, cx: &LateContext<'tcx>, expr: &'tcx hir::Expr<'_>) { - match &expr.kind { - hir::ExprKind::AssignOp(op, lhs, rhs) => { - if let hir::ExprKind::Binary(binop, l, r) = &rhs.kind { - if op.node != binop.node { - return; - } - // lhs op= l op r - if eq_expr_value(cx, lhs, l) { - lint_misrefactored_assign_op(cx, expr, *op, rhs, lhs, r); - } - // lhs op= l commutative_op r - if is_commutative(op.node) && eq_expr_value(cx, lhs, r) { - lint_misrefactored_assign_op(cx, expr, *op, rhs, lhs, l); - } - } - }, - hir::ExprKind::Assign(assignee, e, _) => { - if let hir::ExprKind::Binary(op, l, r) = &e.kind { - let lint = |assignee: &hir::Expr<'_>, rhs: &hir::Expr<'_>| { - let ty = cx.typeck_results().expr_ty(assignee); - let rty = cx.typeck_results().expr_ty(rhs); - if_chain! { - if let Some((_, lang_item)) = binop_traits(op.node); - if let Ok(trait_id) = cx.tcx.lang_items().require(lang_item); - let parent_fn = cx.tcx.hir().get_parent_item(e.hir_id); - if trait_ref_of_method(cx, parent_fn) - .map_or(true, |t| t.path.res.def_id() != trait_id); - if implements_trait(cx, ty, trait_id, &[rty.into()]); - then { - span_lint_and_then( - cx, - ASSIGN_OP_PATTERN, - expr.span, - "manual implementation of an assign operation", - |diag| { - if let (Some(snip_a), Some(snip_r)) = - (snippet_opt(cx, assignee.span), snippet_opt(cx, rhs.span)) - { - diag.span_suggestion( - expr.span, - "replace it with", - format!("{} {}= {}", snip_a, op.node.as_str(), snip_r), - Applicability::MachineApplicable, - ); - } - }, - ); - } - } - }; - - let mut visitor = ExprVisitor { - assignee, - counter: 0, - cx, - }; - - walk_expr(&mut visitor, e); - - if visitor.counter == 1 { - // a = a op b - if eq_expr_value(cx, assignee, l) { - lint(assignee, r); - } - // a = b commutative_op a - // Limited to primitive type as these ops are know to be commutative - if eq_expr_value(cx, assignee, r) && cx.typeck_results().expr_ty(assignee).is_primitive_ty() { - match op.node { - hir::BinOpKind::Add - | hir::BinOpKind::Mul - | hir::BinOpKind::And - | hir::BinOpKind::Or - | hir::BinOpKind::BitXor - | hir::BinOpKind::BitAnd - | hir::BinOpKind::BitOr => { - lint(assignee, l); - }, - _ => {}, - } - } - } - } - }, - _ => {}, - } - } -} - -fn lint_misrefactored_assign_op( - cx: &LateContext<'_>, - expr: &hir::Expr<'_>, - op: hir::BinOp, - rhs: &hir::Expr<'_>, - assignee: &hir::Expr<'_>, - rhs_other: &hir::Expr<'_>, -) { - span_lint_and_then( - cx, - MISREFACTORED_ASSIGN_OP, - expr.span, - "variable appears on both sides of an assignment operation", - |diag| { - if let (Some(snip_a), Some(snip_r)) = (snippet_opt(cx, assignee.span), snippet_opt(cx, rhs_other.span)) { - let a = &sugg::Sugg::hir(cx, assignee, ".."); - let r = &sugg::Sugg::hir(cx, rhs, ".."); - let long = format!("{} = {}", snip_a, sugg::make_binop(op.node.into(), a, r)); - diag.span_suggestion( - expr.span, - &format!( - "did you mean `{} = {} {} {}` or `{}`? Consider replacing it with", - snip_a, - snip_a, - op.node.as_str(), - snip_r, - long - ), - format!("{} {}= {}", snip_a, op.node.as_str(), snip_r), - Applicability::MaybeIncorrect, - ); - diag.span_suggestion( - expr.span, - "or", - long, - Applicability::MaybeIncorrect, // snippet - ); - } - }, - ); -} - -#[must_use] -fn is_commutative(op: hir::BinOpKind) -> bool { - use rustc_hir::BinOpKind::{ - Add, And, BitAnd, BitOr, BitXor, Div, Eq, Ge, Gt, Le, Lt, Mul, Ne, Or, Rem, Shl, Shr, Sub, - }; - match op { - Add | Mul | And | Or | BitXor | BitAnd | BitOr | Eq | Ne => true, - Sub | Div | Rem | Shl | Shr | Lt | Le | Ge | Gt => false, - } -} - -struct ExprVisitor<'a, 'tcx> { - assignee: &'a hir::Expr<'a>, - counter: u8, - cx: &'a LateContext<'tcx>, -} - -impl<'a, 'tcx> Visitor<'tcx> for ExprVisitor<'a, 'tcx> { - fn visit_expr(&mut self, expr: &'tcx hir::Expr<'_>) { - if eq_expr_value(self.cx, self.assignee, expr) { - self.counter += 1; - } - - walk_expr(self, expr); - } -} diff --git a/src/tools/clippy/clippy_lints/src/attrs.rs b/src/tools/clippy/clippy_lints/src/attrs.rs index ed12ad9c367..4bcbeacf9fe 100644 --- a/src/tools/clippy/clippy_lints/src/attrs.rs +++ b/src/tools/clippy/clippy_lints/src/attrs.rs @@ -78,10 +78,17 @@ declare_clippy_lint! { /// Checks for `extern crate` and `use` items annotated with /// lint attributes. /// - /// This lint permits `#[allow(unused_imports)]`, `#[allow(deprecated)]`, - /// `#[allow(unreachable_pub)]`, `#[allow(clippy::wildcard_imports)]` and - /// `#[allow(clippy::enum_glob_use)]` on `use` items and `#[allow(unused_imports)]` on - /// `extern crate` items with a `#[macro_use]` attribute. + /// This lint permits lint attributes for lints emitted on the items themself. + /// For `use` items these lints are: + /// * deprecated + /// * unreachable_pub + /// * unused_imports + /// * clippy::enum_glob_use + /// * clippy::macro_use_imports + /// * clippy::wildcard_imports + /// + /// For `extern crate` items these lints are: + /// * `unused_imports` on items with `#[macro_use]` /// /// ### Why is this bad? /// Lint attributes have no effect on crate imports. Most @@ -347,7 +354,10 @@ impl<'tcx> LateLintPass<'tcx> for Attributes { || extract_clippy_lint(lint).map_or(false, |s| { matches!( s.as_str(), - "wildcard_imports" | "enum_glob_use" | "redundant_pub_crate", + "wildcard_imports" + | "enum_glob_use" + | "redundant_pub_crate" + | "macro_use_imports", ) }) { diff --git a/src/tools/clippy/clippy_lints/src/booleans.rs b/src/tools/clippy/clippy_lints/src/booleans.rs index e4e122ba6eb..526ee2f891a 100644 --- a/src/tools/clippy/clippy_lints/src/booleans.rs +++ b/src/tools/clippy/clippy_lints/src/booleans.rs @@ -1,4 +1,4 @@ -use clippy_utils::diagnostics::{span_lint_and_sugg, span_lint_and_then}; +use clippy_utils::diagnostics::{span_lint_and_sugg, span_lint_hir_and_then}; use clippy_utils::source::snippet_opt; use clippy_utils::ty::{implements_trait, is_type_diagnostic_item}; use clippy_utils::{eq_expr_value, get_trait_def_id, paths}; @@ -394,9 +394,10 @@ impl<'a, 'tcx> NonminimalBoolVisitor<'a, 'tcx> { continue 'simplified; } if stats.terminals[i] != 0 && simplified_stats.terminals[i] == 0 { - span_lint_and_then( + span_lint_hir_and_then( self.cx, LOGIC_BUG, + e.hir_id, e.span, "this boolean expression contains a logic bug", |diag| { @@ -429,9 +430,10 @@ impl<'a, 'tcx> NonminimalBoolVisitor<'a, 'tcx> { } } let nonminimal_bool_lint = |suggestions: Vec<_>| { - span_lint_and_then( + span_lint_hir_and_then( self.cx, NONMINIMAL_BOOL, + e.hir_id, e.span, "this boolean expression can be simplified", |diag| { diff --git a/src/tools/clippy/clippy_lints/src/default_instead_of_iter_empty.rs b/src/tools/clippy/clippy_lints/src/default_instead_of_iter_empty.rs new file mode 100644 index 00000000000..3c996d3d2ae --- /dev/null +++ b/src/tools/clippy/clippy_lints/src/default_instead_of_iter_empty.rs @@ -0,0 +1,68 @@ +use clippy_utils::diagnostics::span_lint_and_sugg; +use clippy_utils::last_path_segment; +use clippy_utils::source::snippet_with_applicability; +use clippy_utils::{match_def_path, paths}; +use rustc_errors::Applicability; +use rustc_hir::{def, Expr, ExprKind, GenericArg, QPath, TyKind}; +use rustc_lint::{LateContext, LateLintPass}; +use rustc_session::{declare_lint_pass, declare_tool_lint}; + +declare_clippy_lint! { + /// ### What it does + /// It checks for `std::iter::Empty::default()` and suggests replacing it with + /// `std::iter::empty()`. + /// ### Why is this bad? + /// `std::iter::empty()` is the more idiomatic way. + /// ### Example + /// ```rust + /// let _ = std::iter::Empty::<usize>::default(); + /// let iter: std::iter::Empty<usize> = std::iter::Empty::default(); + /// ``` + /// Use instead: + /// ```rust + /// let _ = std::iter::empty::<usize>(); + /// let iter: std::iter::Empty<usize> = std::iter::empty(); + /// ``` + #[clippy::version = "1.63.0"] + pub DEFAULT_INSTEAD_OF_ITER_EMPTY, + style, + "check `std::iter::Empty::default()` and replace with `std::iter::empty()`" +} +declare_lint_pass!(DefaultIterEmpty => [DEFAULT_INSTEAD_OF_ITER_EMPTY]); + +impl<'tcx> LateLintPass<'tcx> for DefaultIterEmpty { + fn check_expr(&mut self, cx: &LateContext<'tcx>, expr: &'tcx Expr<'_>) { + if let ExprKind::Call(iter_expr, []) = &expr.kind + && let ExprKind::Path(QPath::TypeRelative(ty, _)) = &iter_expr.kind + && let TyKind::Path(ty_path) = &ty.kind + && let QPath::Resolved(None, path) = ty_path + && let def::Res::Def(_, def_id) = &path.res + && match_def_path(cx, *def_id, &paths::ITER_EMPTY) + { + let mut applicability = Applicability::MachineApplicable; + let sugg = make_sugg(cx, ty_path, &mut applicability); + span_lint_and_sugg( + cx, + DEFAULT_INSTEAD_OF_ITER_EMPTY, + expr.span, + "`std::iter::empty()` is the more idiomatic way", + "try", + sugg, + applicability, + ); + } + } +} + +fn make_sugg(cx: &LateContext<'_>, ty_path: &rustc_hir::QPath<'_>, applicability: &mut Applicability) -> String { + if let Some(last) = last_path_segment(ty_path).args + && let Some(iter_ty) = last.args.iter().find_map(|arg| match arg { + GenericArg::Type(ty) => Some(ty), + _ => None, + }) + { + format!("std::iter::empty::<{}>()", snippet_with_applicability(cx, iter_ty.span, "..", applicability)) + } else { + "std::iter::empty()".to_owned() + } +} diff --git a/src/tools/clippy/clippy_lints/src/deprecated_lints.rs b/src/tools/clippy/clippy_lints/src/deprecated_lints.rs index 5d5ea0f49c8..9aa5af3190f 100644 --- a/src/tools/clippy/clippy_lints/src/deprecated_lints.rs +++ b/src/tools/clippy/clippy_lints/src/deprecated_lints.rs @@ -1,16 +1,21 @@ -// NOTE: if you add a deprecated lint in this file, please add a corresponding test in -// tests/ui/deprecated.rs +// NOTE: Entries should be created with `cargo dev deprecate` /// This struct fakes the `Lint` declaration that is usually created by `declare_lint!`. This /// enables the simple extraction of the metadata without changing the current deprecation /// declaration. -pub struct ClippyDeprecatedLint; +pub struct ClippyDeprecatedLint { + #[allow(dead_code)] + pub desc: &'static str, +} +#[macro_export] macro_rules! declare_deprecated_lint { - { $(#[$attr:meta])* pub $name: ident, $_reason: expr} => { + { $(#[$attr:meta])* pub $name: ident, $reason: literal} => { $(#[$attr])* #[allow(dead_code)] - pub static $name: ClippyDeprecatedLint = ClippyDeprecatedLint {}; + pub static $name: ClippyDeprecatedLint = ClippyDeprecatedLint { + desc: $reason + }; } } diff --git a/src/tools/clippy/clippy_lints/src/dereference.rs b/src/tools/clippy/clippy_lints/src/dereference.rs index b47441eff37..0f4a2f79ac5 100644 --- a/src/tools/clippy/clippy_lints/src/dereference.rs +++ b/src/tools/clippy/clippy_lints/src/dereference.rs @@ -1,20 +1,24 @@ use clippy_utils::diagnostics::{span_lint_and_sugg, span_lint_hir_and_then}; use clippy_utils::source::{snippet_with_applicability, snippet_with_context}; use clippy_utils::sugg::has_enclosing_paren; -use clippy_utils::ty::peel_mid_ty_refs; -use clippy_utils::{get_parent_expr, get_parent_node, is_lint_allowed, path_to_local}; +use clippy_utils::ty::{expr_sig, peel_mid_ty_refs, variant_of_res}; +use clippy_utils::{get_parent_expr, is_lint_allowed, path_to_local, walk_to_expr_usage}; use rustc_ast::util::parser::{PREC_POSTFIX, PREC_PREFIX}; use rustc_data_structures::fx::FxIndexMap; use rustc_errors::Applicability; +use rustc_hir::intravisit::{walk_ty, Visitor}; use rustc_hir::{ - BindingAnnotation, Body, BodyId, BorrowKind, Destination, Expr, ExprKind, HirId, MatchSource, Mutability, Node, - Pat, PatKind, UnOp, + self as hir, BindingAnnotation, Body, BodyId, BorrowKind, Expr, ExprKind, GenericArg, HirId, ImplItem, + ImplItemKind, Item, ItemKind, Local, MatchSource, Mutability, Node, Pat, PatKind, Path, QPath, TraitItem, + TraitItemKind, TyKind, UnOp, }; +use rustc_infer::infer::TyCtxtInferExt; use rustc_lint::{LateContext, LateLintPass}; use rustc_middle::ty::adjustment::{Adjust, Adjustment, AutoBorrow, AutoBorrowMutability}; -use rustc_middle::ty::{self, Ty, TyCtxt, TypeckResults}; +use rustc_middle::ty::{self, Ty, TyCtxt, TypeVisitable, TypeckResults}; use rustc_session::{declare_tool_lint, impl_lint_pass}; -use rustc_span::{symbol::sym, Span}; +use rustc_span::{symbol::sym, Span, Symbol}; +use rustc_trait_selection::infer::InferCtxtExt; declare_clippy_lint! { /// ### What it does @@ -104,10 +108,34 @@ declare_clippy_lint! { "`ref` binding to a reference" } +declare_clippy_lint! { + /// ### What it does + /// Checks for dereferencing expressions which would be covered by auto-deref. + /// + /// ### Why is this bad? + /// This unnecessarily complicates the code. + /// + /// ### Example + /// ```rust + /// let x = String::new(); + /// let y: &str = &*x; + /// ``` + /// Use instead: + /// ```rust + /// let x = String::new(); + /// let y: &str = &x; + /// ``` + #[clippy::version = "1.60.0"] + pub EXPLICIT_AUTO_DEREF, + complexity, + "dereferencing when the compiler would automatically dereference" +} + impl_lint_pass!(Dereferencing => [ EXPLICIT_DEREF_METHODS, NEEDLESS_BORROW, REF_BINDING_TO_REFERENCE, + EXPLICIT_AUTO_DEREF, ]); #[derive(Default)] @@ -136,6 +164,12 @@ struct StateData { /// Span of the top level expression span: Span, hir_id: HirId, + position: Position, +} + +struct DerefedBorrow { + count: usize, + msg: &'static str, } enum State { @@ -147,11 +181,19 @@ enum State { /// The required mutability target_mut: Mutability, }, - DerefedBorrow { - count: usize, - required_precedence: i8, - msg: &'static str, + DerefedBorrow(DerefedBorrow), + ExplicitDeref { + // Span and id of the top-level deref expression if the parent expression is a borrow. + deref_span_id: Option<(Span, HirId)>, + }, + ExplicitDerefField { + name: Symbol, }, + Reborrow { + deref_span: Span, + deref_hir_id: HirId, + }, + Borrow, } // A reference operation considered by this lint pass @@ -207,13 +249,28 @@ impl<'tcx> LateLintPass<'tcx> for Dereferencing { match (self.state.take(), kind) { (None, kind) => { - let parent = get_parent_node(cx.tcx, expr.hir_id); let expr_ty = typeck.expr_ty(expr); + let (position, adjustments) = walk_parents(cx, expr); match kind { + RefOp::Deref => { + if let Position::FieldAccess(name) = position + && !ty_contains_field(typeck.expr_ty(sub_expr), name) + { + self.state = Some(( + State::ExplicitDerefField { name }, + StateData { span: expr.span, hir_id: expr.hir_id, position }, + )); + } else if position.is_deref_stable() { + self.state = Some(( + State::ExplicitDeref { deref_span_id: None }, + StateData { span: expr.span, hir_id: expr.hir_id, position }, + )); + } + } RefOp::Method(target_mut) if !is_lint_allowed(cx, EXPLICIT_DEREF_METHODS, expr.hir_id) - && is_linted_explicit_deref_position(parent, expr.hir_id, expr.span) => + && position.lint_explicit_deref() => { self.state = Some(( State::DerefMethod { @@ -228,12 +285,13 @@ impl<'tcx> LateLintPass<'tcx> for Dereferencing { StateData { span: expr.span, hir_id: expr.hir_id, + position }, )); }, RefOp::AddrOf => { // Find the number of times the borrow is auto-derefed. - let mut iter = find_adjustments(cx.tcx, typeck, expr).iter(); + let mut iter = adjustments.iter(); let mut deref_count = 0usize; let next_adjust = loop { match iter.next() { @@ -274,40 +332,43 @@ impl<'tcx> LateLintPass<'tcx> for Dereferencing { "this expression creates a reference which is immediately dereferenced by the compiler"; let borrow_msg = "this expression borrows a value the compiler would automatically borrow"; - let (required_refs, required_precedence, msg) = if is_auto_borrow_position(parent, expr.hir_id) - { - (1, PREC_POSTFIX, if deref_count == 1 { borrow_msg } else { deref_msg }) + let (required_refs, msg) = if position.can_auto_borrow() { + (1, if deref_count == 1 { borrow_msg } else { deref_msg }) } else if let Some(&Adjust::Borrow(AutoBorrow::Ref(_, mutability))) = next_adjust.map(|a| &a.kind) { - if matches!(mutability, AutoBorrowMutability::Mut { .. }) - && !is_auto_reborrow_position(parent) + if matches!(mutability, AutoBorrowMutability::Mut { .. }) && !position.is_reborrow_stable() { - (3, 0, deref_msg) + (3, deref_msg) } else { - (2, 0, deref_msg) + (2, deref_msg) } } else { - (2, 0, deref_msg) + (2, deref_msg) }; if deref_count >= required_refs { self.state = Some(( - State::DerefedBorrow { + State::DerefedBorrow(DerefedBorrow { // One of the required refs is for the current borrow expression, the remaining ones // can't be removed without breaking the code. See earlier comment. count: deref_count - required_refs, - required_precedence, msg, - }, + }), + StateData { span: expr.span, hir_id: expr.hir_id, position }, + )); + } else if position.is_deref_stable() { + self.state = Some(( + State::Borrow, StateData { span: expr.span, hir_id: expr.hir_id, + position }, )); } }, - _ => (), + RefOp::Method(..) => (), } }, ( @@ -334,26 +395,90 @@ impl<'tcx> LateLintPass<'tcx> for Dereferencing { data, )); }, + (Some((State::DerefedBorrow(state), data)), RefOp::AddrOf) if state.count != 0 => { + self.state = Some(( + State::DerefedBorrow(DerefedBorrow { + count: state.count - 1, + ..state + }), + data, + )); + }, + (Some((State::DerefedBorrow(state), data)), RefOp::AddrOf) => { + let position = data.position; + report(cx, expr, State::DerefedBorrow(state), data); + if position.is_deref_stable() { + self.state = Some(( + State::Borrow, + StateData { + span: expr.span, + hir_id: expr.hir_id, + position, + }, + )); + } + }, + (Some((State::DerefedBorrow(state), data)), RefOp::Deref) => { + let position = data.position; + report(cx, expr, State::DerefedBorrow(state), data); + if let Position::FieldAccess(name) = position + && !ty_contains_field(typeck.expr_ty(sub_expr), name) + { + self.state = Some(( + State::ExplicitDerefField { name }, + StateData { span: expr.span, hir_id: expr.hir_id, position }, + )); + } else if position.is_deref_stable() { + self.state = Some(( + State::ExplicitDeref { deref_span_id: None }, + StateData { span: expr.span, hir_id: expr.hir_id, position }, + )); + } + }, + + (Some((State::Borrow, data)), RefOp::Deref) => { + if typeck.expr_ty(sub_expr).is_ref() { + self.state = Some(( + State::Reborrow { + deref_span: expr.span, + deref_hir_id: expr.hir_id, + }, + data, + )); + } else { + self.state = Some(( + State::ExplicitDeref { + deref_span_id: Some((expr.span, expr.hir_id)), + }, + data, + )); + } + }, ( Some(( - State::DerefedBorrow { - count, - required_precedence, - msg, + State::Reborrow { + deref_span, + deref_hir_id, }, data, )), - RefOp::AddrOf, - ) if count != 0 => { + RefOp::Deref, + ) => { self.state = Some(( - State::DerefedBorrow { - count: count - 1, - required_precedence, - msg, + State::ExplicitDeref { + deref_span_id: Some((deref_span, deref_hir_id)), }, data, )); }, + (state @ Some((State::ExplicitDeref { .. }, _)), RefOp::Deref) => { + self.state = state; + }, + (Some((State::ExplicitDerefField { name }, data)), RefOp::Deref) + if !ty_contains_field(typeck.expr_ty(sub_expr), name) => + { + self.state = Some((State::ExplicitDerefField { name }, data)); + }, (Some((state, data)), _) => report(cx, expr, state, data), } @@ -473,131 +598,362 @@ fn deref_method_same_type<'tcx>(result_ty: Ty<'tcx>, arg_ty: Ty<'tcx>) -> bool { } } -// Checks whether the parent node is a suitable context for switching from a deref method to the -// deref operator. -fn is_linted_explicit_deref_position(parent: Option<Node<'_>>, child_id: HirId, child_span: Span) -> bool { - let parent = match parent { - Some(Node::Expr(e)) if e.span.ctxt() == child_span.ctxt() => e, - _ => return true, - }; - match parent.kind { - // Leave deref calls in the middle of a method chain. - // e.g. x.deref().foo() - ExprKind::MethodCall(_, [self_arg, ..], _) if self_arg.hir_id == child_id => false, - - // Leave deref calls resulting in a called function - // e.g. (x.deref())() - ExprKind::Call(func_expr, _) if func_expr.hir_id == child_id => false, - - // Makes an ugly suggestion - // e.g. *x.deref() => *&*x - ExprKind::Unary(UnOp::Deref, _) - // Postfix expressions would require parens - | ExprKind::Match(_, _, MatchSource::TryDesugar | MatchSource::AwaitDesugar) - | ExprKind::Field(..) - | ExprKind::Index(..) - | ExprKind::Err => false, - - ExprKind::Box(..) - | ExprKind::ConstBlock(..) - | ExprKind::Array(_) - | ExprKind::Call(..) - | ExprKind::MethodCall(..) - | ExprKind::Tup(..) - | ExprKind::Binary(..) - | ExprKind::Unary(..) - | ExprKind::Lit(..) - | ExprKind::Cast(..) - | ExprKind::Type(..) - | ExprKind::DropTemps(..) - | ExprKind::If(..) - | ExprKind::Loop(..) - | ExprKind::Match(..) - | ExprKind::Let(..) - | ExprKind::Closure{..} - | ExprKind::Block(..) - | ExprKind::Assign(..) - | ExprKind::AssignOp(..) - | ExprKind::Path(..) - | ExprKind::AddrOf(..) - | ExprKind::Break(..) - | ExprKind::Continue(..) - | ExprKind::Ret(..) - | ExprKind::InlineAsm(..) - | ExprKind::Struct(..) - | ExprKind::Repeat(..) - | ExprKind::Yield(..) => true, - } +/// The position of an expression relative to it's parent. +#[derive(Clone, Copy)] +enum Position { + MethodReceiver, + /// The method is defined on a reference type. e.g. `impl Foo for &T` + MethodReceiverRefImpl, + Callee, + FieldAccess(Symbol), + Postfix, + Deref, + /// Any other location which will trigger auto-deref to a specific time. + DerefStable(i8), + /// Any other location which will trigger auto-reborrowing. + ReborrowStable(i8), + Other(i8), } +impl Position { + fn is_deref_stable(self) -> bool { + matches!(self, Self::DerefStable(_)) + } -/// Checks if the given expression is in a position which can be auto-reborrowed. -/// Note: This is only correct assuming auto-deref is already occurring. -fn is_auto_reborrow_position(parent: Option<Node<'_>>) -> bool { - match parent { - Some(Node::Expr(parent)) => matches!(parent.kind, ExprKind::MethodCall(..) | ExprKind::Call(..)), - Some(Node::Local(_)) => true, - _ => false, + fn is_reborrow_stable(self) -> bool { + matches!(self, Self::DerefStable(_) | Self::ReborrowStable(_)) } -} -/// Checks if the given expression is a position which can auto-borrow. -fn is_auto_borrow_position(parent: Option<Node<'_>>, child_id: HirId) -> bool { - if let Some(Node::Expr(parent)) = parent { - match parent.kind { - // ExprKind::MethodCall(_, [self_arg, ..], _) => self_arg.hir_id == child_id, - ExprKind::Field(..) => true, - ExprKind::Call(f, _) => f.hir_id == child_id, - _ => false, - } - } else { - false + fn can_auto_borrow(self) -> bool { + matches!(self, Self::MethodReceiver | Self::FieldAccess(_) | Self::Callee) } -} -/// Adjustments are sometimes made in the parent block rather than the expression itself. -fn find_adjustments<'tcx>( - tcx: TyCtxt<'tcx>, - typeck: &'tcx TypeckResults<'tcx>, - expr: &'tcx Expr<'tcx>, -) -> &'tcx [Adjustment<'tcx>] { - let map = tcx.hir(); - let mut iter = map.parent_iter(expr.hir_id); - let mut prev = expr; + fn lint_explicit_deref(self) -> bool { + matches!(self, Self::Other(_) | Self::DerefStable(_) | Self::ReborrowStable(_)) + } - loop { - match typeck.expr_adjustments(prev) { - [] => (), - a => break a, - }; + fn precedence(self) -> i8 { + match self { + Self::MethodReceiver + | Self::MethodReceiverRefImpl + | Self::Callee + | Self::FieldAccess(_) + | Self::Postfix => PREC_POSTFIX, + Self::Deref => PREC_PREFIX, + Self::DerefStable(p) | Self::ReborrowStable(p) | Self::Other(p) => p, + } + } +} - match iter.next().map(|(_, x)| x) { - Some(Node::Block(_)) => { - if let Some((_, Node::Expr(e))) = iter.next() { - prev = e; +/// Walks up the parent expressions attempting to determine both how stable the auto-deref result +/// is, and which adjustments will be applied to it. Note this will not consider auto-borrow +/// locations as those follow different rules. +#[allow(clippy::too_many_lines)] +fn walk_parents<'tcx>(cx: &LateContext<'tcx>, e: &'tcx Expr<'_>) -> (Position, &'tcx [Adjustment<'tcx>]) { + let mut adjustments = [].as_slice(); + let mut precedence = 0i8; + let ctxt = e.span.ctxt(); + let position = walk_to_expr_usage(cx, e, &mut |parent, child_id| { + // LocalTableInContext returns the wrong lifetime, so go use `expr_adjustments` instead. + if adjustments.is_empty() && let Node::Expr(e) = cx.tcx.hir().get(child_id) { + adjustments = cx.typeck_results().expr_adjustments(e); + } + match parent { + Node::Local(Local { ty: Some(ty), span, .. }) if span.ctxt() == ctxt => { + Some(binding_ty_auto_deref_stability(ty, precedence)) + }, + Node::Item(&Item { + kind: ItemKind::Static(..) | ItemKind::Const(..), + def_id, + span, + .. + }) + | Node::TraitItem(&TraitItem { + kind: TraitItemKind::Const(..), + def_id, + span, + .. + }) + | Node::ImplItem(&ImplItem { + kind: ImplItemKind::Const(..), + def_id, + span, + .. + }) if span.ctxt() == ctxt => { + let ty = cx.tcx.type_of(def_id); + Some(if ty.is_ref() { + Position::DerefStable(precedence) } else { - // This shouldn't happen. Blocks are always contained in an expression. - break &[]; - } + Position::Other(precedence) + }) }, - Some(Node::Expr(&Expr { - kind: ExprKind::Break(Destination { target_id: Ok(id), .. }, _), + + Node::Item(&Item { + kind: ItemKind::Fn(..), + def_id, + span, + .. + }) + | Node::TraitItem(&TraitItem { + kind: TraitItemKind::Fn(..), + def_id, + span, + .. + }) + | Node::ImplItem(&ImplItem { + kind: ImplItemKind::Fn(..), + def_id, + span, .. - })) => { - if let Some(Node::Expr(e)) = map.find(id) { - prev = e; - iter = map.parent_iter(id); + }) if span.ctxt() == ctxt => { + let output = cx.tcx.fn_sig(def_id.to_def_id()).skip_binder().output(); + Some(if !output.is_ref() { + Position::Other(precedence) + } else if output.has_placeholders() || output.has_opaque_types() { + Position::ReborrowStable(precedence) + } else { + Position::DerefStable(precedence) + }) + }, + + Node::Expr(parent) if parent.span.ctxt() == ctxt => match parent.kind { + ExprKind::Ret(_) => { + let output = cx + .tcx + .fn_sig(cx.tcx.hir().body_owner_def_id(cx.enclosing_body.unwrap())) + .skip_binder() + .output(); + Some(if !output.is_ref() { + Position::Other(precedence) + } else if output.has_placeholders() || output.has_opaque_types() { + Position::ReborrowStable(precedence) + } else { + Position::DerefStable(precedence) + }) + }, + ExprKind::Call(func, _) if func.hir_id == child_id => (child_id == e.hir_id).then(|| Position::Callee), + ExprKind::Call(func, args) => args + .iter() + .position(|arg| arg.hir_id == child_id) + .zip(expr_sig(cx, func)) + .and_then(|(i, sig)| sig.input_with_hir(i)) + .map(|(hir_ty, ty)| match hir_ty { + // Type inference for closures can depend on how they're called. Only go by the explicit + // types here. + Some(ty) => binding_ty_auto_deref_stability(ty, precedence), + None => param_auto_deref_stability(ty.skip_binder(), precedence), + }), + ExprKind::MethodCall(_, args, _) => { + let id = cx.typeck_results().type_dependent_def_id(parent.hir_id).unwrap(); + args.iter().position(|arg| arg.hir_id == child_id).map(|i| { + if i == 0 { + // Check for calls to trait methods where the trait is implemented on a reference. + // Two cases need to be handled: + // * `self` methods on `&T` will never have auto-borrow + // * `&self` methods on `&T` can have auto-borrow, but `&self` methods on `T` will take + // priority. + if e.hir_id != child_id { + Position::ReborrowStable(precedence) + } else if let Some(trait_id) = cx.tcx.trait_of_item(id) + && let arg_ty = cx.tcx.erase_regions(cx.typeck_results().expr_ty_adjusted(e)) + && let ty::Ref(_, sub_ty, _) = *arg_ty.kind() + && let subs = cx.typeck_results().node_substs_opt(child_id).unwrap_or_else( + || cx.tcx.mk_substs([].iter()) + ) && let impl_ty = if cx.tcx.fn_sig(id).skip_binder().inputs()[0].is_ref() { + // Trait methods taking `&self` + sub_ty + } else { + // Trait methods taking `self` + arg_ty + } && impl_ty.is_ref() + && cx.tcx.infer_ctxt().enter(|infcx| + infcx + .type_implements_trait(trait_id, impl_ty, subs, cx.param_env) + .must_apply_modulo_regions() + ) + { + Position::MethodReceiverRefImpl + } else { + Position::MethodReceiver + } + } else { + param_auto_deref_stability(cx.tcx.fn_sig(id).skip_binder().inputs()[i], precedence) + } + }) + }, + ExprKind::Struct(path, fields, _) => { + let variant = variant_of_res(cx, cx.qpath_res(path, parent.hir_id)); + fields + .iter() + .find(|f| f.expr.hir_id == child_id) + .zip(variant) + .and_then(|(field, variant)| variant.fields.iter().find(|f| f.name == field.ident.name)) + .map(|field| param_auto_deref_stability(cx.tcx.type_of(field.did), precedence)) + }, + ExprKind::Field(child, name) if child.hir_id == e.hir_id => Some(Position::FieldAccess(name.name)), + ExprKind::Unary(UnOp::Deref, child) if child.hir_id == e.hir_id => Some(Position::Deref), + ExprKind::Match(child, _, MatchSource::TryDesugar | MatchSource::AwaitDesugar) + | ExprKind::Index(child, _) + if child.hir_id == e.hir_id => + { + Some(Position::Postfix) + }, + _ if child_id == e.hir_id => { + precedence = parent.precedence().order(); + None + }, + _ => None, + }, + _ => None, + } + }) + .unwrap_or(Position::Other(precedence)); + (position, adjustments) +} + +// Checks the stability of auto-deref when assigned to a binding with the given explicit type. +// +// e.g. +// let x = Box::new(Box::new(0u32)); +// let y1: &Box<_> = x.deref(); +// let y2: &Box<_> = &x; +// +// Here `y1` and `y2` would resolve to different types, so the type `&Box<_>` is not stable when +// switching to auto-dereferencing. +fn binding_ty_auto_deref_stability(ty: &hir::Ty<'_>, precedence: i8) -> Position { + let TyKind::Rptr(_, ty) = &ty.kind else { + return Position::Other(precedence); + }; + let mut ty = ty; + + loop { + break match ty.ty.kind { + TyKind::Rptr(_, ref ref_ty) => { + ty = ref_ty; + continue; + }, + TyKind::Path( + QPath::TypeRelative(_, path) + | QPath::Resolved( + _, + Path { + segments: [.., path], .. + }, + ), + ) => { + if let Some(args) = path.args + && args.args.iter().any(|arg| match arg { + GenericArg::Infer(_) => true, + GenericArg::Type(ty) => ty_contains_infer(ty), + _ => false, + }) + { + Position::ReborrowStable(precedence) } else { - // This shouldn't happen. The destination should exist. - break &[]; + Position::DerefStable(precedence) } }, - _ => break &[], + TyKind::Slice(_) + | TyKind::Array(..) + | TyKind::BareFn(_) + | TyKind::Never + | TyKind::Tup(_) + | TyKind::Ptr(_) + | TyKind::TraitObject(..) + | TyKind::Path(_) => Position::DerefStable(precedence), + TyKind::OpaqueDef(..) + | TyKind::Infer + | TyKind::Typeof(..) + | TyKind::Err => Position::ReborrowStable(precedence), + }; + } +} + +// Checks whether a type is inferred at some point. +// e.g. `_`, `Box<_>`, `[_]` +fn ty_contains_infer(ty: &hir::Ty<'_>) -> bool { + struct V(bool); + impl Visitor<'_> for V { + fn visit_ty(&mut self, ty: &hir::Ty<'_>) { + if self.0 + || matches!( + ty.kind, + TyKind::OpaqueDef(..) | TyKind::Infer | TyKind::Typeof(_) | TyKind::Err + ) + { + self.0 = true; + } else { + walk_ty(self, ty); + } } + + fn visit_generic_arg(&mut self, arg: &GenericArg<'_>) { + if self.0 || matches!(arg, GenericArg::Infer(_)) { + self.0 = true; + } else if let GenericArg::Type(ty) = arg { + self.visit_ty(ty); + } + } + } + let mut v = V(false); + v.visit_ty(ty); + v.0 +} + +// Checks whether a type is stable when switching to auto dereferencing, +fn param_auto_deref_stability(ty: Ty<'_>, precedence: i8) -> Position { + let ty::Ref(_, mut ty, _) = *ty.kind() else { + return Position::Other(precedence); + }; + + loop { + break match *ty.kind() { + ty::Ref(_, ref_ty, _) => { + ty = ref_ty; + continue; + }, + ty::Infer(_) + | ty::Error(_) + | ty::Param(_) + | ty::Bound(..) + | ty::Opaque(..) + | ty::Placeholder(_) + | ty::Dynamic(..) => Position::ReborrowStable(precedence), + ty::Adt(..) if ty.has_placeholders() || ty.has_param_types_or_consts() => { + Position::ReborrowStable(precedence) + }, + ty::Adt(..) + | ty::Bool + | ty::Char + | ty::Int(_) + | ty::Uint(_) + | ty::Float(_) + | ty::Foreign(_) + | ty::Str + | ty::Array(..) + | ty::Slice(..) + | ty::RawPtr(..) + | ty::FnDef(..) + | ty::FnPtr(_) + | ty::Closure(..) + | ty::Generator(..) + | ty::GeneratorWitness(..) + | ty::Never + | ty::Tuple(_) + | ty::Projection(_) => Position::DerefStable(precedence), + }; + } +} + +fn ty_contains_field(ty: Ty<'_>, name: Symbol) -> bool { + if let ty::Adt(adt, _) = *ty.kind() { + adt.is_struct() && adt.all_fields().any(|f| f.name == name) + } else { + false } } -#[expect(clippy::needless_pass_by_value)] -fn report<'tcx>(cx: &LateContext<'tcx>, expr: &Expr<'tcx>, state: State, data: StateData) { +#[expect(clippy::needless_pass_by_value, clippy::too_many_lines)] +fn report<'tcx>(cx: &LateContext<'tcx>, expr: &'tcx Expr<'_>, state: State, data: StateData) { match state { State::DerefMethod { ty_changed_count, @@ -647,15 +1003,14 @@ fn report<'tcx>(cx: &LateContext<'tcx>, expr: &Expr<'tcx>, state: State, data: S app, ); }, - State::DerefedBorrow { - required_precedence, - msg, - .. - } => { + State::DerefedBorrow(state) => { let mut app = Applicability::MachineApplicable; - let snip = snippet_with_context(cx, expr.span, data.span.ctxt(), "..", &mut app).0; - span_lint_hir_and_then(cx, NEEDLESS_BORROW, data.hir_id, data.span, msg, |diag| { - let sugg = if required_precedence > expr.precedence().order() && !has_enclosing_paren(&snip) { + let (snip, snip_is_macro) = snippet_with_context(cx, expr.span, data.span.ctxt(), "..", &mut app); + span_lint_hir_and_then(cx, NEEDLESS_BORROW, data.hir_id, data.span, state.msg, |diag| { + let sugg = if !snip_is_macro + && expr.precedence().order() < data.position.precedence() + && !has_enclosing_paren(&snip) + { format!("({})", snip) } else { snip.into() @@ -663,6 +1018,48 @@ fn report<'tcx>(cx: &LateContext<'tcx>, expr: &Expr<'tcx>, state: State, data: S diag.span_suggestion(data.span, "change this to", sugg, app); }); }, + State::ExplicitDeref { deref_span_id } => { + let (span, hir_id, precedence) = if let Some((span, hir_id)) = deref_span_id + && !cx.typeck_results().expr_ty(expr).is_ref() + { + (span, hir_id, PREC_PREFIX) + } else { + (data.span, data.hir_id, data.position.precedence()) + }; + span_lint_hir_and_then( + cx, + EXPLICIT_AUTO_DEREF, + hir_id, + span, + "deref which would be done by auto-deref", + |diag| { + let mut app = Applicability::MachineApplicable; + let (snip, snip_is_macro) = snippet_with_context(cx, expr.span, span.ctxt(), "..", &mut app); + let sugg = + if !snip_is_macro && expr.precedence().order() < precedence && !has_enclosing_paren(&snip) { + format!("({})", snip) + } else { + snip.into() + }; + diag.span_suggestion(span, "try this", sugg, app); + }, + ); + }, + State::ExplicitDerefField { .. } => { + span_lint_hir_and_then( + cx, + EXPLICIT_AUTO_DEREF, + data.hir_id, + data.span, + "deref which would be done by auto-deref", + |diag| { + let mut app = Applicability::MachineApplicable; + let snip = snippet_with_context(cx, expr.span, data.span.ctxt(), "..", &mut app).0; + diag.span_suggestion(data.span, "try this", snip.into_owned(), app); + }, + ); + }, + State::Borrow | State::Reborrow { .. } => (), } } diff --git a/src/tools/clippy/clippy_lints/src/double_comparison.rs b/src/tools/clippy/clippy_lints/src/double_comparison.rs deleted file mode 100644 index ee0440e52ff..00000000000 --- a/src/tools/clippy/clippy_lints/src/double_comparison.rs +++ /dev/null @@ -1,96 +0,0 @@ -//! Lint on unnecessary double comparisons. Some examples: - -use clippy_utils::diagnostics::span_lint_and_sugg; -use clippy_utils::eq_expr_value; -use clippy_utils::source::snippet_with_applicability; -use rustc_errors::Applicability; -use rustc_hir::{BinOpKind, Expr, ExprKind}; -use rustc_lint::{LateContext, LateLintPass}; -use rustc_session::{declare_lint_pass, declare_tool_lint}; -use rustc_span::source_map::Span; - -declare_clippy_lint! { - /// ### What it does - /// Checks for double comparisons that could be simplified to a single expression. - /// - /// - /// ### Why is this bad? - /// Readability. - /// - /// ### Example - /// ```rust - /// # let x = 1; - /// # let y = 2; - /// if x == y || x < y {} - /// ``` - /// - /// Use instead: - /// - /// ```rust - /// # let x = 1; - /// # let y = 2; - /// if x <= y {} - /// ``` - #[clippy::version = "pre 1.29.0"] - pub DOUBLE_COMPARISONS, - complexity, - "unnecessary double comparisons that can be simplified" -} - -declare_lint_pass!(DoubleComparisons => [DOUBLE_COMPARISONS]); - -impl<'tcx> DoubleComparisons { - #[expect(clippy::similar_names)] - fn check_binop(cx: &LateContext<'tcx>, op: BinOpKind, lhs: &'tcx Expr<'_>, rhs: &'tcx Expr<'_>, span: Span) { - let (lkind, llhs, lrhs, rkind, rlhs, rrhs) = match (&lhs.kind, &rhs.kind) { - (ExprKind::Binary(lb, llhs, lrhs), ExprKind::Binary(rb, rlhs, rrhs)) => { - (lb.node, llhs, lrhs, rb.node, rlhs, rrhs) - }, - _ => return, - }; - if !(eq_expr_value(cx, llhs, rlhs) && eq_expr_value(cx, lrhs, rrhs)) { - return; - } - macro_rules! lint_double_comparison { - ($op:tt) => {{ - let mut applicability = Applicability::MachineApplicable; - let lhs_str = snippet_with_applicability(cx, llhs.span, "", &mut applicability); - let rhs_str = snippet_with_applicability(cx, lrhs.span, "", &mut applicability); - let sugg = format!("{} {} {}", lhs_str, stringify!($op), rhs_str); - span_lint_and_sugg( - cx, - DOUBLE_COMPARISONS, - span, - "this binary expression can be simplified", - "try", - sugg, - applicability, - ); - }}; - } - #[rustfmt::skip] - match (op, lkind, rkind) { - (BinOpKind::Or, BinOpKind::Eq, BinOpKind::Lt) | (BinOpKind::Or, BinOpKind::Lt, BinOpKind::Eq) => { - lint_double_comparison!(<=); - }, - (BinOpKind::Or, BinOpKind::Eq, BinOpKind::Gt) | (BinOpKind::Or, BinOpKind::Gt, BinOpKind::Eq) => { - lint_double_comparison!(>=); - }, - (BinOpKind::Or, BinOpKind::Lt, BinOpKind::Gt) | (BinOpKind::Or, BinOpKind::Gt, BinOpKind::Lt) => { - lint_double_comparison!(!=); - }, - (BinOpKind::And, BinOpKind::Le, BinOpKind::Ge) | (BinOpKind::And, BinOpKind::Ge, BinOpKind::Le) => { - lint_double_comparison!(==); - }, - _ => (), - }; - } -} - -impl<'tcx> LateLintPass<'tcx> for DoubleComparisons { - fn check_expr(&mut self, cx: &LateContext<'tcx>, expr: &'tcx Expr<'_>) { - if let ExprKind::Binary(ref kind, lhs, rhs) = expr.kind { - Self::check_binop(cx, kind.node, lhs, rhs, expr.span); - } - } -} diff --git a/src/tools/clippy/clippy_lints/src/duration_subsec.rs b/src/tools/clippy/clippy_lints/src/duration_subsec.rs deleted file mode 100644 index d85ace3a279..00000000000 --- a/src/tools/clippy/clippy_lints/src/duration_subsec.rs +++ /dev/null @@ -1,75 +0,0 @@ -use clippy_utils::consts::{constant, Constant}; -use clippy_utils::diagnostics::span_lint_and_sugg; -use clippy_utils::source::snippet_with_applicability; -use clippy_utils::ty::is_type_diagnostic_item; -use if_chain::if_chain; -use rustc_errors::Applicability; -use rustc_hir::{BinOpKind, Expr, ExprKind}; -use rustc_lint::{LateContext, LateLintPass}; -use rustc_session::{declare_lint_pass, declare_tool_lint}; -use rustc_span::source_map::Spanned; -use rustc_span::sym; - -declare_clippy_lint! { - /// ### What it does - /// Checks for calculation of subsecond microseconds or milliseconds - /// from other `Duration` methods. - /// - /// ### Why is this bad? - /// It's more concise to call `Duration::subsec_micros()` or - /// `Duration::subsec_millis()` than to calculate them. - /// - /// ### Example - /// ```rust - /// # use std::time::Duration; - /// # let duration = Duration::new(5, 0); - /// let micros = duration.subsec_nanos() / 1_000; - /// let millis = duration.subsec_nanos() / 1_000_000; - /// ``` - /// - /// Use instead: - /// ```rust - /// # use std::time::Duration; - /// # let duration = Duration::new(5, 0); - /// let micros = duration.subsec_micros(); - /// let millis = duration.subsec_millis(); - /// ``` - #[clippy::version = "pre 1.29.0"] - pub DURATION_SUBSEC, - complexity, - "checks for calculation of subsecond microseconds or milliseconds" -} - -declare_lint_pass!(DurationSubsec => [DURATION_SUBSEC]); - -impl<'tcx> LateLintPass<'tcx> for DurationSubsec { - fn check_expr(&mut self, cx: &LateContext<'tcx>, expr: &'tcx Expr<'_>) { - if_chain! { - if let ExprKind::Binary(Spanned { node: BinOpKind::Div, .. }, left, right) = expr.kind; - if let ExprKind::MethodCall(method_path, args, _) = left.kind; - if is_type_diagnostic_item(cx, cx.typeck_results().expr_ty(&args[0]).peel_refs(), sym::Duration); - if let Some((Constant::Int(divisor), _)) = constant(cx, cx.typeck_results(), right); - then { - let suggested_fn = match (method_path.ident.as_str(), divisor) { - ("subsec_micros", 1_000) | ("subsec_nanos", 1_000_000) => "subsec_millis", - ("subsec_nanos", 1_000) => "subsec_micros", - _ => return, - }; - let mut applicability = Applicability::MachineApplicable; - span_lint_and_sugg( - cx, - DURATION_SUBSEC, - expr.span, - &format!("calling `{}()` is more concise than this calculation", suggested_fn), - "try", - format!( - "{}.{}()", - snippet_with_applicability(cx, args[0].span, "_", &mut applicability), - suggested_fn - ), - applicability, - ); - } - } - } -} diff --git a/src/tools/clippy/clippy_lints/src/enum_variants.rs b/src/tools/clippy/clippy_lints/src/enum_variants.rs index 23b75104570..cd36f9fcd72 100644 --- a/src/tools/clippy/clippy_lints/src/enum_variants.rs +++ b/src/tools/clippy/clippy_lints/src/enum_variants.rs @@ -190,7 +190,7 @@ fn check_variant(cx: &LateContext<'_>, threshold: u64, def: &EnumDef<'_>, item_n .map(|e| *e.0) .collect(); } - let (what, value) = match (pre.is_empty(), post.is_empty()) { + let (what, value) = match (have_no_extra_prefix(&pre), post.is_empty()) { (true, true) => return, (false, _) => ("pre", pre.join("")), (true, false) => { @@ -213,6 +213,11 @@ fn check_variant(cx: &LateContext<'_>, threshold: u64, def: &EnumDef<'_>, item_n } #[must_use] +fn have_no_extra_prefix(prefixes: &[&str]) -> bool { + prefixes.iter().all(|p| p == &"" || p == &"_") +} + +#[must_use] fn to_camel_case(item_name: &str) -> String { let mut s = String::new(); let mut up = true; diff --git a/src/tools/clippy/clippy_lints/src/eq_op.rs b/src/tools/clippy/clippy_lints/src/eq_op.rs deleted file mode 100644 index 2f4c90d07cf..00000000000 --- a/src/tools/clippy/clippy_lints/src/eq_op.rs +++ /dev/null @@ -1,319 +0,0 @@ -use clippy_utils::diagnostics::{multispan_sugg, span_lint, span_lint_and_then}; -use clippy_utils::get_enclosing_block; -use clippy_utils::macros::{find_assert_eq_args, first_node_macro_backtrace}; -use clippy_utils::source::snippet; -use clippy_utils::ty::{implements_trait, is_copy}; -use clippy_utils::{ast_utils::is_useless_with_eq_exprs, eq_expr_value, is_in_test_function}; -use if_chain::if_chain; -use rustc_errors::Applicability; -use rustc_hir::{def::Res, def_id::DefId, BinOpKind, BorrowKind, Expr, ExprKind, GenericArg, ItemKind, QPath, TyKind}; -use rustc_lint::{LateContext, LateLintPass}; -use rustc_middle::ty::{self, Ty}; -use rustc_session::{declare_lint_pass, declare_tool_lint}; - -declare_clippy_lint! { - /// ### What it does - /// Checks for equal operands to comparison, logical and - /// bitwise, difference and division binary operators (`==`, `>`, etc., `&&`, - /// `||`, `&`, `|`, `^`, `-` and `/`). - /// - /// ### Why is this bad? - /// This is usually just a typo or a copy and paste error. - /// - /// ### Known problems - /// False negatives: We had some false positives regarding - /// calls (notably [racer](https://github.com/phildawes/racer) had one instance - /// of `x.pop() && x.pop()`), so we removed matching any function or method - /// calls. We may introduce a list of known pure functions in the future. - /// - /// ### Example - /// ```rust - /// # let x = 1; - /// if x + 1 == x + 1 {} - /// - /// // or - /// - /// # let a = 3; - /// # let b = 4; - /// assert_eq!(a, a); - /// ``` - #[clippy::version = "pre 1.29.0"] - pub EQ_OP, - correctness, - "equal operands on both sides of a comparison or bitwise combination (e.g., `x == x`)" -} - -declare_clippy_lint! { - /// ### What it does - /// Checks for arguments to `==` which have their address - /// taken to satisfy a bound - /// and suggests to dereference the other argument instead - /// - /// ### Why is this bad? - /// It is more idiomatic to dereference the other argument. - /// - /// ### Example - /// ```rust,ignore - /// &x == y - /// ``` - /// - /// Use instead: - /// ```rust,ignore - /// x == *y - /// ``` - #[clippy::version = "pre 1.29.0"] - pub OP_REF, - style, - "taking a reference to satisfy the type constraints on `==`" -} - -declare_lint_pass!(EqOp => [EQ_OP, OP_REF]); - -impl<'tcx> LateLintPass<'tcx> for EqOp { - #[expect(clippy::similar_names, clippy::too_many_lines)] - fn check_expr(&mut self, cx: &LateContext<'tcx>, e: &'tcx Expr<'_>) { - if_chain! { - if let Some((macro_call, macro_name)) = first_node_macro_backtrace(cx, e).find_map(|macro_call| { - let name = cx.tcx.item_name(macro_call.def_id); - matches!(name.as_str(), "assert_eq" | "assert_ne" | "debug_assert_eq" | "debug_assert_ne") - .then(|| (macro_call, name)) - }); - if let Some((lhs, rhs, _)) = find_assert_eq_args(cx, e, macro_call.expn); - if eq_expr_value(cx, lhs, rhs); - if macro_call.is_local(); - if !is_in_test_function(cx.tcx, e.hir_id); - then { - span_lint( - cx, - EQ_OP, - lhs.span.to(rhs.span), - &format!("identical args used in this `{}!` macro call", macro_name), - ); - } - } - if let ExprKind::Binary(op, left, right) = e.kind { - if e.span.from_expansion() { - return; - } - let macro_with_not_op = |expr_kind: &ExprKind<'_>| { - if let ExprKind::Unary(_, expr) = *expr_kind { - expr.span.from_expansion() - } else { - false - } - }; - if macro_with_not_op(&left.kind) || macro_with_not_op(&right.kind) { - return; - } - if is_useless_with_eq_exprs(op.node.into()) - && eq_expr_value(cx, left, right) - && !is_in_test_function(cx.tcx, e.hir_id) - { - span_lint( - cx, - EQ_OP, - e.span, - &format!("equal expressions as operands to `{}`", op.node.as_str()), - ); - return; - } - let (trait_id, requires_ref) = match op.node { - BinOpKind::Add => (cx.tcx.lang_items().add_trait(), false), - BinOpKind::Sub => (cx.tcx.lang_items().sub_trait(), false), - BinOpKind::Mul => (cx.tcx.lang_items().mul_trait(), false), - BinOpKind::Div => (cx.tcx.lang_items().div_trait(), false), - BinOpKind::Rem => (cx.tcx.lang_items().rem_trait(), false), - // don't lint short circuiting ops - BinOpKind::And | BinOpKind::Or => return, - BinOpKind::BitXor => (cx.tcx.lang_items().bitxor_trait(), false), - BinOpKind::BitAnd => (cx.tcx.lang_items().bitand_trait(), false), - BinOpKind::BitOr => (cx.tcx.lang_items().bitor_trait(), false), - BinOpKind::Shl => (cx.tcx.lang_items().shl_trait(), false), - BinOpKind::Shr => (cx.tcx.lang_items().shr_trait(), false), - BinOpKind::Ne | BinOpKind::Eq => (cx.tcx.lang_items().eq_trait(), true), - BinOpKind::Lt | BinOpKind::Le | BinOpKind::Ge | BinOpKind::Gt => { - (cx.tcx.lang_items().partial_ord_trait(), true) - }, - }; - if let Some(trait_id) = trait_id { - match (&left.kind, &right.kind) { - // do not suggest to dereference literals - (&ExprKind::Lit(..), _) | (_, &ExprKind::Lit(..)) => {}, - // &foo == &bar - (&ExprKind::AddrOf(BorrowKind::Ref, _, l), &ExprKind::AddrOf(BorrowKind::Ref, _, r)) => { - let lty = cx.typeck_results().expr_ty(l); - let rty = cx.typeck_results().expr_ty(r); - let lcpy = is_copy(cx, lty); - let rcpy = is_copy(cx, rty); - if let Some((self_ty, other_ty)) = in_impl(cx, e, trait_id) { - if (are_equal(cx, rty, self_ty) && are_equal(cx, lty, other_ty)) - || (are_equal(cx, rty, other_ty) && are_equal(cx, lty, self_ty)) - { - return; // Don't lint - } - } - // either operator autorefs or both args are copyable - if (requires_ref || (lcpy && rcpy)) && implements_trait(cx, lty, trait_id, &[rty.into()]) { - span_lint_and_then( - cx, - OP_REF, - e.span, - "needlessly taken reference of both operands", - |diag| { - let lsnip = snippet(cx, l.span, "...").to_string(); - let rsnip = snippet(cx, r.span, "...").to_string(); - multispan_sugg( - diag, - "use the values directly", - vec![(left.span, lsnip), (right.span, rsnip)], - ); - }, - ); - } else if lcpy - && !rcpy - && implements_trait(cx, lty, trait_id, &[cx.typeck_results().expr_ty(right).into()]) - { - span_lint_and_then( - cx, - OP_REF, - e.span, - "needlessly taken reference of left operand", - |diag| { - let lsnip = snippet(cx, l.span, "...").to_string(); - diag.span_suggestion( - left.span, - "use the left value directly", - lsnip, - Applicability::MaybeIncorrect, // FIXME #2597 - ); - }, - ); - } else if !lcpy - && rcpy - && implements_trait(cx, cx.typeck_results().expr_ty(left), trait_id, &[rty.into()]) - { - span_lint_and_then( - cx, - OP_REF, - e.span, - "needlessly taken reference of right operand", - |diag| { - let rsnip = snippet(cx, r.span, "...").to_string(); - diag.span_suggestion( - right.span, - "use the right value directly", - rsnip, - Applicability::MaybeIncorrect, // FIXME #2597 - ); - }, - ); - } - }, - // &foo == bar - (&ExprKind::AddrOf(BorrowKind::Ref, _, l), _) => { - let lty = cx.typeck_results().expr_ty(l); - if let Some((self_ty, other_ty)) = in_impl(cx, e, trait_id) { - let rty = cx.typeck_results().expr_ty(right); - if (are_equal(cx, rty, self_ty) && are_equal(cx, lty, other_ty)) - || (are_equal(cx, rty, other_ty) && are_equal(cx, lty, self_ty)) - { - return; // Don't lint - } - } - let lcpy = is_copy(cx, lty); - if (requires_ref || lcpy) - && implements_trait(cx, lty, trait_id, &[cx.typeck_results().expr_ty(right).into()]) - { - span_lint_and_then( - cx, - OP_REF, - e.span, - "needlessly taken reference of left operand", - |diag| { - let lsnip = snippet(cx, l.span, "...").to_string(); - diag.span_suggestion( - left.span, - "use the left value directly", - lsnip, - Applicability::MaybeIncorrect, // FIXME #2597 - ); - }, - ); - } - }, - // foo == &bar - (_, &ExprKind::AddrOf(BorrowKind::Ref, _, r)) => { - let rty = cx.typeck_results().expr_ty(r); - if let Some((self_ty, other_ty)) = in_impl(cx, e, trait_id) { - let lty = cx.typeck_results().expr_ty(left); - if (are_equal(cx, rty, self_ty) && are_equal(cx, lty, other_ty)) - || (are_equal(cx, rty, other_ty) && are_equal(cx, lty, self_ty)) - { - return; // Don't lint - } - } - let rcpy = is_copy(cx, rty); - if (requires_ref || rcpy) - && implements_trait(cx, cx.typeck_results().expr_ty(left), trait_id, &[rty.into()]) - { - span_lint_and_then(cx, OP_REF, e.span, "taken reference of right operand", |diag| { - let rsnip = snippet(cx, r.span, "...").to_string(); - diag.span_suggestion( - right.span, - "use the right value directly", - rsnip, - Applicability::MaybeIncorrect, // FIXME #2597 - ); - }); - } - }, - _ => {}, - } - } - } - } -} - -fn in_impl<'tcx>( - cx: &LateContext<'tcx>, - e: &'tcx Expr<'_>, - bin_op: DefId, -) -> Option<(&'tcx rustc_hir::Ty<'tcx>, &'tcx rustc_hir::Ty<'tcx>)> { - if_chain! { - if let Some(block) = get_enclosing_block(cx, e.hir_id); - if let Some(impl_def_id) = cx.tcx.impl_of_method(block.hir_id.owner.to_def_id()); - let item = cx.tcx.hir().expect_item(impl_def_id.expect_local()); - if let ItemKind::Impl(item) = &item.kind; - if let Some(of_trait) = &item.of_trait; - if let Some(seg) = of_trait.path.segments.last(); - if let Some(Res::Def(_, trait_id)) = seg.res; - if trait_id == bin_op; - if let Some(generic_args) = seg.args; - if let Some(GenericArg::Type(other_ty)) = generic_args.args.last(); - - then { - Some((item.self_ty, other_ty)) - } - else { - None - } - } -} - -fn are_equal<'tcx>(cx: &LateContext<'tcx>, middle_ty: Ty<'_>, hir_ty: &rustc_hir::Ty<'_>) -> bool { - if_chain! { - if let ty::Adt(adt_def, _) = middle_ty.kind(); - if let Some(local_did) = adt_def.did().as_local(); - let item = cx.tcx.hir().expect_item(local_did); - let middle_ty_id = item.def_id.to_def_id(); - if let TyKind::Path(QPath::Resolved(_, path)) = hir_ty.kind; - if let Res::Def(_, hir_ty_id) = path.res; - - then { - hir_ty_id == middle_ty_id - } - else { - false - } - } -} diff --git a/src/tools/clippy/clippy_lints/src/erasing_op.rs b/src/tools/clippy/clippy_lints/src/erasing_op.rs deleted file mode 100644 index c1a84973c42..00000000000 --- a/src/tools/clippy/clippy_lints/src/erasing_op.rs +++ /dev/null @@ -1,77 +0,0 @@ -use clippy_utils::consts::{constant_simple, Constant}; -use clippy_utils::diagnostics::span_lint; -use clippy_utils::ty::same_type_and_consts; - -use rustc_hir::{BinOpKind, Expr, ExprKind}; -use rustc_lint::{LateContext, LateLintPass}; -use rustc_middle::ty::TypeckResults; -use rustc_session::{declare_lint_pass, declare_tool_lint}; - -declare_clippy_lint! { - /// ### What it does - /// Checks for erasing operations, e.g., `x * 0`. - /// - /// ### Why is this bad? - /// The whole expression can be replaced by zero. - /// This is most likely not the intended outcome and should probably be - /// corrected - /// - /// ### Example - /// ```rust - /// let x = 1; - /// 0 / x; - /// 0 * x; - /// x & 0; - /// ``` - #[clippy::version = "pre 1.29.0"] - pub ERASING_OP, - correctness, - "using erasing operations, e.g., `x * 0` or `y & 0`" -} - -declare_lint_pass!(ErasingOp => [ERASING_OP]); - -impl<'tcx> LateLintPass<'tcx> for ErasingOp { - fn check_expr(&mut self, cx: &LateContext<'tcx>, e: &'tcx Expr<'_>) { - if e.span.from_expansion() { - return; - } - if let ExprKind::Binary(ref cmp, left, right) = e.kind { - let tck = cx.typeck_results(); - match cmp.node { - BinOpKind::Mul | BinOpKind::BitAnd => { - check(cx, tck, left, right, e); - check(cx, tck, right, left, e); - }, - BinOpKind::Div => check(cx, tck, left, right, e), - _ => (), - } - } - } -} - -fn different_types(tck: &TypeckResults<'_>, input: &Expr<'_>, output: &Expr<'_>) -> bool { - let input_ty = tck.expr_ty(input).peel_refs(); - let output_ty = tck.expr_ty(output).peel_refs(); - !same_type_and_consts(input_ty, output_ty) -} - -fn check<'tcx>( - cx: &LateContext<'tcx>, - tck: &TypeckResults<'tcx>, - op: &Expr<'tcx>, - other: &Expr<'tcx>, - parent: &Expr<'tcx>, -) { - if constant_simple(cx, tck, op) == Some(Constant::Int(0)) { - if different_types(tck, other, parent) { - return; - } - span_lint( - cx, - ERASING_OP, - parent.span, - "this operation will always return zero. This is likely not the intended outcome", - ); - } -} diff --git a/src/tools/clippy/clippy_lints/src/escape.rs b/src/tools/clippy/clippy_lints/src/escape.rs index 9d21dd71e0e..1ac7bfba06b 100644 --- a/src/tools/clippy/clippy_lints/src/escape.rs +++ b/src/tools/clippy/clippy_lints/src/escape.rs @@ -1,7 +1,7 @@ -use clippy_utils::diagnostics::span_lint; +use clippy_utils::diagnostics::span_lint_hir; use clippy_utils::ty::contains_ty; use rustc_hir::intravisit; -use rustc_hir::{self, AssocItemKind, Body, FnDecl, HirId, HirIdSet, Impl, ItemKind, Node}; +use rustc_hir::{self, AssocItemKind, Body, FnDecl, HirId, HirIdSet, Impl, ItemKind, Node, Pat, PatKind}; use rustc_infer::infer::TyCtxtInferExt; use rustc_lint::{LateContext, LateLintPass}; use rustc_middle::mir::FakeReadCause; @@ -118,9 +118,10 @@ impl<'tcx> LateLintPass<'tcx> for BoxedLocal { }); for node in v.set { - span_lint( + span_lint_hir( cx, BOXED_LOCAL, + node, cx.tcx.hir().span(node), "local variable doesn't need to be boxed here", ); @@ -131,7 +132,10 @@ impl<'tcx> LateLintPass<'tcx> for BoxedLocal { // TODO: Replace with Map::is_argument(..) when it's fixed fn is_argument(map: rustc_middle::hir::map::Map<'_>, id: HirId) -> bool { match map.find(id) { - Some(Node::Binding(_)) => (), + Some(Node::Pat(Pat { + kind: PatKind::Binding(..), + .. + })) => (), _ => return false, } @@ -143,15 +147,6 @@ impl<'a, 'tcx> Delegate<'tcx> for EscapeDelegate<'a, 'tcx> { if cmt.place.projections.is_empty() { if let PlaceBase::Local(lid) = cmt.place.base { self.set.remove(&lid); - let map = &self.cx.tcx.hir(); - if let Some(Node::Binding(_)) = map.find(cmt.hir_id) { - if self.set.contains(&lid) { - // let y = x where x is known - // remove x, insert y - self.set.insert(cmt.hir_id); - self.set.remove(&lid); - } - } } } } diff --git a/src/tools/clippy/clippy_lints/src/eta_reduction.rs b/src/tools/clippy/clippy_lints/src/eta_reduction.rs index a5a763c37d1..42fac550ec6 100644 --- a/src/tools/clippy/clippy_lints/src/eta_reduction.rs +++ b/src/tools/clippy/clippy_lints/src/eta_reduction.rs @@ -12,7 +12,7 @@ use rustc_lint::{LateContext, LateLintPass}; use rustc_middle::ty::adjustment::{Adjust, Adjustment, AutoBorrow}; use rustc_middle::ty::binding::BindingMode; use rustc_middle::ty::subst::Subst; -use rustc_middle::ty::{self, ClosureKind, Ty, TypeFoldable}; +use rustc_middle::ty::{self, ClosureKind, Ty, TypeVisitable}; use rustc_session::{declare_lint_pass, declare_tool_lint}; use rustc_span::symbol::sym; diff --git a/src/tools/clippy/clippy_lints/src/explicit_write.rs b/src/tools/clippy/clippy_lints/src/explicit_write.rs index 12d636cf410..5bf4313b41a 100644 --- a/src/tools/clippy/clippy_lints/src/explicit_write.rs +++ b/src/tools/clippy/clippy_lints/src/explicit_write.rs @@ -125,7 +125,7 @@ fn look_in_block<'tcx, 'hir>(cx: &LateContext<'tcx>, kind: &'tcx ExprKind<'hir>) // Find id of the local that expr_end_of_block resolves to if let ExprKind::Path(QPath::Resolved(None, expr_path)) = expr_end_of_block.kind; if let Res::Local(expr_res) = expr_path.res; - if let Some(Node::Binding(res_pat)) = cx.tcx.hir().find(expr_res); + if let Some(Node::Pat(res_pat)) = cx.tcx.hir().find(expr_res); // Find id of the local we found in the block if let PatKind::Binding(BindingAnnotation::Unannotated, local_hir_id, _ident, None) = local.pat.kind; diff --git a/src/tools/clippy/clippy_lints/src/float_equality_without_abs.rs b/src/tools/clippy/clippy_lints/src/float_equality_without_abs.rs deleted file mode 100644 index 98aee7592ae..00000000000 --- a/src/tools/clippy/clippy_lints/src/float_equality_without_abs.rs +++ /dev/null @@ -1,116 +0,0 @@ -use clippy_utils::diagnostics::span_lint_and_then; -use clippy_utils::{match_def_path, paths, sugg}; -use if_chain::if_chain; -use rustc_ast::util::parser::AssocOp; -use rustc_errors::Applicability; -use rustc_hir::def::{DefKind, Res}; -use rustc_hir::{BinOpKind, Expr, ExprKind}; -use rustc_lint::{LateContext, LateLintPass}; -use rustc_middle::ty; -use rustc_session::{declare_lint_pass, declare_tool_lint}; -use rustc_span::source_map::Spanned; - -declare_clippy_lint! { - /// ### What it does - /// Checks for statements of the form `(a - b) < f32::EPSILON` or - /// `(a - b) < f64::EPSILON`. Notes the missing `.abs()`. - /// - /// ### Why is this bad? - /// The code without `.abs()` is more likely to have a bug. - /// - /// ### Known problems - /// If the user can ensure that b is larger than a, the `.abs()` is - /// technically unnecessary. However, it will make the code more robust and doesn't have any - /// large performance implications. If the abs call was deliberately left out for performance - /// reasons, it is probably better to state this explicitly in the code, which then can be done - /// with an allow. - /// - /// ### Example - /// ```rust - /// pub fn is_roughly_equal(a: f32, b: f32) -> bool { - /// (a - b) < f32::EPSILON - /// } - /// ``` - /// Use instead: - /// ```rust - /// pub fn is_roughly_equal(a: f32, b: f32) -> bool { - /// (a - b).abs() < f32::EPSILON - /// } - /// ``` - #[clippy::version = "1.48.0"] - pub FLOAT_EQUALITY_WITHOUT_ABS, - suspicious, - "float equality check without `.abs()`" -} - -declare_lint_pass!(FloatEqualityWithoutAbs => [FLOAT_EQUALITY_WITHOUT_ABS]); - -impl<'tcx> LateLintPass<'tcx> for FloatEqualityWithoutAbs { - fn check_expr(&mut self, cx: &LateContext<'tcx>, expr: &'tcx Expr<'_>) { - let lhs; - let rhs; - - // check if expr is a binary expression with a lt or gt operator - if let ExprKind::Binary(op, left, right) = expr.kind { - match op.node { - BinOpKind::Lt => { - lhs = left; - rhs = right; - }, - BinOpKind::Gt => { - lhs = right; - rhs = left; - }, - _ => return, - }; - } else { - return; - } - - if_chain! { - - // left hand side is a subtraction - if let ExprKind::Binary( - Spanned { - node: BinOpKind::Sub, - .. - }, - val_l, - val_r, - ) = lhs.kind; - - // right hand side matches either f32::EPSILON or f64::EPSILON - if let ExprKind::Path(ref epsilon_path) = rhs.kind; - if let Res::Def(DefKind::AssocConst, def_id) = cx.qpath_res(epsilon_path, rhs.hir_id); - if match_def_path(cx, def_id, &paths::F32_EPSILON) || match_def_path(cx, def_id, &paths::F64_EPSILON); - - // values of the subtractions on the left hand side are of the type float - let t_val_l = cx.typeck_results().expr_ty(val_l); - let t_val_r = cx.typeck_results().expr_ty(val_r); - if let ty::Float(_) = t_val_l.kind(); - if let ty::Float(_) = t_val_r.kind(); - - then { - let sug_l = sugg::Sugg::hir(cx, val_l, ".."); - let sug_r = sugg::Sugg::hir(cx, val_r, ".."); - // format the suggestion - let suggestion = format!("{}.abs()", sugg::make_assoc(AssocOp::Subtract, &sug_l, &sug_r).maybe_par()); - // spans the lint - span_lint_and_then( - cx, - FLOAT_EQUALITY_WITHOUT_ABS, - expr.span, - "float equality check without `.abs()`", - | diag | { - diag.span_suggestion( - lhs.span, - "add `.abs()`", - suggestion, - Applicability::MaybeIncorrect, - ); - } - ); - } - } - } -} diff --git a/src/tools/clippy/clippy_lints/src/implicit_return.rs b/src/tools/clippy/clippy_lints/src/implicit_return.rs index 647947d5d30..a6610ade37e 100644 --- a/src/tools/clippy/clippy_lints/src/implicit_return.rs +++ b/src/tools/clippy/clippy_lints/src/implicit_return.rs @@ -1,5 +1,5 @@ use clippy_utils::{ - diagnostics::span_lint_and_sugg, + diagnostics::span_lint_hir_and_then, get_async_fn_body, is_async_fn, source::{snippet_with_applicability, snippet_with_context, walk_span_to_context}, visitors::expr_visitor_no_bodies, @@ -43,31 +43,38 @@ declare_clippy_lint! { declare_lint_pass!(ImplicitReturn => [IMPLICIT_RETURN]); -fn lint_return(cx: &LateContext<'_>, span: Span) { +fn lint_return(cx: &LateContext<'_>, emission_place: HirId, span: Span) { let mut app = Applicability::MachineApplicable; let snip = snippet_with_applicability(cx, span, "..", &mut app); - span_lint_and_sugg( + span_lint_hir_and_then( cx, IMPLICIT_RETURN, + emission_place, span, "missing `return` statement", - "add `return` as shown", - format!("return {}", snip), - app, + |diag| { + diag.span_suggestion(span, "add `return` as shown", format!("return {}", snip), app); + }, ); } -fn lint_break(cx: &LateContext<'_>, break_span: Span, expr_span: Span) { +fn lint_break(cx: &LateContext<'_>, emission_place: HirId, break_span: Span, expr_span: Span) { let mut app = Applicability::MachineApplicable; let snip = snippet_with_context(cx, expr_span, break_span.ctxt(), "..", &mut app).0; - span_lint_and_sugg( + span_lint_hir_and_then( cx, IMPLICIT_RETURN, + emission_place, break_span, "missing `return` statement", - "change `break` to `return` as shown", - format!("return {}", snip), - app, + |diag| { + diag.span_suggestion( + break_span, + "change `break` to `return` as shown", + format!("return {}", snip), + app, + ); + }, ); } @@ -152,7 +159,7 @@ fn lint_implicit_returns( // At this point sub_expr can be `None` in async functions which either diverge, or return // the unit type. if let Some(sub_expr) = sub_expr { - lint_break(cx, e.span, sub_expr.span); + lint_break(cx, e.hir_id, e.span, sub_expr.span); } } else { // the break expression is from a macro call, add a return to the loop @@ -166,10 +173,10 @@ fn lint_implicit_returns( if add_return { #[expect(clippy::option_if_let_else)] if let Some(span) = call_site_span { - lint_return(cx, span); + lint_return(cx, expr.hir_id, span); LintLocation::Parent } else { - lint_return(cx, expr.span); + lint_return(cx, expr.hir_id, expr.span); LintLocation::Inner } } else { @@ -198,10 +205,10 @@ fn lint_implicit_returns( { #[expect(clippy::option_if_let_else)] if let Some(span) = call_site_span { - lint_return(cx, span); + lint_return(cx, expr.hir_id, span); LintLocation::Parent } else { - lint_return(cx, expr.span); + lint_return(cx, expr.hir_id, expr.span); LintLocation::Inner } }, diff --git a/src/tools/clippy/clippy_lints/src/integer_division.rs b/src/tools/clippy/clippy_lints/src/integer_division.rs deleted file mode 100644 index 3effba56826..00000000000 --- a/src/tools/clippy/clippy_lints/src/integer_division.rs +++ /dev/null @@ -1,61 +0,0 @@ -use clippy_utils::diagnostics::span_lint_and_help; -use if_chain::if_chain; -use rustc_hir as hir; -use rustc_lint::{LateContext, LateLintPass}; -use rustc_session::{declare_lint_pass, declare_tool_lint}; - -declare_clippy_lint! { - /// ### What it does - /// Checks for division of integers - /// - /// ### Why is this bad? - /// When outside of some very specific algorithms, - /// integer division is very often a mistake because it discards the - /// remainder. - /// - /// ### Example - /// ```rust - /// let x = 3 / 2; - /// println!("{}", x); - /// ``` - /// - /// Use instead: - /// ```rust - /// let x = 3f32 / 2f32; - /// println!("{}", x); - /// ``` - #[clippy::version = "1.37.0"] - pub INTEGER_DIVISION, - restriction, - "integer division may cause loss of precision" -} - -declare_lint_pass!(IntegerDivision => [INTEGER_DIVISION]); - -impl<'tcx> LateLintPass<'tcx> for IntegerDivision { - fn check_expr(&mut self, cx: &LateContext<'tcx>, expr: &'tcx hir::Expr<'_>) { - if is_integer_division(cx, expr) { - span_lint_and_help( - cx, - INTEGER_DIVISION, - expr.span, - "integer division", - None, - "division of integers may cause loss of precision. consider using floats", - ); - } - } -} - -fn is_integer_division<'tcx>(cx: &LateContext<'tcx>, expr: &'tcx hir::Expr<'_>) -> bool { - if_chain! { - if let hir::ExprKind::Binary(binop, left, right) = &expr.kind; - if binop.node == hir::BinOpKind::Div; - then { - let (left_ty, right_ty) = (cx.typeck_results().expr_ty(left), cx.typeck_results().expr_ty(right)); - return left_ty.is_integral() && right_ty.is_integral(); - } - } - - false -} diff --git a/src/tools/clippy/clippy_lints/src/large_const_arrays.rs b/src/tools/clippy/clippy_lints/src/large_const_arrays.rs index 289755bfec6..984c5cd4e37 100644 --- a/src/tools/clippy/clippy_lints/src/large_const_arrays.rs +++ b/src/tools/clippy/clippy_lints/src/large_const_arrays.rs @@ -24,7 +24,7 @@ declare_clippy_lint! { /// ``` /// /// Use instead: - /// ```rust.ignore + /// ```rust,ignore /// pub static a = [0u32; 1_000_000]; /// ``` #[clippy::version = "1.44.0"] diff --git a/src/tools/clippy/clippy_lints/src/let_underscore.rs b/src/tools/clippy/clippy_lints/src/let_underscore.rs index 26c540e2223..176787497eb 100644 --- a/src/tools/clippy/clippy_lints/src/let_underscore.rs +++ b/src/tools/clippy/clippy_lints/src/let_underscore.rs @@ -99,12 +99,13 @@ declare_clippy_lint! { declare_lint_pass!(LetUnderscore => [LET_UNDERSCORE_MUST_USE, LET_UNDERSCORE_LOCK, LET_UNDERSCORE_DROP]); -const SYNC_GUARD_PATHS: [&[&str]; 5] = [ +const SYNC_GUARD_PATHS: [&[&str]; 6] = [ &paths::MUTEX_GUARD, &paths::RWLOCK_READ_GUARD, &paths::RWLOCK_WRITE_GUARD, - &paths::PARKING_LOT_RAWMUTEX, - &paths::PARKING_LOT_RAWRWLOCK, + &paths::PARKING_LOT_MUTEX_GUARD, + &paths::PARKING_LOT_RWLOCK_READ_GUARD, + &paths::PARKING_LOT_RWLOCK_WRITE_GUARD, ]; impl<'tcx> LateLintPass<'tcx> for LetUnderscore { diff --git a/src/tools/clippy/clippy_lints/src/lib.register_all.rs b/src/tools/clippy/clippy_lints/src/lib.register_all.rs index 8a2cfbff953..563ad891603 100644 --- a/src/tools/clippy/clippy_lints/src/lib.register_all.rs +++ b/src/tools/clippy/clippy_lints/src/lib.register_all.rs @@ -3,12 +3,9 @@ // Manual edits will be overwritten. store.register_group(true, "clippy::all", Some("clippy_all"), vec![ - LintId::of(absurd_extreme_comparisons::ABSURD_EXTREME_COMPARISONS), LintId::of(almost_complete_letter_range::ALMOST_COMPLETE_LETTER_RANGE), LintId::of(approx_const::APPROX_CONSTANT), LintId::of(assertions_on_constants::ASSERTIONS_ON_CONSTANTS), - LintId::of(assign_ops::ASSIGN_OP_PATTERN), - LintId::of(assign_ops::MISREFACTORED_ASSIGN_OP), LintId::of(async_yields_async::ASYNC_YIELDS_ASYNC), LintId::of(attrs::BLANKET_CLIPPY_RESTRICTION_LINTS), LintId::of(attrs::DEPRECATED_CFG_ATTR), @@ -18,8 +15,6 @@ store.register_group(true, "clippy::all", Some("clippy_all"), vec![ LintId::of(await_holding_invalid::AWAIT_HOLDING_INVALID_TYPE), LintId::of(await_holding_invalid::AWAIT_HOLDING_LOCK), LintId::of(await_holding_invalid::AWAIT_HOLDING_REFCELL_REF), - LintId::of(bit_mask::BAD_BIT_MASK), - LintId::of(bit_mask::INEFFECTIVE_BIT_MASK), LintId::of(blacklisted_name::BLACKLISTED_NAME), LintId::of(blocks_in_if_conditions::BLOCKS_IN_IF_CONDITIONS), LintId::of(bool_assert_comparison::BOOL_ASSERT_COMPARISON), @@ -43,6 +38,8 @@ store.register_group(true, "clippy::all", Some("clippy_all"), vec![ LintId::of(copies::IF_SAME_THEN_ELSE), LintId::of(crate_in_macro_def::CRATE_IN_MACRO_DEF), LintId::of(default::FIELD_REASSIGN_WITH_DEFAULT), + LintId::of(default_instead_of_iter_empty::DEFAULT_INSTEAD_OF_ITER_EMPTY), + LintId::of(dereference::EXPLICIT_AUTO_DEREF), LintId::of(dereference::NEEDLESS_BORROW), LintId::of(derivable_impls::DERIVABLE_IMPLS), LintId::of(derive::DERIVE_HASH_XOR_EQ), @@ -52,7 +49,6 @@ store.register_group(true, "clippy::all", Some("clippy_all"), vec![ LintId::of(disallowed_types::DISALLOWED_TYPES), LintId::of(doc::MISSING_SAFETY_DOC), LintId::of(doc::NEEDLESS_DOCTEST_MAIN), - LintId::of(double_comparison::DOUBLE_COMPARISONS), LintId::of(double_parens::DOUBLE_PARENS), LintId::of(drop_forget_ref::DROP_COPY), LintId::of(drop_forget_ref::DROP_NON_DROP), @@ -62,18 +58,13 @@ store.register_group(true, "clippy::all", Some("clippy_all"), vec![ LintId::of(drop_forget_ref::FORGET_REF), LintId::of(drop_forget_ref::UNDROPPED_MANUALLY_DROPS), LintId::of(duplicate_mod::DUPLICATE_MOD), - LintId::of(duration_subsec::DURATION_SUBSEC), LintId::of(entry::MAP_ENTRY), LintId::of(enum_clike::ENUM_CLIKE_UNPORTABLE_VARIANT), LintId::of(enum_variants::ENUM_VARIANT_NAMES), LintId::of(enum_variants::MODULE_INCEPTION), - LintId::of(eq_op::EQ_OP), - LintId::of(eq_op::OP_REF), - LintId::of(erasing_op::ERASING_OP), LintId::of(escape::BOXED_LOCAL), LintId::of(eta_reduction::REDUNDANT_CLOSURE), LintId::of(explicit_write::EXPLICIT_WRITE), - LintId::of(float_equality_without_abs::FLOAT_EQUALITY_WITHOUT_ABS), LintId::of(float_literal::EXCESSIVE_PRECISION), LintId::of(format::USELESS_FORMAT), LintId::of(format_args::FORMAT_IN_FORMAT_ARGS), @@ -93,7 +84,6 @@ store.register_group(true, "clippy::all", Some("clippy_all"), vec![ LintId::of(functions::RESULT_UNIT_ERR), LintId::of(functions::TOO_MANY_ARGUMENTS), LintId::of(get_first::GET_FIRST), - LintId::of(identity_op::IDENTITY_OP), LintId::of(if_let_mutex::IF_LET_MUTEX), LintId::of(indexing_slicing::OUT_OF_BOUNDS_INDEXING), LintId::of(infinite_iter::INFINITE_ITER), @@ -118,6 +108,7 @@ store.register_group(true, "clippy::all", Some("clippy_all"), vec![ LintId::of(loops::FOR_KV_MAP), LintId::of(loops::FOR_LOOPS_OVER_FALLIBLES), LintId::of(loops::ITER_NEXT_LOOP), + LintId::of(loops::MANUAL_FIND), LintId::of(loops::MANUAL_FLATTEN), LintId::of(loops::MANUAL_MEMCPY), LintId::of(loops::MISSING_SPIN_LOOP), @@ -134,6 +125,8 @@ store.register_group(true, "clippy::all", Some("clippy_all"), vec![ LintId::of(manual_async_fn::MANUAL_ASYNC_FN), LintId::of(manual_bits::MANUAL_BITS), LintId::of(manual_non_exhaustive::MANUAL_NON_EXHAUSTIVE), + LintId::of(manual_rem_euclid::MANUAL_REM_EUCLID), + LintId::of(manual_retain::MANUAL_RETAIN), LintId::of(manual_strip::MANUAL_STRIP), LintId::of(map_clone::MAP_CLONE), LintId::of(map_unit_fn::OPTION_MAP_UNIT_FN), @@ -220,9 +213,6 @@ store.register_group(true, "clippy::all", Some("clippy_all"), vec![ LintId::of(methods::WRONG_SELF_CONVENTION), LintId::of(methods::ZST_OFFSET), LintId::of(minmax::MIN_MAX), - LintId::of(misc::CMP_NAN), - LintId::of(misc::CMP_OWNED), - LintId::of(misc::MODULO_ONE), LintId::of(misc::SHORT_CIRCUIT_STATEMENT), LintId::of(misc::TOPLEVEL_REF_ARG), LintId::of(misc::ZERO_PTR), @@ -256,6 +246,23 @@ store.register_group(true, "clippy::all", Some("clippy_all"), vec![ LintId::of(non_octal_unix_permissions::NON_OCTAL_UNIX_PERMISSIONS), LintId::of(octal_escapes::OCTAL_ESCAPES), LintId::of(open_options::NONSENSICAL_OPEN_OPTIONS), + LintId::of(operators::ABSURD_EXTREME_COMPARISONS), + LintId::of(operators::ASSIGN_OP_PATTERN), + LintId::of(operators::BAD_BIT_MASK), + LintId::of(operators::CMP_NAN), + LintId::of(operators::CMP_OWNED), + LintId::of(operators::DOUBLE_COMPARISONS), + LintId::of(operators::DURATION_SUBSEC), + LintId::of(operators::EQ_OP), + LintId::of(operators::ERASING_OP), + LintId::of(operators::FLOAT_EQUALITY_WITHOUT_ABS), + LintId::of(operators::IDENTITY_OP), + LintId::of(operators::INEFFECTIVE_BIT_MASK), + LintId::of(operators::MISREFACTORED_ASSIGN_OP), + LintId::of(operators::MODULO_ONE), + LintId::of(operators::OP_REF), + LintId::of(operators::PTR_EQ), + LintId::of(operators::SELF_ASSIGNMENT), LintId::of(option_env_unwrap::OPTION_ENV_UNWRAP), LintId::of(overflow_check_conditional::OVERFLOW_CHECK_CONDITIONAL), LintId::of(partialeq_ne_impl::PARTIALEQ_NE_IMPL), @@ -264,7 +271,6 @@ store.register_group(true, "clippy::all", Some("clippy_all"), vec![ LintId::of(ptr::INVALID_NULL_PTR_USAGE), LintId::of(ptr::MUT_FROM_REF), LintId::of(ptr::PTR_ARG), - LintId::of(ptr_eq::PTR_EQ), LintId::of(ptr_offset_with_cast::PTR_OFFSET_WITH_CAST), LintId::of(question_mark::QUESTION_MARK), LintId::of(ranges::MANUAL_RANGE_CONTAINS), @@ -282,7 +288,6 @@ store.register_group(true, "clippy::all", Some("clippy_all"), vec![ LintId::of(repeat_once::REPEAT_ONCE), LintId::of(returns::LET_AND_RETURN), LintId::of(returns::NEEDLESS_RETURN), - LintId::of(self_assignment::SELF_ASSIGNMENT), LintId::of(self_named_constructors::SELF_NAMED_CONSTRUCTORS), LintId::of(serde_api::SERDE_API_MISUSE), LintId::of(single_component_path_imports::SINGLE_COMPONENT_PATH_IMPORTS), diff --git a/src/tools/clippy/clippy_lints/src/lib.register_complexity.rs b/src/tools/clippy/clippy_lints/src/lib.register_complexity.rs index 4f1c3673f85..3784d3c68dc 100644 --- a/src/tools/clippy/clippy_lints/src/lib.register_complexity.rs +++ b/src/tools/clippy/clippy_lints/src/lib.register_complexity.rs @@ -9,21 +9,21 @@ store.register_group(true, "clippy::complexity", Some("clippy_complexity"), vec! LintId::of(bytes_count_to_len::BYTES_COUNT_TO_LEN), LintId::of(casts::CHAR_LIT_AS_U8), LintId::of(casts::UNNECESSARY_CAST), + LintId::of(dereference::EXPLICIT_AUTO_DEREF), LintId::of(derivable_impls::DERIVABLE_IMPLS), - LintId::of(double_comparison::DOUBLE_COMPARISONS), LintId::of(double_parens::DOUBLE_PARENS), - LintId::of(duration_subsec::DURATION_SUBSEC), LintId::of(explicit_write::EXPLICIT_WRITE), LintId::of(format::USELESS_FORMAT), LintId::of(functions::TOO_MANY_ARGUMENTS), - LintId::of(identity_op::IDENTITY_OP), LintId::of(int_plus_one::INT_PLUS_ONE), LintId::of(lifetimes::EXTRA_UNUSED_LIFETIMES), LintId::of(lifetimes::NEEDLESS_LIFETIMES), LintId::of(loops::EXPLICIT_COUNTER_LOOP), + LintId::of(loops::MANUAL_FIND), LintId::of(loops::MANUAL_FLATTEN), LintId::of(loops::SINGLE_ELEMENT_LOOP), LintId::of(loops::WHILE_LET_LOOP), + LintId::of(manual_rem_euclid::MANUAL_REM_EUCLID), LintId::of(manual_strip::MANUAL_STRIP), LintId::of(map_unit_fn::OPTION_MAP_UNIT_FN), LintId::of(map_unit_fn::RESULT_MAP_UNIT_FN), @@ -69,6 +69,9 @@ store.register_group(true, "clippy::complexity", Some("clippy_complexity"), vec! LintId::of(neg_cmp_op_on_partial_ord::NEG_CMP_OP_ON_PARTIAL_ORD), LintId::of(no_effect::NO_EFFECT), LintId::of(no_effect::UNNECESSARY_OPERATION), + LintId::of(operators::DOUBLE_COMPARISONS), + LintId::of(operators::DURATION_SUBSEC), + LintId::of(operators::IDENTITY_OP), LintId::of(overflow_check_conditional::OVERFLOW_CHECK_CONDITIONAL), LintId::of(partialeq_ne_impl::PARTIALEQ_NE_IMPL), LintId::of(precedence::PRECEDENCE), diff --git a/src/tools/clippy/clippy_lints/src/lib.register_correctness.rs b/src/tools/clippy/clippy_lints/src/lib.register_correctness.rs index 92a3a0aabf1..7d5e65cb27a 100644 --- a/src/tools/clippy/clippy_lints/src/lib.register_correctness.rs +++ b/src/tools/clippy/clippy_lints/src/lib.register_correctness.rs @@ -3,14 +3,11 @@ // Manual edits will be overwritten. store.register_group(true, "clippy::correctness", Some("clippy_correctness"), vec![ - LintId::of(absurd_extreme_comparisons::ABSURD_EXTREME_COMPARISONS), LintId::of(approx_const::APPROX_CONSTANT), LintId::of(async_yields_async::ASYNC_YIELDS_ASYNC), LintId::of(attrs::DEPRECATED_SEMVER), LintId::of(attrs::MISMATCHED_TARGET_OS), LintId::of(attrs::USELESS_ATTRIBUTE), - LintId::of(bit_mask::BAD_BIT_MASK), - LintId::of(bit_mask::INEFFECTIVE_BIT_MASK), LintId::of(booleans::LOGIC_BUG), LintId::of(casts::CAST_REF_TO_MUT), LintId::of(casts::CAST_SLICE_DIFFERENT_SIZES), @@ -24,8 +21,6 @@ store.register_group(true, "clippy::correctness", Some("clippy_correctness"), ve LintId::of(drop_forget_ref::FORGET_REF), LintId::of(drop_forget_ref::UNDROPPED_MANUALLY_DROPS), LintId::of(enum_clike::ENUM_CLIKE_UNPORTABLE_VARIANT), - LintId::of(eq_op::EQ_OP), - LintId::of(erasing_op::ERASING_OP), LintId::of(format_impl::RECURSIVE_FORMAT_IMPL), LintId::of(formatting::POSSIBLE_MISSING_COMMA), LintId::of(functions::NOT_UNSAFE_PTR_ARG_DEREF), @@ -47,17 +42,22 @@ store.register_group(true, "clippy::correctness", Some("clippy_correctness"), ve LintId::of(methods::UNINIT_ASSUMED_INIT), LintId::of(methods::ZST_OFFSET), LintId::of(minmax::MIN_MAX), - LintId::of(misc::CMP_NAN), - LintId::of(misc::MODULO_ONE), LintId::of(non_octal_unix_permissions::NON_OCTAL_UNIX_PERMISSIONS), LintId::of(open_options::NONSENSICAL_OPEN_OPTIONS), + LintId::of(operators::ABSURD_EXTREME_COMPARISONS), + LintId::of(operators::BAD_BIT_MASK), + LintId::of(operators::CMP_NAN), + LintId::of(operators::EQ_OP), + LintId::of(operators::ERASING_OP), + LintId::of(operators::INEFFECTIVE_BIT_MASK), + LintId::of(operators::MODULO_ONE), + LintId::of(operators::SELF_ASSIGNMENT), LintId::of(option_env_unwrap::OPTION_ENV_UNWRAP), LintId::of(ptr::INVALID_NULL_PTR_USAGE), LintId::of(ptr::MUT_FROM_REF), LintId::of(ranges::REVERSED_EMPTY_RANGES), LintId::of(read_zero_byte_vec::READ_ZERO_BYTE_VEC), LintId::of(regex::INVALID_REGEX), - LintId::of(self_assignment::SELF_ASSIGNMENT), LintId::of(serde_api::SERDE_API_MISUSE), LintId::of(size_of_in_element_count::SIZE_OF_IN_ELEMENT_COUNT), LintId::of(swap::ALMOST_SWAPPED), diff --git a/src/tools/clippy/clippy_lints/src/lib.register_internal.rs b/src/tools/clippy/clippy_lints/src/lib.register_internal.rs index 4778f4fdfa7..be63646a12f 100644 --- a/src/tools/clippy/clippy_lints/src/lib.register_internal.rs +++ b/src/tools/clippy/clippy_lints/src/lib.register_internal.rs @@ -6,6 +6,7 @@ store.register_group(true, "clippy::internal", Some("clippy_internal"), vec![ LintId::of(utils::internal_lints::CLIPPY_LINTS_INTERNAL), LintId::of(utils::internal_lints::COLLAPSIBLE_SPAN_LINT_CALLS), LintId::of(utils::internal_lints::COMPILER_LINT_FUNCTIONS), + LintId::of(utils::internal_lints::DEFAULT_DEPRECATION_REASON), LintId::of(utils::internal_lints::DEFAULT_LINT), LintId::of(utils::internal_lints::IF_CHAIN_STYLE), LintId::of(utils::internal_lints::INTERNING_DEFINED_SYMBOL), diff --git a/src/tools/clippy/clippy_lints/src/lib.register_lints.rs b/src/tools/clippy/clippy_lints/src/lib.register_lints.rs index 8ad984c68b8..d3c75f8b519 100644 --- a/src/tools/clippy/clippy_lints/src/lib.register_lints.rs +++ b/src/tools/clippy/clippy_lints/src/lib.register_lints.rs @@ -10,6 +10,8 @@ store.register_lints(&[ #[cfg(feature = "internal")] utils::internal_lints::COMPILER_LINT_FUNCTIONS, #[cfg(feature = "internal")] + utils::internal_lints::DEFAULT_DEPRECATION_REASON, + #[cfg(feature = "internal")] utils::internal_lints::DEFAULT_LINT, #[cfg(feature = "internal")] utils::internal_lints::IF_CHAIN_STYLE, @@ -33,7 +35,6 @@ store.register_lints(&[ utils::internal_lints::PRODUCE_ICE, #[cfg(feature = "internal")] utils::internal_lints::UNNECESSARY_SYMBOL_STR, - absurd_extreme_comparisons::ABSURD_EXTREME_COMPARISONS, almost_complete_letter_range::ALMOST_COMPLETE_LETTER_RANGE, approx_const::APPROX_CONSTANT, as_conversions::AS_CONVERSIONS, @@ -41,8 +42,6 @@ store.register_lints(&[ asm_syntax::INLINE_ASM_X86_ATT_SYNTAX, asm_syntax::INLINE_ASM_X86_INTEL_SYNTAX, assertions_on_constants::ASSERTIONS_ON_CONSTANTS, - assign_ops::ASSIGN_OP_PATTERN, - assign_ops::MISREFACTORED_ASSIGN_OP, async_yields_async::ASYNC_YIELDS_ASYNC, attrs::ALLOW_ATTRIBUTES_WITHOUT_REASON, attrs::BLANKET_CLIPPY_RESTRICTION_LINTS, @@ -55,9 +54,6 @@ store.register_lints(&[ await_holding_invalid::AWAIT_HOLDING_INVALID_TYPE, await_holding_invalid::AWAIT_HOLDING_LOCK, await_holding_invalid::AWAIT_HOLDING_REFCELL_REF, - bit_mask::BAD_BIT_MASK, - bit_mask::INEFFECTIVE_BIT_MASK, - bit_mask::VERBOSE_BIT_MASK, blacklisted_name::BLACKLISTED_NAME, blocks_in_if_conditions::BLOCKS_IN_IF_CONDITIONS, bool_assert_comparison::BOOL_ASSERT_COMPARISON, @@ -105,8 +101,10 @@ store.register_lints(&[ dbg_macro::DBG_MACRO, default::DEFAULT_TRAIT_ACCESS, default::FIELD_REASSIGN_WITH_DEFAULT, + default_instead_of_iter_empty::DEFAULT_INSTEAD_OF_ITER_EMPTY, default_numeric_fallback::DEFAULT_NUMERIC_FALLBACK, default_union_representation::DEFAULT_UNION_REPRESENTATION, + dereference::EXPLICIT_AUTO_DEREF, dereference::EXPLICIT_DEREF_METHODS, dereference::NEEDLESS_BORROW, dereference::REF_BINDING_TO_REFERENCE, @@ -125,7 +123,6 @@ store.register_lints(&[ doc::MISSING_SAFETY_DOC, doc::NEEDLESS_DOCTEST_MAIN, doc_link_with_quotes::DOC_LINK_WITH_QUOTES, - double_comparison::DOUBLE_COMPARISONS, double_parens::DOUBLE_PARENS, drop_forget_ref::DROP_COPY, drop_forget_ref::DROP_NON_DROP, @@ -135,7 +132,6 @@ store.register_lints(&[ drop_forget_ref::FORGET_REF, drop_forget_ref::UNDROPPED_MANUALLY_DROPS, duplicate_mod::DUPLICATE_MOD, - duration_subsec::DURATION_SUBSEC, else_if_without_else::ELSE_IF_WITHOUT_ELSE, empty_drop::EMPTY_DROP, empty_enum::EMPTY_ENUM, @@ -145,10 +141,7 @@ store.register_lints(&[ enum_variants::ENUM_VARIANT_NAMES, enum_variants::MODULE_INCEPTION, enum_variants::MODULE_NAME_REPETITIONS, - eq_op::EQ_OP, - eq_op::OP_REF, equatable_if_let::EQUATABLE_IF_LET, - erasing_op::ERASING_OP, escape::BOXED_LOCAL, eta_reduction::REDUNDANT_CLOSURE, eta_reduction::REDUNDANT_CLOSURE_FOR_METHOD_CALLS, @@ -159,7 +152,6 @@ store.register_lints(&[ exit::EXIT, explicit_write::EXPLICIT_WRITE, fallible_impl_from::FALLIBLE_IMPL_FROM, - float_equality_without_abs::FLOAT_EQUALITY_WITHOUT_ABS, float_literal::EXCESSIVE_PRECISION, float_literal::LOSSY_FLOAT_LITERAL, floating_point_arithmetic::IMPRECISE_FLOPS, @@ -185,7 +177,6 @@ store.register_lints(&[ functions::TOO_MANY_LINES, future_not_send::FUTURE_NOT_SEND, get_first::GET_FIRST, - identity_op::IDENTITY_OP, if_let_mutex::IF_LET_MUTEX, if_not_else::IF_NOT_ELSE, if_then_some_else_none::IF_THEN_SOME_ELSE_NONE, @@ -204,7 +195,6 @@ store.register_lints(&[ init_numbered_fields::INIT_NUMBERED_FIELDS, inline_fn_without_body::INLINE_FN_WITHOUT_BODY, int_plus_one::INT_PLUS_ONE, - integer_division::INTEGER_DIVISION, invalid_upcast_comparisons::INVALID_UPCAST_COMPARISONS, items_after_statements::ITEMS_AFTER_STATEMENTS, iter_not_returning_iterator::ITER_NOT_RETURNING_ITERATOR, @@ -234,6 +224,7 @@ store.register_lints(&[ loops::FOR_KV_MAP, loops::FOR_LOOPS_OVER_FALLIBLES, loops::ITER_NEXT_LOOP, + loops::MANUAL_FIND, loops::MANUAL_FLATTEN, loops::MANUAL_MEMCPY, loops::MISSING_SPIN_LOOP, @@ -253,6 +244,8 @@ store.register_lints(&[ manual_bits::MANUAL_BITS, manual_non_exhaustive::MANUAL_NON_EXHAUSTIVE, manual_ok_or::MANUAL_OK_OR, + manual_rem_euclid::MANUAL_REM_EUCLID, + manual_retain::MANUAL_RETAIN, manual_strip::MANUAL_STRIP, map_clone::MAP_CLONE, map_err_ignore::MAP_ERR_IGNORE, @@ -364,11 +357,6 @@ store.register_lints(&[ methods::WRONG_SELF_CONVENTION, methods::ZST_OFFSET, minmax::MIN_MAX, - misc::CMP_NAN, - misc::CMP_OWNED, - misc::FLOAT_CMP, - misc::FLOAT_CMP_CONST, - misc::MODULO_ONE, misc::SHORT_CIRCUIT_STATEMENT, misc::TOPLEVEL_REF_ARG, misc::USED_UNDERSCORE_BINDING, @@ -392,7 +380,6 @@ store.register_lints(&[ mixed_read_write_in_expression::MIXED_READ_WRITE_IN_EXPRESSION, module_style::MOD_MODULE_FILES, module_style::SELF_NAMED_MODULE_FILES, - modulo_arithmetic::MODULO_ARITHMETIC, mut_key::MUTABLE_KEY_TYPE, mut_mut::MUT_MUT, mut_mutex_lock::MUT_MUTEX_LOCK, @@ -401,7 +388,6 @@ store.register_lints(&[ mutex_atomic::MUTEX_ATOMIC, mutex_atomic::MUTEX_INTEGER, needless_arbitrary_self_type::NEEDLESS_ARBITRARY_SELF_TYPE, - needless_bitwise_bool::NEEDLESS_BITWISE_BOOL, needless_bool::BOOL_COMPARISON, needless_bool::NEEDLESS_BOOL, needless_borrowed_ref::NEEDLESS_BORROWED_REFERENCE, @@ -426,11 +412,34 @@ store.register_lints(&[ non_octal_unix_permissions::NON_OCTAL_UNIX_PERMISSIONS, non_send_fields_in_send_ty::NON_SEND_FIELDS_IN_SEND_TY, nonstandard_macro_braces::NONSTANDARD_MACRO_BRACES, - numeric_arithmetic::FLOAT_ARITHMETIC, - numeric_arithmetic::INTEGER_ARITHMETIC, octal_escapes::OCTAL_ESCAPES, only_used_in_recursion::ONLY_USED_IN_RECURSION, open_options::NONSENSICAL_OPEN_OPTIONS, + operators::ABSURD_EXTREME_COMPARISONS, + operators::ASSIGN_OP_PATTERN, + operators::BAD_BIT_MASK, + operators::CMP_NAN, + operators::CMP_OWNED, + operators::DOUBLE_COMPARISONS, + operators::DURATION_SUBSEC, + operators::EQ_OP, + operators::ERASING_OP, + operators::FLOAT_ARITHMETIC, + operators::FLOAT_CMP, + operators::FLOAT_CMP_CONST, + operators::FLOAT_EQUALITY_WITHOUT_ABS, + operators::IDENTITY_OP, + operators::INEFFECTIVE_BIT_MASK, + operators::INTEGER_ARITHMETIC, + operators::INTEGER_DIVISION, + operators::MISREFACTORED_ASSIGN_OP, + operators::MODULO_ARITHMETIC, + operators::MODULO_ONE, + operators::NEEDLESS_BITWISE_BOOL, + operators::OP_REF, + operators::PTR_EQ, + operators::SELF_ASSIGNMENT, + operators::VERBOSE_BIT_MASK, option_env_unwrap::OPTION_ENV_UNWRAP, option_if_let_else::OPTION_IF_LET_ELSE, overflow_check_conditional::OVERFLOW_CHECK_CONDITIONAL, @@ -449,7 +458,6 @@ store.register_lints(&[ ptr::INVALID_NULL_PTR_USAGE, ptr::MUT_FROM_REF, ptr::PTR_ARG, - ptr_eq::PTR_EQ, ptr_offset_with_cast::PTR_OFFSET_WITH_CAST, pub_use::PUB_USE, question_mark::QUESTION_MARK, @@ -477,7 +485,6 @@ store.register_lints(&[ returns::LET_AND_RETURN, returns::NEEDLESS_RETURN, same_name_method::SAME_NAME_METHOD, - self_assignment::SELF_ASSIGNMENT, self_named_constructors::SELF_NAMED_CONSTRUCTORS, semicolon_if_nothing_returned::SEMICOLON_IF_NOTHING_RETURNED, serde_api::SERDE_API_MISUSE, diff --git a/src/tools/clippy/clippy_lints/src/lib.register_pedantic.rs b/src/tools/clippy/clippy_lints/src/lib.register_pedantic.rs index 48de92ae945..a1b54665814 100644 --- a/src/tools/clippy/clippy_lints/src/lib.register_pedantic.rs +++ b/src/tools/clippy/clippy_lints/src/lib.register_pedantic.rs @@ -4,7 +4,6 @@ store.register_group(true, "clippy::pedantic", Some("clippy_pedantic"), vec![ LintId::of(attrs::INLINE_ALWAYS), - LintId::of(bit_mask::VERBOSE_BIT_MASK), LintId::of(borrow_as_ptr::BORROW_AS_PTR), LintId::of(bytecount::NAIVE_BYTECOUNT), LintId::of(case_sensitive_file_extension_comparisons::CASE_SENSITIVE_FILE_EXTENSION_COMPARISONS), @@ -65,17 +64,18 @@ store.register_group(true, "clippy::pedantic", Some("clippy_pedantic"), vec![ LintId::of(methods::INEFFICIENT_TO_STRING), LintId::of(methods::MAP_UNWRAP_OR), LintId::of(methods::UNNECESSARY_JOIN), - LintId::of(misc::FLOAT_CMP), LintId::of(misc::USED_UNDERSCORE_BINDING), LintId::of(mismatching_type_param_order::MISMATCHING_TYPE_PARAM_ORDER), LintId::of(mut_mut::MUT_MUT), - LintId::of(needless_bitwise_bool::NEEDLESS_BITWISE_BOOL), LintId::of(needless_continue::NEEDLESS_CONTINUE), LintId::of(needless_for_each::NEEDLESS_FOR_EACH), LintId::of(needless_pass_by_value::NEEDLESS_PASS_BY_VALUE), LintId::of(no_effect::NO_EFFECT_UNDERSCORE_BINDING), LintId::of(non_expressive_names::MANY_SINGLE_CHAR_NAMES), LintId::of(non_expressive_names::SIMILAR_NAMES), + LintId::of(operators::FLOAT_CMP), + LintId::of(operators::NEEDLESS_BITWISE_BOOL), + LintId::of(operators::VERBOSE_BIT_MASK), LintId::of(pass_by_ref_or_value::LARGE_TYPES_PASSED_BY_VALUE), LintId::of(pass_by_ref_or_value::TRIVIALLY_COPY_PASS_BY_REF), LintId::of(ranges::RANGE_MINUS_ONE), diff --git a/src/tools/clippy/clippy_lints/src/lib.register_perf.rs b/src/tools/clippy/clippy_lints/src/lib.register_perf.rs index 82431863e6c..6bf519c24e8 100644 --- a/src/tools/clippy/clippy_lints/src/lib.register_perf.rs +++ b/src/tools/clippy/clippy_lints/src/lib.register_perf.rs @@ -13,6 +13,7 @@ store.register_group(true, "clippy::perf", Some("clippy_perf"), vec![ LintId::of(loops::MANUAL_MEMCPY), LintId::of(loops::MISSING_SPIN_LOOP), LintId::of(loops::NEEDLESS_COLLECT), + LintId::of(manual_retain::MANUAL_RETAIN), LintId::of(methods::EXPECT_FUN_CALL), LintId::of(methods::EXTEND_WITH_DRAIN), LintId::of(methods::ITER_NTH), @@ -21,7 +22,7 @@ store.register_group(true, "clippy::perf", Some("clippy_perf"), vec![ LintId::of(methods::OR_FUN_CALL), LintId::of(methods::SINGLE_CHAR_PATTERN), LintId::of(methods::UNNECESSARY_TO_OWNED), - LintId::of(misc::CMP_OWNED), + LintId::of(operators::CMP_OWNED), LintId::of(redundant_clone::REDUNDANT_CLONE), LintId::of(slow_vector_initialization::SLOW_VECTOR_INITIALIZATION), LintId::of(types::BOX_COLLECTION), diff --git a/src/tools/clippy/clippy_lints/src/lib.register_restriction.rs b/src/tools/clippy/clippy_lints/src/lib.register_restriction.rs index 3695012f552..970e9db4772 100644 --- a/src/tools/clippy/clippy_lints/src/lib.register_restriction.rs +++ b/src/tools/clippy/clippy_lints/src/lib.register_restriction.rs @@ -25,7 +25,6 @@ store.register_group(true, "clippy::restriction", Some("clippy_restriction"), ve LintId::of(implicit_return::IMPLICIT_RETURN), LintId::of(indexing_slicing::INDEXING_SLICING), LintId::of(inherent_impl::MULTIPLE_INHERENT_IMPL), - LintId::of(integer_division::INTEGER_DIVISION), LintId::of(large_include_file::LARGE_INCLUDE_FILE), LintId::of(let_underscore::LET_UNDERSCORE_MUST_USE), LintId::of(literal_representation::DECIMAL_LITERAL_REPRESENTATION), @@ -39,7 +38,6 @@ store.register_group(true, "clippy::restriction", Some("clippy_restriction"), ve LintId::of(methods::FILETYPE_IS_FILE), LintId::of(methods::GET_UNWRAP), LintId::of(methods::UNWRAP_USED), - LintId::of(misc::FLOAT_CMP_CONST), LintId::of(misc_early::SEPARATED_LITERAL_SUFFIX), LintId::of(misc_early::UNNEEDED_FIELD_PATTERN), LintId::of(misc_early::UNSEPARATED_LITERAL_SUFFIX), @@ -49,9 +47,11 @@ store.register_group(true, "clippy::restriction", Some("clippy_restriction"), ve LintId::of(mixed_read_write_in_expression::MIXED_READ_WRITE_IN_EXPRESSION), LintId::of(module_style::MOD_MODULE_FILES), LintId::of(module_style::SELF_NAMED_MODULE_FILES), - LintId::of(modulo_arithmetic::MODULO_ARITHMETIC), - LintId::of(numeric_arithmetic::FLOAT_ARITHMETIC), - LintId::of(numeric_arithmetic::INTEGER_ARITHMETIC), + LintId::of(operators::FLOAT_ARITHMETIC), + LintId::of(operators::FLOAT_CMP_CONST), + LintId::of(operators::INTEGER_ARITHMETIC), + LintId::of(operators::INTEGER_DIVISION), + LintId::of(operators::MODULO_ARITHMETIC), LintId::of(panic_in_result_fn::PANIC_IN_RESULT_FN), LintId::of(panic_unimplemented::PANIC), LintId::of(panic_unimplemented::TODO), diff --git a/src/tools/clippy/clippy_lints/src/lib.register_style.rs b/src/tools/clippy/clippy_lints/src/lib.register_style.rs index b6992ae0ad2..15a1bc569af 100644 --- a/src/tools/clippy/clippy_lints/src/lib.register_style.rs +++ b/src/tools/clippy/clippy_lints/src/lib.register_style.rs @@ -4,7 +4,6 @@ store.register_group(true, "clippy::style", Some("clippy_style"), vec![ LintId::of(assertions_on_constants::ASSERTIONS_ON_CONSTANTS), - LintId::of(assign_ops::ASSIGN_OP_PATTERN), LintId::of(blacklisted_name::BLACKLISTED_NAME), LintId::of(blocks_in_if_conditions::BLOCKS_IN_IF_CONDITIONS), LintId::of(bool_assert_comparison::BOOL_ASSERT_COMPARISON), @@ -14,6 +13,7 @@ store.register_group(true, "clippy::style", Some("clippy_style"), vec![ LintId::of(collapsible_if::COLLAPSIBLE_IF), LintId::of(comparison_chain::COMPARISON_CHAIN), LintId::of(default::FIELD_REASSIGN_WITH_DEFAULT), + LintId::of(default_instead_of_iter_empty::DEFAULT_INSTEAD_OF_ITER_EMPTY), LintId::of(dereference::NEEDLESS_BORROW), LintId::of(derive::DERIVE_PARTIAL_EQ_WITHOUT_EQ), LintId::of(disallowed_methods::DISALLOWED_METHODS), @@ -22,7 +22,6 @@ store.register_group(true, "clippy::style", Some("clippy_style"), vec![ LintId::of(doc::NEEDLESS_DOCTEST_MAIN), LintId::of(enum_variants::ENUM_VARIANT_NAMES), LintId::of(enum_variants::MODULE_INCEPTION), - LintId::of(eq_op::OP_REF), LintId::of(eta_reduction::REDUNDANT_CLOSURE), LintId::of(float_literal::EXCESSIVE_PRECISION), LintId::of(from_over_into::FROM_OVER_INTO), @@ -97,9 +96,11 @@ store.register_group(true, "clippy::style", Some("clippy_style"), vec![ LintId::of(non_copy_const::BORROW_INTERIOR_MUTABLE_CONST), LintId::of(non_copy_const::DECLARE_INTERIOR_MUTABLE_CONST), LintId::of(non_expressive_names::JUST_UNDERSCORES_AND_DIGITS), + LintId::of(operators::ASSIGN_OP_PATTERN), + LintId::of(operators::OP_REF), + LintId::of(operators::PTR_EQ), LintId::of(ptr::CMP_NULL), LintId::of(ptr::PTR_ARG), - LintId::of(ptr_eq::PTR_EQ), LintId::of(question_mark::QUESTION_MARK), LintId::of(ranges::MANUAL_RANGE_CONTAINS), LintId::of(redundant_field_names::REDUNDANT_FIELD_NAMES), diff --git a/src/tools/clippy/clippy_lints/src/lib.register_suspicious.rs b/src/tools/clippy/clippy_lints/src/lib.register_suspicious.rs index 7b13713c36e..f7558f87098 100644 --- a/src/tools/clippy/clippy_lints/src/lib.register_suspicious.rs +++ b/src/tools/clippy/clippy_lints/src/lib.register_suspicious.rs @@ -4,7 +4,6 @@ store.register_group(true, "clippy::suspicious", Some("clippy_suspicious"), vec![ LintId::of(almost_complete_letter_range::ALMOST_COMPLETE_LETTER_RANGE), - LintId::of(assign_ops::MISREFACTORED_ASSIGN_OP), LintId::of(attrs::BLANKET_CLIPPY_RESTRICTION_LINTS), LintId::of(await_holding_invalid::AWAIT_HOLDING_INVALID_TYPE), LintId::of(await_holding_invalid::AWAIT_HOLDING_LOCK), @@ -16,7 +15,6 @@ store.register_group(true, "clippy::suspicious", Some("clippy_suspicious"), vec! LintId::of(drop_forget_ref::DROP_NON_DROP), LintId::of(drop_forget_ref::FORGET_NON_DROP), LintId::of(duplicate_mod::DUPLICATE_MOD), - LintId::of(float_equality_without_abs::FLOAT_EQUALITY_WITHOUT_ABS), LintId::of(format_impl::PRINT_IN_FORMAT_IMPL), LintId::of(formatting::SUSPICIOUS_ASSIGNMENT_FORMATTING), LintId::of(formatting::SUSPICIOUS_ELSE_FORMATTING), @@ -29,6 +27,8 @@ store.register_group(true, "clippy::suspicious", Some("clippy_suspicious"), vec! LintId::of(methods::SUSPICIOUS_MAP), LintId::of(mut_key::MUTABLE_KEY_TYPE), LintId::of(octal_escapes::OCTAL_ESCAPES), + LintId::of(operators::FLOAT_EQUALITY_WITHOUT_ABS), + LintId::of(operators::MISREFACTORED_ASSIGN_OP), LintId::of(rc_clone_in_vec_init::RC_CLONE_IN_VEC_INIT), LintId::of(suspicious_trait_impl::SUSPICIOUS_ARITHMETIC_IMPL), LintId::of(suspicious_trait_impl::SUSPICIOUS_OP_ASSIGN_IMPL), diff --git a/src/tools/clippy/clippy_lints/src/lib.rs b/src/tools/clippy/clippy_lints/src/lib.rs index 84898eae05a..172fdf8c852 100644 --- a/src/tools/clippy/clippy_lints/src/lib.rs +++ b/src/tools/clippy/clippy_lints/src/lib.rs @@ -7,6 +7,7 @@ #![feature(let_chains)] #![feature(let_else)] #![feature(lint_reasons)] +#![feature(never_type)] #![feature(once_cell)] #![feature(rustc_private)] #![feature(stmt_expr_attributes)] @@ -52,6 +53,7 @@ extern crate clippy_utils; use clippy_utils::parse_msrv; use rustc_data_structures::fx::FxHashSet; use rustc_lint::LintId; +use rustc_semver::RustcVersion; use rustc_session::Session; /// Macro used to declare a Clippy lint. @@ -159,25 +161,22 @@ macro_rules! declare_clippy_lint { } #[cfg(feature = "internal")] -mod deprecated_lints; +pub mod deprecated_lints; #[cfg_attr(feature = "internal", allow(clippy::missing_clippy_version_attribute))] mod utils; mod renamed_lints; // begin lints modules, do not remove this comment, it’s used in `update_lints` -mod absurd_extreme_comparisons; mod almost_complete_letter_range; mod approx_const; mod as_conversions; mod as_underscore; mod asm_syntax; mod assertions_on_constants; -mod assign_ops; mod async_yields_async; mod attrs; mod await_holding_invalid; -mod bit_mask; mod blacklisted_name; mod blocks_in_if_conditions; mod bool_assert_comparison; @@ -199,6 +198,7 @@ mod crate_in_macro_def; mod create_dir; mod dbg_macro; mod default; +mod default_instead_of_iter_empty; mod default_numeric_fallback; mod default_union_representation; mod dereference; @@ -209,11 +209,9 @@ mod disallowed_script_idents; mod disallowed_types; mod doc; mod doc_link_with_quotes; -mod double_comparison; mod double_parens; mod drop_forget_ref; mod duplicate_mod; -mod duration_subsec; mod else_if_without_else; mod empty_drop; mod empty_enum; @@ -221,9 +219,7 @@ mod empty_structs_with_brackets; mod entry; mod enum_clike; mod enum_variants; -mod eq_op; mod equatable_if_let; -mod erasing_op; mod escape; mod eta_reduction; mod excessive_bools; @@ -231,7 +227,6 @@ mod exhaustive_items; mod exit; mod explicit_write; mod fallible_impl_from; -mod float_equality_without_abs; mod float_literal; mod floating_point_arithmetic; mod format; @@ -244,7 +239,6 @@ mod from_str_radix_10; mod functions; mod future_not_send; mod get_first; -mod identity_op; mod if_let_mutex; mod if_not_else; mod if_then_some_else_none; @@ -260,7 +254,6 @@ mod inherent_to_string; mod init_numbered_fields; mod inline_fn_without_body; mod int_plus_one; -mod integer_division; mod invalid_upcast_comparisons; mod items_after_statements; mod iter_not_returning_iterator; @@ -281,6 +274,8 @@ mod manual_async_fn; mod manual_bits; mod manual_non_exhaustive; mod manual_ok_or; +mod manual_rem_euclid; +mod manual_retain; mod manual_strip; mod map_clone; mod map_err_ignore; @@ -300,7 +295,6 @@ mod missing_enforced_import_rename; mod missing_inline; mod mixed_read_write_in_expression; mod module_style; -mod modulo_arithmetic; mod mut_key; mod mut_mut; mod mut_mutex_lock; @@ -308,7 +302,6 @@ mod mut_reference; mod mutable_debug_assertion; mod mutex_atomic; mod needless_arbitrary_self_type; -mod needless_bitwise_bool; mod needless_bool; mod needless_borrowed_ref; mod needless_continue; @@ -327,10 +320,10 @@ mod non_expressive_names; mod non_octal_unix_permissions; mod non_send_fields_in_send_ty; mod nonstandard_macro_braces; -mod numeric_arithmetic; mod octal_escapes; mod only_used_in_recursion; mod open_options; +mod operators; mod option_env_unwrap; mod option_if_let_else; mod overflow_check_conditional; @@ -342,7 +335,6 @@ mod path_buf_push_overwrite; mod pattern_type_mismatch; mod precedence; mod ptr; -mod ptr_eq; mod ptr_offset_with_cast; mod pub_use; mod question_mark; @@ -363,7 +355,6 @@ mod repeat_once; mod return_self_not_must_use; mod returns; mod same_name_method; -mod self_assignment; mod self_named_constructors; mod semicolon_if_nothing_returned; mod serde_api; @@ -448,6 +439,39 @@ pub fn register_pre_expansion_lints(store: &mut rustc_lint::LintStore, sess: &Se store.register_pre_expansion_pass(move || Box::new(attrs::EarlyAttributes { msrv })); } +fn read_msrv(conf: &Conf, sess: &Session) -> Option<RustcVersion> { + let cargo_msrv = std::env::var("CARGO_PKG_RUST_VERSION") + .ok() + .and_then(|v| parse_msrv(&v, None, None)); + let clippy_msrv = conf.msrv.as_ref().and_then(|s| { + parse_msrv(s, None, None).or_else(|| { + sess.err(&format!( + "error reading Clippy's configuration file. `{}` is not a valid Rust version", + s + )); + None + }) + }); + + if let Some(cargo_msrv) = cargo_msrv { + if let Some(clippy_msrv) = clippy_msrv { + // if both files have an msrv, let's compare them and emit a warning if they differ + if clippy_msrv != cargo_msrv { + sess.warn(&format!( + "the MSRV in `clippy.toml` and `Cargo.toml` differ; using `{}` from `clippy.toml`", + clippy_msrv + )); + } + + Some(clippy_msrv) + } else { + Some(cargo_msrv) + } + } else { + clippy_msrv + } +} + #[doc(hidden)] pub fn read_conf(sess: &Session) -> Conf { let file_name = match utils::conf::lookup_conf_file() { @@ -463,12 +487,11 @@ pub fn read_conf(sess: &Session) -> Conf { let TryConf { conf, errors } = utils::conf::read(&file_name); // all conf errors are non-fatal, we just use the default conf in case of error for error in errors { - sess.struct_err(&format!( + sess.err(&format!( "error reading Clippy's configuration file `{}`: {}", file_name.display(), format_error(error) - )) - .emit(); + )); } conf @@ -543,21 +566,14 @@ pub fn register_plugins(store: &mut rustc_lint::LintStore, sess: &Session, conf: )) }); store.register_late_pass(|| Box::new(booleans::NonminimalBool)); - store.register_late_pass(|| Box::new(needless_bitwise_bool::NeedlessBitwiseBool)); - store.register_late_pass(|| Box::new(eq_op::EqOp)); store.register_late_pass(|| Box::new(enum_clike::UnportableVariant)); store.register_late_pass(|| Box::new(float_literal::FloatLiteral)); - let verbose_bit_mask_threshold = conf.verbose_bit_mask_threshold; - store.register_late_pass(move || Box::new(bit_mask::BitMask::new(verbose_bit_mask_threshold))); store.register_late_pass(|| Box::new(ptr::Ptr)); - store.register_late_pass(|| Box::new(ptr_eq::PtrEq)); store.register_late_pass(|| Box::new(needless_bool::NeedlessBool)); store.register_late_pass(|| Box::new(needless_bool::BoolComparison)); store.register_late_pass(|| Box::new(needless_for_each::NeedlessForEach)); store.register_late_pass(|| Box::new(misc::MiscLints)); store.register_late_pass(|| Box::new(eta_reduction::EtaReduction)); - store.register_late_pass(|| Box::new(identity_op::IdentityOp)); - store.register_late_pass(|| Box::new(erasing_op::ErasingOp)); store.register_late_pass(|| Box::new(mut_mut::MutMut)); store.register_late_pass(|| Box::new(mut_reference::UnnecessaryMutPassed)); store.register_late_pass(|| Box::new(len_zero::LenZero)); @@ -575,16 +591,7 @@ pub fn register_plugins(store: &mut rustc_lint::LintStore, sess: &Session, conf: store.register_late_pass(|| Box::new(non_octal_unix_permissions::NonOctalUnixPermissions)); store.register_early_pass(|| Box::new(unnecessary_self_imports::UnnecessarySelfImports)); - let msrv = conf.msrv.as_ref().and_then(|s| { - parse_msrv(s, None, None).or_else(|| { - sess.err(&format!( - "error reading Clippy's configuration file. `{}` is not a valid Rust version", - s - )); - None - }) - }); - + let msrv = read_msrv(conf, sess); let avoid_breaking_exported_api = conf.avoid_breaking_exported_api; let allow_expect_in_tests = conf.allow_expect_in_tests; let allow_unwrap_in_tests = conf.allow_unwrap_in_tests; @@ -639,7 +646,7 @@ pub fn register_plugins(store: &mut rustc_lint::LintStore, sess: &Session, conf: store.register_late_pass(|| Box::new(borrow_deref_ref::BorrowDerefRef)); store.register_late_pass(|| Box::new(no_effect::NoEffect)); store.register_late_pass(|| Box::new(temporary_assignment::TemporaryAssignment)); - store.register_late_pass(|| Box::new(transmute::Transmute)); + store.register_late_pass(move || Box::new(transmute::Transmute::new(msrv))); let cognitive_complexity_threshold = conf.cognitive_complexity_threshold; store.register_late_pass(move || { Box::new(cognitive_complexity::CognitiveComplexity::new( @@ -655,7 +662,6 @@ pub fn register_plugins(store: &mut rustc_lint::LintStore, sess: &Session, conf: store.register_late_pass(|| Box::new(derivable_impls::DerivableImpls)); store.register_late_pass(|| Box::new(drop_forget_ref::DropForgetRef)); store.register_late_pass(|| Box::new(empty_enum::EmptyEnum)); - store.register_late_pass(|| Box::new(absurd_extreme_comparisons::AbsurdExtremeComparisons)); store.register_late_pass(|| Box::new(invalid_upcast_comparisons::InvalidUpcastComparisons)); store.register_late_pass(|| Box::new(regex::Regex)); store.register_late_pass(|| Box::new(copies::CopyAndPaste)); @@ -678,8 +684,6 @@ pub fn register_plugins(store: &mut rustc_lint::LintStore, sess: &Session, conf: store.register_late_pass(move || Box::new(doc::DocMarkdown::new(doc_valid_idents.clone()))); store.register_late_pass(|| Box::new(neg_multiply::NegMultiply)); store.register_late_pass(|| Box::new(mem_forget::MemForget)); - store.register_late_pass(|| Box::new(numeric_arithmetic::NumericArithmetic::default())); - store.register_late_pass(|| Box::new(assign_ops::AssignOps)); store.register_late_pass(|| Box::new(let_if_seq::LetIfSeq)); store.register_late_pass(|| Box::new(mixed_read_write_in_expression::EvalOrderDependence)); store.register_late_pass(|| Box::new(missing_doc::MissingDoc::new())); @@ -706,7 +710,6 @@ pub fn register_plugins(store: &mut rustc_lint::LintStore, sess: &Session, conf: store.register_late_pass(|| Box::new(useless_conversion::UselessConversion::default())); store.register_late_pass(|| Box::new(implicit_hasher::ImplicitHasher)); store.register_late_pass(|| Box::new(fallible_impl_from::FallibleImplFrom)); - store.register_late_pass(|| Box::new(double_comparison::DoubleComparisons)); store.register_late_pass(|| Box::new(question_mark::QuestionMark)); store.register_early_pass(|| Box::new(suspicious_operation_groupings::SuspiciousOperationGroupings)); store.register_late_pass(|| Box::new(suspicious_trait_impl::SuspiciousImpl)); @@ -714,7 +717,6 @@ pub fn register_plugins(store: &mut rustc_lint::LintStore, sess: &Session, conf: store.register_late_pass(|| Box::new(inherent_impl::MultipleInherentImpl)); store.register_late_pass(|| Box::new(neg_cmp_op_on_partial_ord::NoNegCompOpForPartialOrd)); store.register_late_pass(|| Box::new(unwrap::Unwrap)); - store.register_late_pass(|| Box::new(duration_subsec::DurationSubsec)); store.register_late_pass(|| Box::new(indexing_slicing::IndexingSlicing)); store.register_late_pass(|| Box::new(non_copy_const::NonCopyConst)); store.register_late_pass(|| Box::new(ptr_offset_with_cast::PtrOffsetWithCast)); @@ -725,13 +727,11 @@ pub fn register_plugins(store: &mut rustc_lint::LintStore, sess: &Session, conf: store.register_late_pass(|| Box::new(assertions_on_constants::AssertionsOnConstants)); store.register_late_pass(|| Box::new(transmuting_null::TransmutingNull)); store.register_late_pass(|| Box::new(path_buf_push_overwrite::PathBufPushOverwrite)); - store.register_late_pass(|| Box::new(integer_division::IntegerDivision)); store.register_late_pass(|| Box::new(inherent_to_string::InherentToString)); let max_trait_bounds = conf.max_trait_bounds; store.register_late_pass(move || Box::new(trait_bounds::TraitBounds::new(max_trait_bounds))); store.register_late_pass(|| Box::new(comparison_chain::ComparisonChain)); store.register_late_pass(|| Box::new(mut_key::MutableKeyType)); - store.register_late_pass(|| Box::new(modulo_arithmetic::ModuloArithmetic)); store.register_early_pass(|| Box::new(reference::DerefAddrOf)); store.register_early_pass(|| Box::new(double_parens::DoubleParens)); store.register_late_pass(|| Box::new(format_impl::FormatImpl::new())); @@ -828,9 +828,7 @@ pub fn register_plugins(store: &mut rustc_lint::LintStore, sess: &Session, conf: store.register_late_pass(|| Box::new(stable_sort_primitive::StableSortPrimitive)); store.register_late_pass(|| Box::new(repeat_once::RepeatOnce)); store.register_late_pass(|| Box::new(unwrap_in_result::UnwrapInResult)); - store.register_late_pass(|| Box::new(self_assignment::SelfAssignment)); store.register_late_pass(|| Box::new(manual_ok_or::ManualOkOr)); - store.register_late_pass(|| Box::new(float_equality_without_abs::FloatEqualityWithoutAbs)); store.register_late_pass(|| Box::new(semicolon_if_nothing_returned::SemicolonIfNothingReturned)); store.register_late_pass(|| Box::new(async_yields_async::AsyncYieldsAsync)); let disallowed_methods = conf.disallowed_methods.clone(); @@ -910,6 +908,11 @@ pub fn register_plugins(store: &mut rustc_lint::LintStore, sess: &Session, conf: store.register_late_pass(|| Box::new(mismatching_type_param_order::TypeParamMismatch)); store.register_late_pass(|| Box::new(as_underscore::AsUnderscore)); store.register_late_pass(|| Box::new(read_zero_byte_vec::ReadZeroByteVec)); + store.register_late_pass(|| Box::new(default_instead_of_iter_empty::DefaultIterEmpty)); + store.register_late_pass(move || Box::new(manual_rem_euclid::ManualRemEuclid::new(msrv))); + store.register_late_pass(move || Box::new(manual_retain::ManualRetain::new(msrv))); + let verbose_bit_mask_threshold = conf.verbose_bit_mask_threshold; + store.register_late_pass(move || Box::new(operators::Operators::new(verbose_bit_mask_threshold))); // add lints here, do not remove this comment, it's used in `new_lint` } diff --git a/src/tools/clippy/clippy_lints/src/lifetimes.rs b/src/tools/clippy/clippy_lints/src/lifetimes.rs index 93f5663312f..5c0bd57ac50 100644 --- a/src/tools/clippy/clippy_lints/src/lifetimes.rs +++ b/src/tools/clippy/clippy_lints/src/lifetimes.rs @@ -92,7 +92,9 @@ impl<'tcx> LateLintPass<'tcx> for Lifetimes { if let ItemKind::Fn(ref sig, generics, id) = item.kind { check_fn_inner(cx, sig.decl, Some(id), None, generics, item.span, true); } else if let ItemKind::Impl(impl_) = item.kind { - report_extra_impl_lifetimes(cx, impl_); + if !item.span.from_expansion() { + report_extra_impl_lifetimes(cx, impl_); + } } } diff --git a/src/tools/clippy/clippy_lints/src/loops/manual_find.rs b/src/tools/clippy/clippy_lints/src/loops/manual_find.rs new file mode 100644 index 00000000000..33736d6d4e6 --- /dev/null +++ b/src/tools/clippy/clippy_lints/src/loops/manual_find.rs @@ -0,0 +1,158 @@ +use super::utils::make_iterator_snippet; +use super::MANUAL_FIND; +use clippy_utils::{ + diagnostics::span_lint_and_then, higher, is_lang_ctor, path_res, peel_blocks_with_stmt, + source::snippet_with_applicability, ty::implements_trait, +}; +use if_chain::if_chain; +use rustc_errors::Applicability; +use rustc_hir::{ + def::Res, lang_items::LangItem, BindingAnnotation, Block, Expr, ExprKind, HirId, Node, Pat, PatKind, Stmt, StmtKind, +}; +use rustc_lint::LateContext; +use rustc_span::source_map::Span; + +pub(super) fn check<'tcx>( + cx: &LateContext<'tcx>, + pat: &'tcx Pat<'_>, + arg: &'tcx Expr<'_>, + body: &'tcx Expr<'_>, + span: Span, + expr: &'tcx Expr<'_>, +) { + let inner_expr = peel_blocks_with_stmt(body); + // Check for the specific case that the result is returned and optimize suggestion for that (more + // cases can be added later) + if_chain! { + if let Some(higher::If { cond, then, r#else: None, }) = higher::If::hir(inner_expr); + if let Some(binding_id) = get_binding(pat); + if let ExprKind::Block(block, _) = then.kind; + if let [stmt] = block.stmts; + if let StmtKind::Semi(semi) = stmt.kind; + if let ExprKind::Ret(Some(ret_value)) = semi.kind; + if let ExprKind::Call(Expr { kind: ExprKind::Path(ctor), .. }, [inner_ret]) = ret_value.kind; + if is_lang_ctor(cx, ctor, LangItem::OptionSome); + if path_res(cx, inner_ret) == Res::Local(binding_id); + if let Some((last_stmt, last_ret)) = last_stmt_and_ret(cx, expr); + then { + let mut applicability = Applicability::MachineApplicable; + let mut snippet = make_iterator_snippet(cx, arg, &mut applicability); + // Checks if `pat` is a single reference to a binding (`&x`) + let is_ref_to_binding = + matches!(pat.kind, PatKind::Ref(inner, _) if matches!(inner.kind, PatKind::Binding(..))); + // If `pat` is not a binding or a reference to a binding (`x` or `&x`) + // we need to map it to the binding returned by the function (i.e. `.map(|(x, _)| x)`) + if !(matches!(pat.kind, PatKind::Binding(..)) || is_ref_to_binding) { + snippet.push_str( + &format!( + ".map(|{}| {})", + snippet_with_applicability(cx, pat.span, "..", &mut applicability), + snippet_with_applicability(cx, inner_ret.span, "..", &mut applicability), + )[..], + ); + } + let ty = cx.typeck_results().expr_ty(inner_ret); + if cx.tcx.lang_items().copy_trait().map_or(false, |id| implements_trait(cx, ty, id, &[])) { + snippet.push_str( + &format!( + ".find(|{}{}| {})", + "&".repeat(1 + usize::from(is_ref_to_binding)), + snippet_with_applicability(cx, inner_ret.span, "..", &mut applicability), + snippet_with_applicability(cx, cond.span, "..", &mut applicability), + )[..], + ); + if is_ref_to_binding { + snippet.push_str(".copied()"); + } + } else { + applicability = Applicability::MaybeIncorrect; + snippet.push_str( + &format!( + ".find(|{}| {})", + snippet_with_applicability(cx, inner_ret.span, "..", &mut applicability), + snippet_with_applicability(cx, cond.span, "..", &mut applicability), + )[..], + ); + } + // Extends to `last_stmt` to include semicolon in case of `return None;` + let lint_span = span.to(last_stmt.span).to(last_ret.span); + span_lint_and_then( + cx, + MANUAL_FIND, + lint_span, + "manual implementation of `Iterator::find`", + |diag| { + if applicability == Applicability::MaybeIncorrect { + diag.note("you may need to dereference some variables"); + } + diag.span_suggestion( + lint_span, + "replace with an iterator", + snippet, + applicability, + ); + }, + ); + } + } +} + +fn get_binding(pat: &Pat<'_>) -> Option<HirId> { + let mut hir_id = None; + let mut count = 0; + pat.each_binding(|annotation, id, _, _| { + count += 1; + if count > 1 { + hir_id = None; + return; + } + if let BindingAnnotation::Unannotated = annotation { + hir_id = Some(id); + } + }); + hir_id +} + +// Returns the last statement and last return if function fits format for lint +fn last_stmt_and_ret<'tcx>( + cx: &LateContext<'tcx>, + expr: &'tcx Expr<'_>, +) -> Option<(&'tcx Stmt<'tcx>, &'tcx Expr<'tcx>)> { + // Returns last non-return statement and the last return + fn extract<'tcx>(block: &Block<'tcx>) -> Option<(&'tcx Stmt<'tcx>, &'tcx Expr<'tcx>)> { + if let [.., last_stmt] = block.stmts { + if let Some(ret) = block.expr { + return Some((last_stmt, ret)); + } + if_chain! { + if let [.., snd_last, _] = block.stmts; + if let StmtKind::Semi(last_expr) = last_stmt.kind; + if let ExprKind::Ret(Some(ret)) = last_expr.kind; + then { + return Some((snd_last, ret)); + } + } + } + None + } + let mut parent_iter = cx.tcx.hir().parent_iter(expr.hir_id); + if_chain! { + // This should be the loop + if let Some((node_hir, Node::Stmt(..))) = parent_iter.next(); + // This should be the funciton body + if let Some((_, Node::Block(block))) = parent_iter.next(); + if let Some((last_stmt, last_ret)) = extract(block); + if last_stmt.hir_id == node_hir; + if let ExprKind::Path(path) = &last_ret.kind; + if is_lang_ctor(cx, path, LangItem::OptionNone); + if let Some((_, Node::Expr(_block))) = parent_iter.next(); + // This includes the function header + if let Some((_, func)) = parent_iter.next(); + if func.fn_kind().is_some(); + then { + Some((block.stmts.last().unwrap(), last_ret)) + } else { + None + } + } +} diff --git a/src/tools/clippy/clippy_lints/src/loops/mod.rs b/src/tools/clippy/clippy_lints/src/loops/mod.rs index 391de922e1e..ed270bd490d 100644 --- a/src/tools/clippy/clippy_lints/src/loops/mod.rs +++ b/src/tools/clippy/clippy_lints/src/loops/mod.rs @@ -5,6 +5,7 @@ mod explicit_iter_loop; mod for_kv_map; mod for_loops_over_fallibles; mod iter_next_loop; +mod manual_find; mod manual_flatten; mod manual_memcpy; mod missing_spin_loop; @@ -346,7 +347,14 @@ declare_clippy_lint! { /// /// ### Example /// ```ignore - /// while let Some(val) = iter() { + /// while let Some(val) = iter.next() { + /// .. + /// } + /// ``` + /// + /// Use instead: + /// ```ignore + /// for val in &mut iter { /// .. /// } /// ``` @@ -602,6 +610,37 @@ declare_clippy_lint! { "An empty busy waiting loop" } +declare_clippy_lint! { + /// ### What it does + /// Check for manual implementations of Iterator::find + /// + /// ### Why is this bad? + /// It doesn't affect performance, but using `find` is shorter and easier to read. + /// + /// ### Example + /// + /// ```rust + /// fn example(arr: Vec<i32>) -> Option<i32> { + /// for el in arr { + /// if el == 1 { + /// return Some(el); + /// } + /// } + /// None + /// } + /// ``` + /// Use instead: + /// ```rust + /// fn example(arr: Vec<i32>) -> Option<i32> { + /// arr.into_iter().find(|&el| el == 1) + /// } + /// ``` + #[clippy::version = "1.61.0"] + pub MANUAL_FIND, + complexity, + "manual implementation of `Iterator::find`" +} + declare_lint_pass!(Loops => [ MANUAL_MEMCPY, MANUAL_FLATTEN, @@ -622,6 +661,7 @@ declare_lint_pass!(Loops => [ SAME_ITEM_PUSH, SINGLE_ELEMENT_LOOP, MISSING_SPIN_LOOP, + MANUAL_FIND, ]); impl<'tcx> LateLintPass<'tcx> for Loops { @@ -696,6 +736,7 @@ fn check_for_loop<'tcx>( single_element_loop::check(cx, pat, arg, body, expr); same_item_push::check(cx, pat, arg, body, expr); manual_flatten::check(cx, pat, arg, body, span); + manual_find::check(cx, pat, arg, body, span, expr); } fn check_for_loop_arg(cx: &LateContext<'_>, pat: &Pat<'_>, arg: &Expr<'_>) { diff --git a/src/tools/clippy/clippy_lints/src/loops/mut_range_bound.rs b/src/tools/clippy/clippy_lints/src/loops/mut_range_bound.rs index d20df830455..aedf3810b23 100644 --- a/src/tools/clippy/clippy_lints/src/loops/mut_range_bound.rs +++ b/src/tools/clippy/clippy_lints/src/loops/mut_range_bound.rs @@ -43,7 +43,7 @@ fn mut_warn_with_span(cx: &LateContext<'_>, span: Option<Span>) { fn check_for_mutability(cx: &LateContext<'_>, bound: &Expr<'_>) -> Option<HirId> { if_chain! { if let Some(hir_id) = path_to_local(bound); - if let Node::Binding(pat) = cx.tcx.hir().get(hir_id); + if let Node::Pat(pat) = cx.tcx.hir().get(hir_id); if let PatKind::Binding(BindingAnnotation::Mutable, ..) = pat.kind; then { return Some(hir_id); diff --git a/src/tools/clippy/clippy_lints/src/loops/same_item_push.rs b/src/tools/clippy/clippy_lints/src/loops/same_item_push.rs index e048d744fc3..1439f1f4c75 100644 --- a/src/tools/clippy/clippy_lints/src/loops/same_item_push.rs +++ b/src/tools/clippy/clippy_lints/src/loops/same_item_push.rs @@ -63,7 +63,7 @@ pub(super) fn check<'tcx>( Res::Local(hir_id) => { let node = cx.tcx.hir().get(hir_id); if_chain! { - if let Node::Binding(pat) = node; + if let Node::Pat(pat) = node; if let PatKind::Binding(bind_ann, ..) = pat.kind; if !matches!(bind_ann, BindingAnnotation::RefMut | BindingAnnotation::Mutable); let parent_node = cx.tcx.hir().get_parent_node(hir_id); diff --git a/src/tools/clippy/clippy_lints/src/loops/while_let_loop.rs b/src/tools/clippy/clippy_lints/src/loops/while_let_loop.rs index 8f57df0be6b..45af6be2653 100644 --- a/src/tools/clippy/clippy_lints/src/loops/while_let_loop.rs +++ b/src/tools/clippy/clippy_lints/src/loops/while_let_loop.rs @@ -2,71 +2,60 @@ use super::WHILE_LET_LOOP; use clippy_utils::diagnostics::span_lint_and_sugg; use clippy_utils::higher; use clippy_utils::source::snippet_with_applicability; +use clippy_utils::ty::needs_ordered_drop; +use clippy_utils::visitors::any_temporaries_need_ordered_drop; use rustc_errors::Applicability; -use rustc_hir::{Block, Expr, ExprKind, MatchSource, Pat, StmtKind}; -use rustc_lint::{LateContext, LintContext}; -use rustc_middle::lint::in_external_macro; +use rustc_hir::{Block, Expr, ExprKind, Local, MatchSource, Pat, StmtKind}; +use rustc_lint::LateContext; pub(super) fn check<'tcx>(cx: &LateContext<'tcx>, expr: &'tcx Expr<'_>, loop_block: &'tcx Block<'_>) { - // extract the expression from the first statement (if any) in a block - let inner_stmt_expr = extract_expr_from_first_stmt(loop_block); - // or extract the first expression (if any) from the block - if let Some(inner) = inner_stmt_expr.or_else(|| extract_first_expr(loop_block)) { - if let Some(higher::IfLet { - let_pat, - let_expr, - if_else: Some(if_else), - .. - }) = higher::IfLet::hir(cx, inner) - { - if is_simple_break_expr(if_else) { - could_be_while_let(cx, expr, let_pat, let_expr); + let (init, has_trailing_exprs) = match (loop_block.stmts, loop_block.expr) { + ([stmt, stmts @ ..], expr) => { + if let StmtKind::Local(&Local { init: Some(e), .. }) | StmtKind::Semi(e) | StmtKind::Expr(e) = stmt.kind { + (e, !stmts.is_empty() || expr.is_some()) + } else { + return; } - } - - if let ExprKind::Match(matchexpr, arms, MatchSource::Normal) = inner.kind { - if arms.len() == 2 - && arms[0].guard.is_none() - && arms[1].guard.is_none() - && is_simple_break_expr(arms[1].body) - { - could_be_while_let(cx, expr, arms[0].pat, matchexpr); - } - } - } -} + }, + ([], Some(e)) => (e, false), + _ => return, + }; -/// If a block begins with a statement (possibly a `let` binding) and has an -/// expression, return it. -fn extract_expr_from_first_stmt<'tcx>(block: &Block<'tcx>) -> Option<&'tcx Expr<'tcx>> { - if let Some(first_stmt) = block.stmts.get(0) { - if let StmtKind::Local(local) = first_stmt.kind { - return local.init; - } + if let Some(if_let) = higher::IfLet::hir(cx, init) + && let Some(else_expr) = if_let.if_else + && is_simple_break_expr(else_expr) + { + could_be_while_let(cx, expr, if_let.let_pat, if_let.let_expr, has_trailing_exprs); + } else if let ExprKind::Match(scrutinee, [arm1, arm2], MatchSource::Normal) = init.kind + && arm1.guard.is_none() + && arm2.guard.is_none() + && is_simple_break_expr(arm2.body) + { + could_be_while_let(cx, expr, arm1.pat, scrutinee, has_trailing_exprs); } - None } -/// If a block begins with an expression (with or without semicolon), return it. -fn extract_first_expr<'tcx>(block: &Block<'tcx>) -> Option<&'tcx Expr<'tcx>> { - match block.expr { - Some(expr) if block.stmts.is_empty() => Some(expr), - None if !block.stmts.is_empty() => match block.stmts[0].kind { - StmtKind::Expr(expr) | StmtKind::Semi(expr) => Some(expr), - StmtKind::Local(..) | StmtKind::Item(..) => None, - }, - _ => None, - } +/// Returns `true` if expr contains a single break expression without a label or eub-expression. +fn is_simple_break_expr(e: &Expr<'_>) -> bool { + matches!(peel_blocks(e).kind, ExprKind::Break(dest, None) if dest.label.is_none()) } -/// Returns `true` if expr contains a single break expr without destination label -/// and -/// passed expression. The expression may be within a block. -fn is_simple_break_expr(expr: &Expr<'_>) -> bool { - match expr.kind { - ExprKind::Break(dest, ref passed_expr) if dest.label.is_none() && passed_expr.is_none() => true, - ExprKind::Block(b, _) => extract_first_expr(b).map_or(false, is_simple_break_expr), - _ => false, +/// Removes any blocks containing only a single expression. +fn peel_blocks<'tcx>(e: &'tcx Expr<'tcx>) -> &'tcx Expr<'tcx> { + if let ExprKind::Block(b, _) = e.kind { + match (b.stmts, b.expr) { + ([s], None) => { + if let StmtKind::Expr(e) | StmtKind::Semi(e) = s.kind { + peel_blocks(e) + } else { + e + } + }, + ([], Some(e)) => peel_blocks(e), + _ => e, + } + } else { + e } } @@ -75,8 +64,13 @@ fn could_be_while_let<'tcx>( expr: &'tcx Expr<'_>, let_pat: &'tcx Pat<'_>, let_expr: &'tcx Expr<'_>, + has_trailing_exprs: bool, ) { - if in_external_macro(cx.sess(), expr.span) { + if has_trailing_exprs + && (needs_ordered_drop(cx, cx.typeck_results().expr_ty(let_expr)) + || any_temporaries_need_ordered_drop(cx, let_expr)) + { + // Switching to a `while let` loop will extend the lifetime of some values. return; } diff --git a/src/tools/clippy/clippy_lints/src/macro_use.rs b/src/tools/clippy/clippy_lints/src/macro_use.rs index 753469c603d..d573a1b4fbb 100644 --- a/src/tools/clippy/clippy_lints/src/macro_use.rs +++ b/src/tools/clippy/clippy_lints/src/macro_use.rs @@ -1,4 +1,4 @@ -use clippy_utils::diagnostics::span_lint_and_sugg; +use clippy_utils::diagnostics::span_lint_hir_and_then; use clippy_utils::source::snippet; use hir::def::{DefKind, Res}; use if_chain::if_chain; @@ -50,8 +50,9 @@ impl MacroRefData { #[derive(Default)] #[expect(clippy::module_name_repetitions)] pub struct MacroUseImports { - /// the actual import path used and the span of the attribute above it. - imports: Vec<(String, Span)>, + /// the actual import path used and the span of the attribute above it. The value is + /// the location, where the lint should be emitted. + imports: Vec<(String, Span, hir::HirId)>, /// the span of the macro reference, kept to ensure only one reference is used per macro call. collected: FxHashSet<Span>, mac_refs: Vec<MacroRefData>, @@ -90,7 +91,8 @@ impl<'tcx> LateLintPass<'tcx> for MacroUseImports { if_chain! { if cx.sess().opts.edition >= Edition::Edition2018; if let hir::ItemKind::Use(path, _kind) = &item.kind; - let attrs = cx.tcx.hir().attrs(item.hir_id()); + let hir_id = item.hir_id(); + let attrs = cx.tcx.hir().attrs(hir_id); if let Some(mac_attr) = attrs.iter().find(|attr| attr.has_name(sym::macro_use)); if let Res::Def(DefKind::Mod, id) = path.res; if !id.is_local(); @@ -99,7 +101,7 @@ impl<'tcx> LateLintPass<'tcx> for MacroUseImports { if let Res::Def(DefKind::Macro(_mac_type), mac_id) = kid.res { let span = mac_attr.span; let def_path = cx.tcx.def_path_str(mac_id); - self.imports.push((def_path, span)); + self.imports.push((def_path, span, hir_id)); } } } else { @@ -137,7 +139,7 @@ impl<'tcx> LateLintPass<'tcx> for MacroUseImports { fn check_crate_post(&mut self, cx: &LateContext<'_>) { let mut used = FxHashMap::default(); let mut check_dup = vec![]; - for (import, span) in &self.imports { + for (import, span, hir_id) in &self.imports { let found_idx = self.mac_refs.iter().position(|mac| import.ends_with(&mac.name)); if let Some(idx) = found_idx { @@ -150,7 +152,7 @@ impl<'tcx> LateLintPass<'tcx> for MacroUseImports { [] | [_] => return, [root, item] => { if !check_dup.contains(&(*item).to_string()) { - used.entry(((*root).to_string(), span)) + used.entry(((*root).to_string(), span, hir_id)) .or_insert_with(Vec::new) .push((*item).to_string()); check_dup.push((*item).to_string()); @@ -168,13 +170,13 @@ impl<'tcx> LateLintPass<'tcx> for MacroUseImports { } }) .collect::<Vec<_>>(); - used.entry(((*root).to_string(), span)) + used.entry(((*root).to_string(), span, hir_id)) .or_insert_with(Vec::new) .push(filtered.join("::")); check_dup.extend(filtered); } else { let rest = rest.to_vec(); - used.entry(((*root).to_string(), span)) + used.entry(((*root).to_string(), span, hir_id)) .or_insert_with(Vec::new) .push(rest.join("::")); check_dup.extend(rest.iter().map(ToString::to_string)); @@ -185,27 +187,33 @@ impl<'tcx> LateLintPass<'tcx> for MacroUseImports { } let mut suggestions = vec![]; - for ((root, span), path) in used { + for ((root, span, hir_id), path) in used { if path.len() == 1 { - suggestions.push((span, format!("{}::{}", root, path[0]))); + suggestions.push((span, format!("{}::{}", root, path[0]), hir_id)); } else { - suggestions.push((span, format!("{}::{{{}}}", root, path.join(", ")))); + suggestions.push((span, format!("{}::{{{}}}", root, path.join(", ")), hir_id)); } } // If mac_refs is not empty we have encountered an import we could not handle // such as `std::prelude::v1::foo` or some other macro that expands to an import. if self.mac_refs.is_empty() { - for (span, import) in suggestions { + for (span, import, hir_id) in suggestions { let help = format!("use {};", import); - span_lint_and_sugg( + span_lint_hir_and_then( cx, MACRO_USE_IMPORTS, + *hir_id, *span, "`macro_use` attributes are no longer needed in the Rust 2018 edition", - "remove the attribute and import the macro directly, try", - help, - Applicability::MaybeIncorrect, + |diag| { + diag.span_suggestion( + *span, + "remove the attribute and import the macro directly, try", + help, + Applicability::MaybeIncorrect, + ); + }, ); } } diff --git a/src/tools/clippy/clippy_lints/src/manual_non_exhaustive.rs b/src/tools/clippy/clippy_lints/src/manual_non_exhaustive.rs index 14f5faafd7c..4278e98dc91 100644 --- a/src/tools/clippy/clippy_lints/src/manual_non_exhaustive.rs +++ b/src/tools/clippy/clippy_lints/src/manual_non_exhaustive.rs @@ -1,6 +1,6 @@ -use clippy_utils::diagnostics::span_lint_and_then; +use clippy_utils::diagnostics::{span_lint_and_then, span_lint_hir_and_then}; use clippy_utils::source::snippet_opt; -use clippy_utils::{is_doc_hidden, is_lint_allowed, meets_msrv, msrvs}; +use clippy_utils::{is_doc_hidden, meets_msrv, msrvs}; use rustc_ast::ast::{self, VisibilityKind}; use rustc_data_structures::fx::FxHashSet; use rustc_errors::Applicability; @@ -190,12 +190,13 @@ impl<'tcx> LateLintPass<'tcx> for ManualNonExhaustiveEnum { !self .constructed_enum_variants .contains(&(enum_id.to_def_id(), variant_id.to_def_id())) - && !is_lint_allowed(cx, MANUAL_NON_EXHAUSTIVE, cx.tcx.hir().local_def_id_to_hir_id(enum_id)) }) { - span_lint_and_then( + let hir_id = cx.tcx.hir().local_def_id_to_hir_id(enum_id); + span_lint_hir_and_then( cx, MANUAL_NON_EXHAUSTIVE, + hir_id, enum_span, "this seems like a manual implementation of the non-exhaustive pattern", |diag| { diff --git a/src/tools/clippy/clippy_lints/src/manual_rem_euclid.rs b/src/tools/clippy/clippy_lints/src/manual_rem_euclid.rs new file mode 100644 index 00000000000..2ce9d0e77c1 --- /dev/null +++ b/src/tools/clippy/clippy_lints/src/manual_rem_euclid.rs @@ -0,0 +1,122 @@ +use clippy_utils::consts::{constant_full_int, FullInt}; +use clippy_utils::diagnostics::span_lint_and_sugg; +use clippy_utils::source::snippet_with_applicability; +use clippy_utils::{in_constant, meets_msrv, msrvs, path_to_local}; +use rustc_errors::Applicability; +use rustc_hir::{BinOpKind, Expr, ExprKind, Node, TyKind}; +use rustc_lint::{LateContext, LateLintPass, LintContext}; +use rustc_middle::lint::in_external_macro; +use rustc_semver::RustcVersion; +use rustc_session::{declare_tool_lint, impl_lint_pass}; + +declare_clippy_lint! { + /// ### What it does + /// Checks for an expression like `((x % 4) + 4) % 4` which is a common manual reimplementation + /// of `x.rem_euclid(4)`. + /// + /// ### Why is this bad? + /// It's simpler and more readable. + /// + /// ### Example + /// ```rust + /// let x: i32 = 24; + /// let rem = ((x % 4) + 4) % 4; + /// ``` + /// Use instead: + /// ```rust + /// let x: i32 = 24; + /// let rem = x.rem_euclid(4); + /// ``` + #[clippy::version = "1.63.0"] + pub MANUAL_REM_EUCLID, + complexity, + "manually reimplementing `rem_euclid`" +} + +pub struct ManualRemEuclid { + msrv: Option<RustcVersion>, +} + +impl ManualRemEuclid { + #[must_use] + pub fn new(msrv: Option<RustcVersion>) -> Self { + Self { msrv } + } +} + +impl_lint_pass!(ManualRemEuclid => [MANUAL_REM_EUCLID]); + +impl<'tcx> LateLintPass<'tcx> for ManualRemEuclid { + fn check_expr(&mut self, cx: &LateContext<'tcx>, expr: &'tcx Expr<'_>) { + if !meets_msrv(self.msrv, msrvs::REM_EUCLID) { + return; + } + + if in_constant(cx, expr.hir_id) && !meets_msrv(self.msrv, msrvs::REM_EUCLID_CONST) { + return; + } + + if in_external_macro(cx.sess(), expr.span) { + return; + } + + if let ExprKind::Binary(op1, expr1, right) = expr.kind + && op1.node == BinOpKind::Rem + && let Some(const1) = check_for_unsigned_int_constant(cx, right) + && let ExprKind::Binary(op2, left, right) = expr1.kind + && op2.node == BinOpKind::Add + && let Some((const2, expr2)) = check_for_either_unsigned_int_constant(cx, left, right) + && let ExprKind::Binary(op3, expr3, right) = expr2.kind + && op3.node == BinOpKind::Rem + && let Some(const3) = check_for_unsigned_int_constant(cx, right) + // Also ensures the const is nonzero since zero can't be a divisor + && const1 == const2 && const2 == const3 + && let Some(hir_id) = path_to_local(expr3) { + // Apply only to params or locals with annotated types + match cx.tcx.hir().find(cx.tcx.hir().get_parent_node(hir_id)) { + Some(Node::Param(..)) => (), + Some(Node::Local(local)) => { + let Some(ty) = local.ty else { return }; + if matches!(ty.kind, TyKind::Infer) { + return; + } + } + _ => return, + }; + + let mut app = Applicability::MachineApplicable; + let rem_of = snippet_with_applicability(cx, expr3.span, "_", &mut app); + span_lint_and_sugg( + cx, + MANUAL_REM_EUCLID, + expr.span, + "manual `rem_euclid` implementation", + "consider using", + format!("{rem_of}.rem_euclid({const1})"), + app, + ); + } + } + + extract_msrv_attr!(LateContext); +} + +// Checks if either the left or right expressions can be an unsigned int constant and returns that +// constant along with the other expression unchanged if so +fn check_for_either_unsigned_int_constant<'a>( + cx: &'a LateContext<'_>, + left: &'a Expr<'_>, + right: &'a Expr<'_>, +) -> Option<(u128, &'a Expr<'a>)> { + check_for_unsigned_int_constant(cx, left) + .map(|int_const| (int_const, right)) + .or_else(|| check_for_unsigned_int_constant(cx, right).map(|int_const| (int_const, left))) +} + +fn check_for_unsigned_int_constant<'a>(cx: &'a LateContext<'_>, expr: &'a Expr<'_>) -> Option<u128> { + let Some(int_const) = constant_full_int(cx, cx.typeck_results(), expr) else { return None }; + match int_const { + FullInt::S(s) => s.try_into().ok(), + FullInt::U(u) => Some(u), + } +} diff --git a/src/tools/clippy/clippy_lints/src/manual_retain.rs b/src/tools/clippy/clippy_lints/src/manual_retain.rs new file mode 100644 index 00000000000..c35e1e021ef --- /dev/null +++ b/src/tools/clippy/clippy_lints/src/manual_retain.rs @@ -0,0 +1,228 @@ +use clippy_utils::diagnostics::span_lint_and_sugg; +use clippy_utils::source::snippet; +use clippy_utils::ty::is_type_diagnostic_item; +use clippy_utils::{get_parent_expr, match_def_path, paths, SpanlessEq}; +use clippy_utils::{meets_msrv, msrvs}; +use rustc_errors::Applicability; +use rustc_hir as hir; +use rustc_hir::def_id::DefId; +use rustc_hir::ExprKind::Assign; +use rustc_lint::{LateContext, LateLintPass}; +use rustc_semver::RustcVersion; +use rustc_session::{declare_tool_lint, impl_lint_pass}; +use rustc_span::symbol::sym; + +const ACCEPTABLE_METHODS: [&[&str]; 4] = [ + &paths::HASHSET_ITER, + &paths::BTREESET_ITER, + &paths::SLICE_INTO, + &paths::VEC_DEQUE_ITER, +]; +const ACCEPTABLE_TYPES: [(rustc_span::Symbol, Option<RustcVersion>); 6] = [ + (sym::BTreeSet, Some(msrvs::BTREE_SET_RETAIN)), + (sym::BTreeMap, Some(msrvs::BTREE_MAP_RETAIN)), + (sym::HashSet, Some(msrvs::HASH_SET_RETAIN)), + (sym::HashMap, Some(msrvs::HASH_MAP_RETAIN)), + (sym::Vec, None), + (sym::VecDeque, None), +]; + +declare_clippy_lint! { + /// ### What it does + /// Checks for code to be replaced by `.retain()`. + /// ### Why is this bad? + /// `.retain()` is simpler and avoids needless allocation. + /// ### Example + /// ```rust + /// let mut vec = vec![0, 1, 2]; + /// vec = vec.iter().filter(|&x| x % 2 == 0).copied().collect(); + /// vec = vec.into_iter().filter(|x| x % 2 == 0).collect(); + /// ``` + /// Use instead: + /// ```rust + /// let mut vec = vec![0, 1, 2]; + /// vec.retain(|x| x % 2 == 0); + /// ``` + #[clippy::version = "1.63.0"] + pub MANUAL_RETAIN, + perf, + "`retain()` is simpler and the same functionalitys" +} + +pub struct ManualRetain { + msrv: Option<RustcVersion>, +} + +impl ManualRetain { + #[must_use] + pub fn new(msrv: Option<RustcVersion>) -> Self { + Self { msrv } + } +} + +impl_lint_pass!(ManualRetain => [MANUAL_RETAIN]); + +impl<'tcx> LateLintPass<'tcx> for ManualRetain { + fn check_expr(&mut self, cx: &LateContext<'tcx>, expr: &'tcx hir::Expr<'_>) { + if let Some(parent_expr) = get_parent_expr(cx, expr) + && let Assign(left_expr, collect_expr, _) = &parent_expr.kind + && let hir::ExprKind::MethodCall(seg, _, _) = &collect_expr.kind + && seg.args.is_none() + && let hir::ExprKind::MethodCall(_, [target_expr], _) = &collect_expr.kind + && let Some(collect_def_id) = cx.typeck_results().type_dependent_def_id(collect_expr.hir_id) + && match_def_path(cx, collect_def_id, &paths::CORE_ITER_COLLECT) { + check_into_iter(cx, parent_expr, left_expr, target_expr, self.msrv); + check_iter(cx, parent_expr, left_expr, target_expr, self.msrv); + check_to_owned(cx, parent_expr, left_expr, target_expr, self.msrv); + } + } + + extract_msrv_attr!(LateContext); +} + +fn check_into_iter( + cx: &LateContext<'_>, + parent_expr: &hir::Expr<'_>, + left_expr: &hir::Expr<'_>, + target_expr: &hir::Expr<'_>, + msrv: Option<RustcVersion>, +) { + if let hir::ExprKind::MethodCall(_, [into_iter_expr, _], _) = &target_expr.kind + && let Some(filter_def_id) = cx.typeck_results().type_dependent_def_id(target_expr.hir_id) + && match_def_path(cx, filter_def_id, &paths::CORE_ITER_FILTER) + && let hir::ExprKind::MethodCall(_, [struct_expr], _) = &into_iter_expr.kind + && let Some(into_iter_def_id) = cx.typeck_results().type_dependent_def_id(into_iter_expr.hir_id) + && match_def_path(cx, into_iter_def_id, &paths::CORE_ITER_INTO_ITER) + && match_acceptable_type(cx, left_expr, msrv) + && SpanlessEq::new(cx).eq_expr(left_expr, struct_expr) { + suggest(cx, parent_expr, left_expr, target_expr); + } +} + +fn check_iter( + cx: &LateContext<'_>, + parent_expr: &hir::Expr<'_>, + left_expr: &hir::Expr<'_>, + target_expr: &hir::Expr<'_>, + msrv: Option<RustcVersion>, +) { + if let hir::ExprKind::MethodCall(_, [filter_expr], _) = &target_expr.kind + && let Some(copied_def_id) = cx.typeck_results().type_dependent_def_id(target_expr.hir_id) + && (match_def_path(cx, copied_def_id, &paths::CORE_ITER_COPIED) + || match_def_path(cx, copied_def_id, &paths::CORE_ITER_CLONED)) + && let hir::ExprKind::MethodCall(_, [iter_expr, _], _) = &filter_expr.kind + && let Some(filter_def_id) = cx.typeck_results().type_dependent_def_id(filter_expr.hir_id) + && match_def_path(cx, filter_def_id, &paths::CORE_ITER_FILTER) + && let hir::ExprKind::MethodCall(_, [struct_expr], _) = &iter_expr.kind + && let Some(iter_expr_def_id) = cx.typeck_results().type_dependent_def_id(iter_expr.hir_id) + && match_acceptable_def_path(cx, iter_expr_def_id) + && match_acceptable_type(cx, left_expr, msrv) + && SpanlessEq::new(cx).eq_expr(left_expr, struct_expr) { + suggest(cx, parent_expr, left_expr, filter_expr); + } +} + +fn check_to_owned( + cx: &LateContext<'_>, + parent_expr: &hir::Expr<'_>, + left_expr: &hir::Expr<'_>, + target_expr: &hir::Expr<'_>, + msrv: Option<RustcVersion>, +) { + if meets_msrv(msrv, msrvs::STRING_RETAIN) + && let hir::ExprKind::MethodCall(_, [filter_expr], _) = &target_expr.kind + && let Some(to_owned_def_id) = cx.typeck_results().type_dependent_def_id(target_expr.hir_id) + && match_def_path(cx, to_owned_def_id, &paths::TO_OWNED_METHOD) + && let hir::ExprKind::MethodCall(_, [chars_expr, _], _) = &filter_expr.kind + && let Some(filter_def_id) = cx.typeck_results().type_dependent_def_id(filter_expr.hir_id) + && match_def_path(cx, filter_def_id, &paths::CORE_ITER_FILTER) + && let hir::ExprKind::MethodCall(_, [str_expr], _) = &chars_expr.kind + && let Some(chars_expr_def_id) = cx.typeck_results().type_dependent_def_id(chars_expr.hir_id) + && match_def_path(cx, chars_expr_def_id, &paths::STR_CHARS) + && let ty = cx.typeck_results().expr_ty(str_expr).peel_refs() + && is_type_diagnostic_item(cx, ty, sym::String) + && SpanlessEq::new(cx).eq_expr(left_expr, str_expr) { + suggest(cx, parent_expr, left_expr, filter_expr); + } +} + +fn suggest(cx: &LateContext<'_>, parent_expr: &hir::Expr<'_>, left_expr: &hir::Expr<'_>, filter_expr: &hir::Expr<'_>) { + if let hir::ExprKind::MethodCall(_, [_, closure], _) = filter_expr.kind + && let hir::ExprKind::Closure{ body, ..} = closure.kind + && let filter_body = cx.tcx.hir().body(body) + && let [filter_params] = filter_body.params + && let Some(sugg) = match filter_params.pat.kind { + hir::PatKind::Binding(_, _, filter_param_ident, None) => { + Some(format!("{}.retain(|{}| {})", snippet(cx, left_expr.span, ".."), filter_param_ident, snippet(cx, filter_body.value.span, ".."))) + }, + hir::PatKind::Tuple([key_pat, value_pat], _) => { + make_sugg(cx, key_pat, value_pat, left_expr, filter_body) + }, + hir::PatKind::Ref(pat, _) => { + match pat.kind { + hir::PatKind::Binding(_, _, filter_param_ident, None) => { + Some(format!("{}.retain(|{}| {})", snippet(cx, left_expr.span, ".."), filter_param_ident, snippet(cx, filter_body.value.span, ".."))) + }, + _ => None + } + }, + _ => None + } { + span_lint_and_sugg( + cx, + MANUAL_RETAIN, + parent_expr.span, + "this expression can be written more simply using `.retain()`", + "consider calling `.retain()` instead", + sugg, + Applicability::MachineApplicable + ); + } +} + +fn make_sugg( + cx: &LateContext<'_>, + key_pat: &rustc_hir::Pat<'_>, + value_pat: &rustc_hir::Pat<'_>, + left_expr: &hir::Expr<'_>, + filter_body: &hir::Body<'_>, +) -> Option<String> { + match (&key_pat.kind, &value_pat.kind) { + (hir::PatKind::Binding(_, _, key_param_ident, None), hir::PatKind::Binding(_, _, value_param_ident, None)) => { + Some(format!( + "{}.retain(|{}, &mut {}| {})", + snippet(cx, left_expr.span, ".."), + key_param_ident, + value_param_ident, + snippet(cx, filter_body.value.span, "..") + )) + }, + (hir::PatKind::Binding(_, _, key_param_ident, None), hir::PatKind::Wild) => Some(format!( + "{}.retain(|{}, _| {})", + snippet(cx, left_expr.span, ".."), + key_param_ident, + snippet(cx, filter_body.value.span, "..") + )), + (hir::PatKind::Wild, hir::PatKind::Binding(_, _, value_param_ident, None)) => Some(format!( + "{}.retain(|_, &mut {}| {})", + snippet(cx, left_expr.span, ".."), + value_param_ident, + snippet(cx, filter_body.value.span, "..") + )), + _ => None, + } +} + +fn match_acceptable_def_path(cx: &LateContext<'_>, collect_def_id: DefId) -> bool { + ACCEPTABLE_METHODS + .iter() + .any(|&method| match_def_path(cx, collect_def_id, method)) +} + +fn match_acceptable_type(cx: &LateContext<'_>, expr: &hir::Expr<'_>, msrv: Option<RustcVersion>) -> bool { + let expr_ty = cx.typeck_results().expr_ty(expr).peel_refs(); + ACCEPTABLE_TYPES.iter().any(|(ty, acceptable_msrv)| { + is_type_diagnostic_item(cx, expr_ty, *ty) + && acceptable_msrv.map_or(true, |acceptable_msrv| meets_msrv(msrv, acceptable_msrv)) + }) +} diff --git a/src/tools/clippy/clippy_lints/src/matches/match_same_arms.rs b/src/tools/clippy/clippy_lints/src/matches/match_same_arms.rs index 16fefea5520..15513de7d86 100644 --- a/src/tools/clippy/clippy_lints/src/matches/match_same_arms.rs +++ b/src/tools/clippy/clippy_lints/src/matches/match_same_arms.rs @@ -285,7 +285,7 @@ impl<'a> NormalizedPat<'a> { // TODO: Handle negative integers. They're currently treated as a wild match. ExprKind::Lit(lit) => match lit.node { LitKind::Str(sym, _) => Self::LitStr(sym), - LitKind::ByteStr(ref bytes) => Self::LitBytes(&**bytes), + LitKind::ByteStr(ref bytes) => Self::LitBytes(bytes), LitKind::Byte(val) => Self::LitInt(val.into()), LitKind::Char(val) => Self::LitInt(val.into()), LitKind::Int(val, _) => Self::LitInt(val), diff --git a/src/tools/clippy/clippy_lints/src/matches/match_single_binding.rs b/src/tools/clippy/clippy_lints/src/matches/match_single_binding.rs index 9df2db45dcf..5ae4a65acaf 100644 --- a/src/tools/clippy/clippy_lints/src/matches/match_single_binding.rs +++ b/src/tools/clippy/clippy_lints/src/matches/match_single_binding.rs @@ -55,7 +55,7 @@ pub(crate) fn check<'a>(cx: &LateContext<'a>, ex: &Expr<'a>, arms: &[Arm<'_>], e cx, (ex, expr), (bind_names, matched_vars), - &*snippet_body, + &snippet_body, &mut applicability, Some(span), ); @@ -88,7 +88,7 @@ pub(crate) fn check<'a>(cx: &LateContext<'a>, ex: &Expr<'a>, arms: &[Arm<'_>], e cx, (ex, expr), (bind_names, matched_vars), - &*snippet_body, + &snippet_body, &mut applicability, None, ); diff --git a/src/tools/clippy/clippy_lints/src/matches/match_str_case_mismatch.rs b/src/tools/clippy/clippy_lints/src/matches/match_str_case_mismatch.rs index 8302ce426e5..fa3b8d1fcea 100644 --- a/src/tools/clippy/clippy_lints/src/matches/match_str_case_mismatch.rs +++ b/src/tools/clippy/clippy_lints/src/matches/match_str_case_mismatch.rs @@ -118,7 +118,7 @@ fn lint(cx: &LateContext<'_>, case_method: &CaseMethod, bad_case_span: Span, bad MATCH_STR_CASE_MISMATCH, bad_case_span, "this `match` arm has a differing case than its expression", - &*format!("consider changing the case of this arm to respect `{}`", method_str), + &format!("consider changing the case of this arm to respect `{}`", method_str), format!("\"{}\"", suggestion), Applicability::MachineApplicable, ); diff --git a/src/tools/clippy/clippy_lints/src/matches/mod.rs b/src/tools/clippy/clippy_lints/src/matches/mod.rs index 3e765173fb9..b2a873ef582 100644 --- a/src/tools/clippy/clippy_lints/src/matches/mod.rs +++ b/src/tools/clippy/clippy_lints/src/matches/mod.rs @@ -791,7 +791,7 @@ declare_clippy_lint! { /// the match block and thus will not unlock. /// /// ### Example - /// ```rust.ignore + /// ```rust,ignore /// # use std::sync::Mutex; /// /// # struct State {} @@ -963,7 +963,7 @@ impl<'tcx> LateLintPass<'tcx> for Matches { return; } if matches!(source, MatchSource::Normal | MatchSource::ForLoopDesugar) { - significant_drop_in_scrutinee::check(cx, expr, ex, source); + significant_drop_in_scrutinee::check(cx, expr, ex, arms, source); } collapsible_match::check_match(cx, arms); diff --git a/src/tools/clippy/clippy_lints/src/matches/redundant_pattern_match.rs b/src/tools/clippy/clippy_lints/src/matches/redundant_pattern_match.rs index 0ea3f3b673b..8499e050af2 100644 --- a/src/tools/clippy/clippy_lints/src/matches/redundant_pattern_match.rs +++ b/src/tools/clippy/clippy_lints/src/matches/redundant_pattern_match.rs @@ -3,16 +3,13 @@ use clippy_utils::diagnostics::span_lint_and_then; use clippy_utils::source::snippet; use clippy_utils::sugg::Sugg; use clippy_utils::ty::needs_ordered_drop; -use clippy_utils::{higher, match_def_path}; -use clippy_utils::{is_lang_ctor, is_trait_method, paths}; +use clippy_utils::visitors::any_temporaries_need_ordered_drop; +use clippy_utils::{higher, is_lang_ctor, is_trait_method, match_def_path, paths}; use if_chain::if_chain; use rustc_ast::ast::LitKind; use rustc_errors::Applicability; use rustc_hir::LangItem::{OptionNone, PollPending}; -use rustc_hir::{ - intravisit::{walk_expr, Visitor}, - Arm, Block, Expr, ExprKind, Node, Pat, PatKind, QPath, UnOp, -}; +use rustc_hir::{Arm, Expr, ExprKind, Node, Pat, PatKind, QPath, UnOp}; use rustc_lint::LateContext; use rustc_middle::ty::{self, subst::GenericArgKind, DefIdTree, Ty}; use rustc_span::sym; @@ -47,79 +44,6 @@ fn try_get_generic_ty(ty: Ty<'_>, index: usize) -> Option<Ty<'_>> { } } -// Checks if there are any temporaries created in the given expression for which drop order -// matters. -fn temporaries_need_ordered_drop<'tcx>(cx: &LateContext<'tcx>, expr: &'tcx Expr<'tcx>) -> bool { - struct V<'a, 'tcx> { - cx: &'a LateContext<'tcx>, - res: bool, - } - impl<'a, 'tcx> Visitor<'tcx> for V<'a, 'tcx> { - fn visit_expr(&mut self, expr: &'tcx Expr<'tcx>) { - match expr.kind { - // Taking the reference of a value leaves a temporary - // e.g. In `&String::new()` the string is a temporary value. - // Remaining fields are temporary values - // e.g. In `(String::new(), 0).1` the string is a temporary value. - ExprKind::AddrOf(_, _, expr) | ExprKind::Field(expr, _) => { - if !matches!(expr.kind, ExprKind::Path(_)) { - if needs_ordered_drop(self.cx, self.cx.typeck_results().expr_ty(expr)) { - self.res = true; - } else { - self.visit_expr(expr); - } - } - }, - // the base type is always taken by reference. - // e.g. In `(vec![0])[0]` the vector is a temporary value. - ExprKind::Index(base, index) => { - if !matches!(base.kind, ExprKind::Path(_)) { - if needs_ordered_drop(self.cx, self.cx.typeck_results().expr_ty(base)) { - self.res = true; - } else { - self.visit_expr(base); - } - } - self.visit_expr(index); - }, - // Method calls can take self by reference. - // e.g. In `String::new().len()` the string is a temporary value. - ExprKind::MethodCall(_, [self_arg, args @ ..], _) => { - if !matches!(self_arg.kind, ExprKind::Path(_)) { - let self_by_ref = self - .cx - .typeck_results() - .type_dependent_def_id(expr.hir_id) - .map_or(false, |id| self.cx.tcx.fn_sig(id).skip_binder().inputs()[0].is_ref()); - if self_by_ref && needs_ordered_drop(self.cx, self.cx.typeck_results().expr_ty(self_arg)) { - self.res = true; - } else { - self.visit_expr(self_arg); - } - } - args.iter().for_each(|arg| self.visit_expr(arg)); - }, - // Either explicitly drops values, or changes control flow. - ExprKind::DropTemps(_) - | ExprKind::Ret(_) - | ExprKind::Break(..) - | ExprKind::Yield(..) - | ExprKind::Block(Block { expr: None, .. }, _) - | ExprKind::Loop(..) => (), - - // Only consider the final expression. - ExprKind::Block(Block { expr: Some(expr), .. }, _) => self.visit_expr(expr), - - _ => walk_expr(self, expr), - } - } - } - - let mut v = V { cx, res: false }; - v.visit_expr(expr); - v.res -} - fn find_sugg_for_if_let<'tcx>( cx: &LateContext<'tcx>, expr: &'tcx Expr<'_>, @@ -191,7 +115,7 @@ fn find_sugg_for_if_let<'tcx>( // scrutinee would be, so they have to be considered as well. // e.g. in `if let Some(x) = foo.lock().unwrap().baz.as_ref() { .. }` the lock will be held // for the duration if body. - let needs_drop = needs_ordered_drop(cx, check_ty) || temporaries_need_ordered_drop(cx, let_expr); + let needs_drop = needs_ordered_drop(cx, check_ty) || any_temporaries_need_ordered_drop(cx, let_expr); // check that `while_let_on_iterator` lint does not trigger if_chain! { @@ -362,9 +286,9 @@ fn find_good_method_for_match<'a>( .qpath_res(path_right, arms[1].pat.hir_id) .opt_def_id()?; let body_node_pair = if match_def_path(cx, left_id, expected_left) && match_def_path(cx, right_id, expected_right) { - (&(*arms[0].body).kind, &(*arms[1].body).kind) + (&arms[0].body.kind, &arms[1].body.kind) } else if match_def_path(cx, right_id, expected_left) && match_def_path(cx, right_id, expected_right) { - (&(*arms[1].body).kind, &(*arms[0].body).kind) + (&arms[1].body.kind, &arms[0].body.kind) } else { return None; }; diff --git a/src/tools/clippy/clippy_lints/src/matches/significant_drop_in_scrutinee.rs b/src/tools/clippy/clippy_lints/src/matches/significant_drop_in_scrutinee.rs index dcaf6f865de..0704a5af525 100644 --- a/src/tools/clippy/clippy_lints/src/matches/significant_drop_in_scrutinee.rs +++ b/src/tools/clippy/clippy_lints/src/matches/significant_drop_in_scrutinee.rs @@ -1,10 +1,10 @@ use crate::FxHashSet; use clippy_utils::diagnostics::span_lint_and_then; -use clippy_utils::get_attr; use clippy_utils::source::{indent_of, snippet}; +use clippy_utils::{get_attr, is_lint_allowed}; use rustc_errors::{Applicability, Diagnostic}; use rustc_hir::intravisit::{walk_expr, Visitor}; -use rustc_hir::{Expr, ExprKind, MatchSource}; +use rustc_hir::{Arm, Expr, ExprKind, MatchSource}; use rustc_lint::{LateContext, LintContext}; use rustc_middle::ty::subst::GenericArgKind; use rustc_middle::ty::{Ty, TypeAndMut}; @@ -16,12 +16,23 @@ pub(super) fn check<'tcx>( cx: &LateContext<'tcx>, expr: &'tcx Expr<'tcx>, scrutinee: &'tcx Expr<'_>, + arms: &'tcx [Arm<'_>], source: MatchSource, ) { + if is_lint_allowed(cx, SIGNIFICANT_DROP_IN_SCRUTINEE, expr.hir_id) { + return; + } + if let Some((suggestions, message)) = has_significant_drop_in_scrutinee(cx, scrutinee, source) { for found in suggestions { span_lint_and_then(cx, SIGNIFICANT_DROP_IN_SCRUTINEE, found.found_span, message, |diag| { set_diagnostic(diag, cx, expr, found); + let s = Span::new(expr.span.hi(), expr.span.hi(), expr.span.ctxt(), None); + diag.span_label(s, "temporary lives until here"); + for span in has_significant_drop_in_arms(cx, arms) { + diag.span_label(span, "another value with significant `Drop` created here"); + } + diag.note("this might lead to deadlocks or other unexpected behavior"); }); } } @@ -80,22 +91,77 @@ fn has_significant_drop_in_scrutinee<'tcx, 'a>( let mut helper = SigDropHelper::new(cx); helper.find_sig_drop(scrutinee).map(|drops| { let message = if source == MatchSource::Normal { - "temporary with significant drop in match scrutinee" + "temporary with significant `Drop` in `match` scrutinee will live until the end of the `match` expression" } else { - "temporary with significant drop in for loop" + "temporary with significant `Drop` in `for` loop condition will live until the end of the `for` expression" }; (drops, message) }) } +struct SigDropChecker<'a, 'tcx> { + seen_types: FxHashSet<Ty<'tcx>>, + cx: &'a LateContext<'tcx>, +} + +impl<'a, 'tcx> SigDropChecker<'a, 'tcx> { + fn new(cx: &'a LateContext<'tcx>) -> SigDropChecker<'a, 'tcx> { + SigDropChecker { + seen_types: FxHashSet::default(), + cx, + } + } + + fn get_type(&self, ex: &'tcx Expr<'_>) -> Ty<'tcx> { + self.cx.typeck_results().expr_ty(ex) + } + + fn has_seen_type(&mut self, ty: Ty<'tcx>) -> bool { + !self.seen_types.insert(ty) + } + + fn has_sig_drop_attr(&mut self, cx: &LateContext<'tcx>, ty: Ty<'tcx>) -> bool { + if let Some(adt) = ty.ty_adt_def() { + if get_attr(cx.sess(), cx.tcx.get_attrs_unchecked(adt.did()), "has_significant_drop").count() > 0 { + return true; + } + } + + match ty.kind() { + rustc_middle::ty::Adt(a, b) => { + for f in a.all_fields() { + let ty = f.ty(cx.tcx, b); + if !self.has_seen_type(ty) && self.has_sig_drop_attr(cx, ty) { + return true; + } + } + + for generic_arg in b.iter() { + if let GenericArgKind::Type(ty) = generic_arg.unpack() { + if self.has_sig_drop_attr(cx, ty) { + return true; + } + } + } + false + }, + rustc_middle::ty::Array(ty, _) + | rustc_middle::ty::RawPtr(TypeAndMut { ty, .. }) + | rustc_middle::ty::Ref(_, ty, _) + | rustc_middle::ty::Slice(ty) => self.has_sig_drop_attr(cx, *ty), + _ => false, + } + } +} + struct SigDropHelper<'a, 'tcx> { cx: &'a LateContext<'tcx>, is_chain_end: bool, - seen_types: FxHashSet<Ty<'tcx>>, has_significant_drop: bool, current_sig_drop: Option<FoundSigDrop>, sig_drop_spans: Option<Vec<FoundSigDrop>>, special_handling_for_binary_op: bool, + sig_drop_checker: SigDropChecker<'a, 'tcx>, } #[expect(clippy::enum_variant_names)] @@ -118,11 +184,11 @@ impl<'a, 'tcx> SigDropHelper<'a, 'tcx> { SigDropHelper { cx, is_chain_end: true, - seen_types: FxHashSet::default(), has_significant_drop: false, current_sig_drop: None, sig_drop_spans: None, special_handling_for_binary_op: false, + sig_drop_checker: SigDropChecker::new(cx), } } @@ -163,7 +229,7 @@ impl<'a, 'tcx> SigDropHelper<'a, 'tcx> { if self.current_sig_drop.is_some() { return; } - let ty = self.get_type(expr); + let ty = self.sig_drop_checker.get_type(expr); if ty.is_ref() { // We checked that the type was ref, so builtin_deref will return Some TypeAndMut, // but let's avoid any chance of an ICE @@ -187,14 +253,6 @@ impl<'a, 'tcx> SigDropHelper<'a, 'tcx> { } } - fn get_type(&self, ex: &'tcx Expr<'_>) -> Ty<'tcx> { - self.cx.typeck_results().expr_ty(ex) - } - - fn has_seen_type(&mut self, ty: Ty<'tcx>) -> bool { - !self.seen_types.insert(ty) - } - fn visit_exprs_for_binary_ops( &mut self, left: &'tcx Expr<'_>, @@ -214,44 +272,15 @@ impl<'a, 'tcx> SigDropHelper<'a, 'tcx> { self.special_handling_for_binary_op = false; } - - fn has_sig_drop_attr(&mut self, cx: &LateContext<'tcx>, ty: Ty<'tcx>) -> bool { - if let Some(adt) = ty.ty_adt_def() { - if get_attr(cx.sess(), cx.tcx.get_attrs_unchecked(adt.did()), "has_significant_drop").count() > 0 { - return true; - } - } - - match ty.kind() { - rustc_middle::ty::Adt(a, b) => { - for f in a.all_fields() { - let ty = f.ty(cx.tcx, b); - if !self.has_seen_type(ty) && self.has_sig_drop_attr(cx, ty) { - return true; - } - } - - for generic_arg in b.iter() { - if let GenericArgKind::Type(ty) = generic_arg.unpack() { - if self.has_sig_drop_attr(cx, ty) { - return true; - } - } - } - false - }, - rustc_middle::ty::Array(ty, _) - | rustc_middle::ty::RawPtr(TypeAndMut { ty, .. }) - | rustc_middle::ty::Ref(_, ty, _) - | rustc_middle::ty::Slice(ty) => self.has_sig_drop_attr(cx, *ty), - _ => false, - } - } } impl<'a, 'tcx> Visitor<'tcx> for SigDropHelper<'a, 'tcx> { fn visit_expr(&mut self, ex: &'tcx Expr<'_>) { - if !self.is_chain_end && self.has_sig_drop_attr(self.cx, self.get_type(ex)) { + if !self.is_chain_end + && self + .sig_drop_checker + .has_sig_drop_attr(self.cx, self.sig_drop_checker.get_type(ex)) + { self.has_significant_drop = true; return; } @@ -330,3 +359,38 @@ impl<'a, 'tcx> Visitor<'tcx> for SigDropHelper<'a, 'tcx> { } } } + +struct ArmSigDropHelper<'a, 'tcx> { + sig_drop_checker: SigDropChecker<'a, 'tcx>, + found_sig_drop_spans: FxHashSet<Span>, +} + +impl<'a, 'tcx> ArmSigDropHelper<'a, 'tcx> { + fn new(cx: &'a LateContext<'tcx>) -> ArmSigDropHelper<'a, 'tcx> { + ArmSigDropHelper { + sig_drop_checker: SigDropChecker::new(cx), + found_sig_drop_spans: FxHashSet::<Span>::default(), + } + } +} + +fn has_significant_drop_in_arms<'tcx, 'a>(cx: &'a LateContext<'tcx>, arms: &'tcx [Arm<'_>]) -> FxHashSet<Span> { + let mut helper = ArmSigDropHelper::new(cx); + for arm in arms { + helper.visit_expr(arm.body); + } + helper.found_sig_drop_spans +} + +impl<'a, 'tcx> Visitor<'tcx> for ArmSigDropHelper<'a, 'tcx> { + fn visit_expr(&mut self, ex: &'tcx Expr<'tcx>) { + if self + .sig_drop_checker + .has_sig_drop_attr(self.sig_drop_checker.cx, self.sig_drop_checker.get_type(ex)) + { + self.found_sig_drop_spans.insert(ex.span); + return; + } + walk_expr(self, ex); + } +} diff --git a/src/tools/clippy/clippy_lints/src/matches/single_match.rs b/src/tools/clippy/clippy_lints/src/matches/single_match.rs index 0c4cb45d147..92091a0c339 100644 --- a/src/tools/clippy/clippy_lints/src/matches/single_match.rs +++ b/src/tools/clippy/clippy_lints/src/matches/single_match.rs @@ -140,70 +140,45 @@ fn check_opt_like<'a>( ty: Ty<'a>, els: Option<&Expr<'_>>, ) { - // list of candidate `Enum`s we know will never get any more members - let candidates = &[ - (&paths::COW, "Borrowed"), - (&paths::COW, "Cow::Borrowed"), - (&paths::COW, "Cow::Owned"), - (&paths::COW, "Owned"), - (&paths::OPTION, "None"), - (&paths::RESULT, "Err"), - (&paths::RESULT, "Ok"), - ]; - - // We want to suggest to exclude an arm that contains only wildcards or forms the exhaustive - // match with the second branch, without enum variants in matches. - if !contains_only_wilds(arms[1].pat) && !form_exhaustive_matches(arms[0].pat, arms[1].pat) { - return; + // We don't want to lint if the second arm contains an enum which could + // have more variants in the future. + if form_exhaustive_matches(cx, ty, arms[0].pat, arms[1].pat) { + report_single_pattern(cx, ex, arms, expr, els); } +} +/// Returns `true` if all of the types in the pattern are enums which we know +/// won't be expanded in the future +fn pat_in_candidate_enum<'a>(cx: &LateContext<'a>, ty: Ty<'a>, pat: &Pat<'_>) -> bool { let mut paths_and_types = Vec::new(); - if !collect_pat_paths(&mut paths_and_types, cx, arms[1].pat, ty) { - return; - } + collect_pat_paths(&mut paths_and_types, cx, pat, ty); + paths_and_types.iter().all(|ty| in_candidate_enum(cx, *ty)) +} - let in_candidate_enum = |path_info: &(String, Ty<'_>)| -> bool { - let (path, ty) = path_info; - for &(ty_path, pat_path) in candidates { - if path == pat_path && match_type(cx, *ty, ty_path) { - return true; - } +/// Returns `true` if the given type is an enum we know won't be expanded in the future +fn in_candidate_enum<'a>(cx: &LateContext<'a>, ty: Ty<'_>) -> bool { + // list of candidate `Enum`s we know will never get any more members + let candidates = [&paths::COW, &paths::OPTION, &paths::RESULT]; + + for candidate_ty in candidates { + if match_type(cx, ty, candidate_ty) { + return true; } - false - }; - if paths_and_types.iter().all(in_candidate_enum) { - report_single_pattern(cx, ex, arms, expr, els); } + false } -/// Collects paths and their types from the given patterns. Returns true if the given pattern could -/// be simplified, false otherwise. -fn collect_pat_paths<'a>(acc: &mut Vec<(String, Ty<'a>)>, cx: &LateContext<'a>, pat: &Pat<'_>, ty: Ty<'a>) -> bool { +/// Collects types from the given pattern +fn collect_pat_paths<'a>(acc: &mut Vec<Ty<'a>>, cx: &LateContext<'a>, pat: &Pat<'_>, ty: Ty<'a>) { match pat.kind { - PatKind::Wild => true, - PatKind::Tuple(inner, _) => inner.iter().all(|p| { + PatKind::Tuple(inner, _) => inner.iter().for_each(|p| { let p_ty = cx.typeck_results().pat_ty(p); - collect_pat_paths(acc, cx, p, p_ty) + collect_pat_paths(acc, cx, p, p_ty); }), - PatKind::TupleStruct(ref path, ..) => { - let path = rustc_hir_pretty::to_string(rustc_hir_pretty::NO_ANN, |s| { - s.print_qpath(path, false); - }); - acc.push((path, ty)); - true - }, - PatKind::Binding(BindingAnnotation::Unannotated, .., ident, None) => { - acc.push((ident.to_string(), ty)); - true + PatKind::TupleStruct(..) | PatKind::Binding(BindingAnnotation::Unannotated, .., None) | PatKind::Path(_) => { + acc.push(ty); }, - PatKind::Path(ref path) => { - let path = rustc_hir_pretty::to_string(rustc_hir_pretty::NO_ANN, |s| { - s.print_qpath(path, false); - }); - acc.push((path, ty)); - true - }, - _ => false, + _ => {}, } } @@ -218,7 +193,7 @@ fn contains_only_wilds(pat: &Pat<'_>) -> bool { /// Returns true if the given patterns forms only exhaustive matches that don't contain enum /// patterns without a wildcard. -fn form_exhaustive_matches(left: &Pat<'_>, right: &Pat<'_>) -> bool { +fn form_exhaustive_matches<'a>(cx: &LateContext<'a>, ty: Ty<'a>, left: &Pat<'_>, right: &Pat<'_>) -> bool { match (&left.kind, &right.kind) { (PatKind::Wild, _) | (_, PatKind::Wild) => true, (PatKind::Tuple(left_in, left_pos), PatKind::Tuple(right_in, right_pos)) => { @@ -264,6 +239,10 @@ fn form_exhaustive_matches(left: &Pat<'_>, right: &Pat<'_>) -> bool { } true }, + (PatKind::TupleStruct(..), PatKind::Path(_)) => pat_in_candidate_enum(cx, ty, right), + (PatKind::TupleStruct(..), PatKind::TupleStruct(_, inner, _)) => { + pat_in_candidate_enum(cx, ty, right) && inner.iter().all(contains_only_wilds) + }, _ => false, } } diff --git a/src/tools/clippy/clippy_lints/src/methods/iter_skip_next.rs b/src/tools/clippy/clippy_lints/src/methods/iter_skip_next.rs index f5410c7fd7f..43e9451f7d3 100644 --- a/src/tools/clippy/clippy_lints/src/methods/iter_skip_next.rs +++ b/src/tools/clippy/clippy_lints/src/methods/iter_skip_next.rs @@ -22,7 +22,7 @@ pub(super) fn check(cx: &LateContext<'_>, expr: &hir::Expr<'_>, recv: &hir::Expr |diag| { if_chain! { if let Some(id) = path_to_local(recv); - if let Node::Binding(pat) = cx.tcx.hir().get(id); + if let Node::Pat(pat) = cx.tcx.hir().get(id); if let PatKind::Binding(ann, _, _, _) = pat.kind; if ann != BindingAnnotation::Mutable; then { 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 8ae84dbb3dc..13853dec99d 100644 --- a/src/tools/clippy/clippy_lints/src/methods/map_flatten.rs +++ b/src/tools/clippy/clippy_lints/src/methods/map_flatten.rs @@ -14,14 +14,17 @@ 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 closure_snippet = snippet_with_applicability(cx, map_arg.span, "..", &mut applicability); span_lint_and_sugg( cx, MAP_FLATTEN, expr.span.with_lo(map_span.lo()), &format!("called `map(..).flatten()` on `{}`", caller_ty_name), - &format!("try replacing `map` with `{}` and remove the `.flatten()`", method_to_use), + &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/misc.rs b/src/tools/clippy/clippy_lints/src/misc.rs index 01bf871198a..df2430ced6b 100644 --- a/src/tools/clippy/clippy_lints/src/misc.rs +++ b/src/tools/clippy/clippy_lints/src/misc.rs @@ -1,28 +1,21 @@ -use clippy_utils::diagnostics::{span_lint, span_lint_and_sugg, span_lint_and_then, span_lint_hir_and_then}; +use clippy_utils::diagnostics::{span_lint, span_lint_and_sugg, span_lint_hir_and_then}; use clippy_utils::source::{snippet, snippet_opt}; -use clippy_utils::ty::{implements_trait, is_copy}; use if_chain::if_chain; use rustc_ast::ast::LitKind; use rustc_errors::Applicability; use rustc_hir::intravisit::FnKind; use rustc_hir::{ self as hir, def, BinOpKind, BindingAnnotation, Body, Expr, ExprKind, FnDecl, HirId, Mutability, PatKind, Stmt, - StmtKind, TyKind, UnOp, + StmtKind, TyKind, }; use rustc_lint::{LateContext, LateLintPass}; use rustc_middle::lint::in_external_macro; -use rustc_middle::ty::{self, Ty}; use rustc_session::{declare_lint_pass, declare_tool_lint}; use rustc_span::hygiene::DesugaringKind; use rustc_span::source_map::{ExpnKind, Span}; -use rustc_span::symbol::sym; -use clippy_utils::consts::{constant, Constant}; use clippy_utils::sugg::Sugg; -use clippy_utils::{ - get_item_name, get_parent_expr, in_constant, is_integer_const, iter_input_pats, last_path_segment, - match_any_def_paths, path_def_id, paths, unsext, SpanlessEq, -}; +use clippy_utils::{get_parent_expr, in_constant, iter_input_pats, last_path_segment, SpanlessEq}; declare_clippy_lint! { /// ### What it does @@ -58,122 +51,6 @@ declare_clippy_lint! { style, "an entire binding declared as `ref`, in a function argument or a `let` statement" } - -declare_clippy_lint! { - /// ### What it does - /// Checks for comparisons to NaN. - /// - /// ### Why is this bad? - /// NaN does not compare meaningfully to anything – not - /// even itself – so those comparisons are simply wrong. - /// - /// ### Example - /// ```rust - /// # let x = 1.0; - /// if x == f32::NAN { } - /// ``` - /// - /// Use instead: - /// ```rust - /// # let x = 1.0f32; - /// if x.is_nan() { } - /// ``` - #[clippy::version = "pre 1.29.0"] - pub CMP_NAN, - correctness, - "comparisons to `NAN`, which will always return false, probably not intended" -} - -declare_clippy_lint! { - /// ### What it does - /// Checks for (in-)equality comparisons on floating-point - /// values (apart from zero), except in functions called `*eq*` (which probably - /// implement equality for a type involving floats). - /// - /// ### Why is this bad? - /// Floating point calculations are usually imprecise, so - /// asking if two values are *exactly* equal is asking for trouble. For a good - /// guide on what to do, see [the floating point - /// guide](http://www.floating-point-gui.de/errors/comparison). - /// - /// ### Example - /// ```rust - /// let x = 1.2331f64; - /// let y = 1.2332f64; - /// - /// if y == 1.23f64 { } - /// if y != x {} // where both are floats - /// ``` - /// - /// Use instead: - /// ```rust - /// # let x = 1.2331f64; - /// # let y = 1.2332f64; - /// let error_margin = f64::EPSILON; // Use an epsilon for comparison - /// // Or, if Rust <= 1.42, use `std::f64::EPSILON` constant instead. - /// // let error_margin = std::f64::EPSILON; - /// if (y - 1.23f64).abs() < error_margin { } - /// if (y - x).abs() > error_margin { } - /// ``` - #[clippy::version = "pre 1.29.0"] - pub FLOAT_CMP, - pedantic, - "using `==` or `!=` on float values instead of comparing difference with an epsilon" -} - -declare_clippy_lint! { - /// ### What it does - /// Checks for conversions to owned values just for the sake - /// of a comparison. - /// - /// ### Why is this bad? - /// The comparison can operate on a reference, so creating - /// an owned value effectively throws it away directly afterwards, which is - /// needlessly consuming code and heap space. - /// - /// ### Example - /// ```rust - /// # let x = "foo"; - /// # let y = String::from("foo"); - /// if x.to_owned() == y {} - /// ``` - /// - /// Use instead: - /// ```rust - /// # let x = "foo"; - /// # let y = String::from("foo"); - /// if x == y {} - /// ``` - #[clippy::version = "pre 1.29.0"] - pub CMP_OWNED, - perf, - "creating owned instances for comparing with others, e.g., `x == \"foo\".to_string()`" -} - -declare_clippy_lint! { - /// ### What it does - /// Checks for getting the remainder of a division by one or minus - /// one. - /// - /// ### Why is this bad? - /// The result for a divisor of one can only ever be zero; for - /// minus one it can cause panic/overflow (if the left operand is the minimal value of - /// the respective integer type) or results in zero. No one will write such code - /// deliberately, unless trying to win an Underhanded Rust Contest. Even for that - /// contest, it's probably a bad idea. Use something more underhanded. - /// - /// ### Example - /// ```rust - /// # let x = 1; - /// let a = x % 1; - /// let a = x % -1; - /// ``` - #[clippy::version = "pre 1.29.0"] - pub MODULO_ONE, - correctness, - "taking a number modulo +/-1, which can either panic/overflow or always returns 0" -} - declare_clippy_lint! { /// ### What it does /// Checks for the use of bindings with a single leading @@ -244,51 +121,11 @@ declare_clippy_lint! { "using `0 as *{const, mut} T`" } -declare_clippy_lint! { - /// ### What it does - /// Checks for (in-)equality comparisons on floating-point - /// value and constant, except in functions called `*eq*` (which probably - /// implement equality for a type involving floats). - /// - /// ### Why is this bad? - /// Floating point calculations are usually imprecise, so - /// asking if two values are *exactly* equal is asking for trouble. For a good - /// guide on what to do, see [the floating point - /// guide](http://www.floating-point-gui.de/errors/comparison). - /// - /// ### Example - /// ```rust - /// let x: f64 = 1.0; - /// const ONE: f64 = 1.00; - /// - /// if x == ONE { } // where both are floats - /// ``` - /// - /// Use instead: - /// ```rust - /// # let x: f64 = 1.0; - /// # const ONE: f64 = 1.00; - /// let error_margin = f64::EPSILON; // Use an epsilon for comparison - /// // Or, if Rust <= 1.42, use `std::f64::EPSILON` constant instead. - /// // let error_margin = std::f64::EPSILON; - /// if (x - ONE).abs() < error_margin { } - /// ``` - #[clippy::version = "pre 1.29.0"] - pub FLOAT_CMP_CONST, - restriction, - "using `==` or `!=` on float constants instead of comparing difference with an epsilon" -} - declare_lint_pass!(MiscLints => [ TOPLEVEL_REF_ARG, - CMP_NAN, - FLOAT_CMP, - CMP_OWNED, - MODULO_ONE, USED_UNDERSCORE_BINDING, SHORT_CIRCUIT_STATEMENT, ZERO_PTR, - FLOAT_CMP_CONST ]); impl<'tcx> LateLintPass<'tcx> for MiscLints { @@ -398,16 +235,9 @@ impl<'tcx> LateLintPass<'tcx> for MiscLints { } fn check_expr(&mut self, cx: &LateContext<'tcx>, expr: &'tcx Expr<'_>) { - match expr.kind { - ExprKind::Cast(e, ty) => { - check_cast(cx, expr.span, e, ty); - return; - }, - ExprKind::Binary(ref cmp, left, right) => { - check_binary(cx, expr, cmp, left, right); - return; - }, - _ => {}, + if let ExprKind::Cast(e, ty) = expr.kind { + check_cast(cx, expr.span, e, ty); + return; } if in_attributes_expansion(expr) || expr.span.is_desugaring(DesugaringKind::Await) { // Don't lint things expanded by #[derive(...)], etc or `await` desugaring @@ -455,236 +285,6 @@ impl<'tcx> LateLintPass<'tcx> for MiscLints { } } -fn get_lint_and_message( - is_comparing_constants: bool, - is_comparing_arrays: bool, -) -> (&'static rustc_lint::Lint, &'static str) { - if is_comparing_constants { - ( - FLOAT_CMP_CONST, - if is_comparing_arrays { - "strict comparison of `f32` or `f64` constant arrays" - } else { - "strict comparison of `f32` or `f64` constant" - }, - ) - } else { - ( - FLOAT_CMP, - if is_comparing_arrays { - "strict comparison of `f32` or `f64` arrays" - } else { - "strict comparison of `f32` or `f64`" - }, - ) - } -} - -fn check_nan(cx: &LateContext<'_>, expr: &Expr<'_>, cmp_expr: &Expr<'_>) { - if_chain! { - if !in_constant(cx, cmp_expr.hir_id); - if let Some((value, _)) = constant(cx, cx.typeck_results(), expr); - if match value { - Constant::F32(num) => num.is_nan(), - Constant::F64(num) => num.is_nan(), - _ => false, - }; - then { - span_lint( - cx, - CMP_NAN, - cmp_expr.span, - "doomed comparison with `NAN`, use `{f32,f64}::is_nan()` instead", - ); - } - } -} - -fn is_named_constant<'tcx>(cx: &LateContext<'tcx>, expr: &'tcx Expr<'_>) -> bool { - if let Some((_, res)) = constant(cx, cx.typeck_results(), expr) { - res - } else { - false - } -} - -fn is_allowed<'tcx>(cx: &LateContext<'tcx>, expr: &'tcx Expr<'_>) -> bool { - match constant(cx, cx.typeck_results(), expr) { - Some((Constant::F32(f), _)) => f == 0.0 || f.is_infinite(), - Some((Constant::F64(f), _)) => f == 0.0 || f.is_infinite(), - Some((Constant::Vec(vec), _)) => vec.iter().all(|f| match f { - Constant::F32(f) => *f == 0.0 || (*f).is_infinite(), - Constant::F64(f) => *f == 0.0 || (*f).is_infinite(), - _ => false, - }), - _ => false, - } -} - -// Return true if `expr` is the result of `signum()` invoked on a float value. -fn is_signum(cx: &LateContext<'_>, expr: &Expr<'_>) -> bool { - // The negation of a signum is still a signum - if let ExprKind::Unary(UnOp::Neg, child_expr) = expr.kind { - return is_signum(cx, child_expr); - } - - if_chain! { - if let ExprKind::MethodCall(method_name, [ref self_arg, ..], _) = expr.kind; - if sym!(signum) == method_name.ident.name; - // Check that the receiver of the signum() is a float (expressions[0] is the receiver of - // the method call) - then { - return is_float(cx, self_arg); - } - } - false -} - -fn is_float(cx: &LateContext<'_>, expr: &Expr<'_>) -> bool { - let value = &cx.typeck_results().expr_ty(expr).peel_refs().kind(); - - if let ty::Array(arr_ty, _) = value { - return matches!(arr_ty.kind(), ty::Float(_)); - }; - - matches!(value, ty::Float(_)) -} - -fn is_array(cx: &LateContext<'_>, expr: &Expr<'_>) -> bool { - matches!(&cx.typeck_results().expr_ty(expr).peel_refs().kind(), ty::Array(_, _)) -} - -#[expect(clippy::too_many_lines)] -fn check_to_owned(cx: &LateContext<'_>, expr: &Expr<'_>, other: &Expr<'_>, left: bool) { - #[derive(Default)] - struct EqImpl { - ty_eq_other: bool, - other_eq_ty: bool, - } - - impl EqImpl { - fn is_implemented(&self) -> bool { - self.ty_eq_other || self.other_eq_ty - } - } - - fn symmetric_partial_eq<'tcx>(cx: &LateContext<'tcx>, ty: Ty<'tcx>, other: Ty<'tcx>) -> Option<EqImpl> { - cx.tcx.lang_items().eq_trait().map(|def_id| EqImpl { - ty_eq_other: implements_trait(cx, ty, def_id, &[other.into()]), - other_eq_ty: implements_trait(cx, other, def_id, &[ty.into()]), - }) - } - - let typeck = cx.typeck_results(); - let (arg, arg_span) = match expr.kind { - ExprKind::MethodCall(.., [arg], _) - if typeck - .type_dependent_def_id(expr.hir_id) - .and_then(|id| cx.tcx.trait_of_item(id)) - .map_or(false, |id| { - matches!(cx.tcx.get_diagnostic_name(id), Some(sym::ToString | sym::ToOwned)) - }) => - { - (arg, arg.span) - }, - ExprKind::Call(path, [arg]) - if path_def_id(cx, path) - .and_then(|id| match_any_def_paths(cx, id, &[&paths::FROM_STR_METHOD, &paths::FROM_FROM])) - .map_or(false, |idx| match idx { - 0 => true, - 1 => !is_copy(cx, typeck.expr_ty(expr)), - _ => false, - }) => - { - (arg, arg.span) - }, - _ => return, - }; - - let arg_ty = typeck.expr_ty(arg); - let other_ty = typeck.expr_ty(other); - - let without_deref = symmetric_partial_eq(cx, arg_ty, other_ty).unwrap_or_default(); - let with_deref = arg_ty - .builtin_deref(true) - .and_then(|tam| symmetric_partial_eq(cx, tam.ty, other_ty)) - .unwrap_or_default(); - - if !with_deref.is_implemented() && !without_deref.is_implemented() { - return; - } - - let other_gets_derefed = matches!(other.kind, ExprKind::Unary(UnOp::Deref, _)); - - let lint_span = if other_gets_derefed { - expr.span.to(other.span) - } else { - expr.span - }; - - span_lint_and_then( - cx, - CMP_OWNED, - lint_span, - "this creates an owned instance just for comparison", - |diag| { - // This also catches `PartialEq` implementations that call `to_owned`. - if other_gets_derefed { - diag.span_label(lint_span, "try implementing the comparison without allocating"); - return; - } - - let arg_snip = snippet(cx, arg_span, ".."); - let expr_snip; - let eq_impl; - if with_deref.is_implemented() { - expr_snip = format!("*{}", arg_snip); - eq_impl = with_deref; - } else { - expr_snip = arg_snip.to_string(); - eq_impl = without_deref; - }; - - let span; - let hint; - if (eq_impl.ty_eq_other && left) || (eq_impl.other_eq_ty && !left) { - span = expr.span; - hint = expr_snip; - } else { - span = expr.span.to(other.span); - - let cmp_span = if other.span < expr.span { - other.span.between(expr.span) - } else { - expr.span.between(other.span) - }; - if eq_impl.ty_eq_other { - hint = format!( - "{}{}{}", - expr_snip, - snippet(cx, cmp_span, ".."), - snippet(cx, other.span, "..") - ); - } else { - hint = format!( - "{}{}{}", - snippet(cx, other.span, ".."), - snippet(cx, cmp_span, ".."), - expr_snip - ); - } - } - - diag.span_suggestion( - span, - "try", - hint, - Applicability::MachineApplicable, // snippet - ); - }, - ); -} - /// Heuristic to see if an expression is used. Should be compatible with /// `unused_variables`'s idea /// of what it means for an expression to be "used". @@ -740,74 +340,3 @@ fn check_cast(cx: &LateContext<'_>, span: Span, e: &Expr<'_>, ty: &hir::Ty<'_>) } } } - -fn check_binary<'a>( - cx: &LateContext<'a>, - expr: &Expr<'_>, - cmp: &rustc_span::source_map::Spanned<rustc_hir::BinOpKind>, - left: &'a Expr<'_>, - right: &'a Expr<'_>, -) { - let op = cmp.node; - if op.is_comparison() { - check_nan(cx, left, expr); - check_nan(cx, right, expr); - check_to_owned(cx, left, right, true); - check_to_owned(cx, right, left, false); - } - if (op == BinOpKind::Eq || op == BinOpKind::Ne) && (is_float(cx, left) || is_float(cx, right)) { - if is_allowed(cx, left) || is_allowed(cx, right) { - return; - } - - // Allow comparing the results of signum() - if is_signum(cx, left) && is_signum(cx, right) { - return; - } - - if let Some(name) = get_item_name(cx, expr) { - let name = name.as_str(); - if name == "eq" || name == "ne" || name == "is_nan" || name.starts_with("eq_") || name.ends_with("_eq") { - return; - } - } - let is_comparing_arrays = is_array(cx, left) || is_array(cx, right); - let (lint, msg) = get_lint_and_message( - is_named_constant(cx, left) || is_named_constant(cx, right), - is_comparing_arrays, - ); - span_lint_and_then(cx, lint, expr.span, msg, |diag| { - let lhs = Sugg::hir(cx, left, ".."); - let rhs = Sugg::hir(cx, right, ".."); - - if !is_comparing_arrays { - diag.span_suggestion( - expr.span, - "consider comparing them within some margin of error", - format!( - "({}).abs() {} error_margin", - lhs - rhs, - if op == BinOpKind::Eq { '<' } else { '>' } - ), - Applicability::HasPlaceholders, // snippet - ); - } - diag.note("`f32::EPSILON` and `f64::EPSILON` are available for the `error_margin`"); - }); - } else if op == BinOpKind::Rem { - if is_integer_const(cx, right, 1) { - span_lint(cx, MODULO_ONE, expr.span, "any number modulo 1 will be 0"); - } - - if let ty::Int(ity) = cx.typeck_results().expr_ty(right).kind() { - if is_integer_const(cx, right, unsext(cx.tcx, -1, *ity)) { - span_lint( - cx, - MODULO_ONE, - expr.span, - "any number modulo -1 will panic/overflow or result in 0", - ); - } - }; - } -} diff --git a/src/tools/clippy/clippy_lints/src/mut_key.rs b/src/tools/clippy/clippy_lints/src/mut_key.rs index 7e2531c7ca5..4db103bbc13 100644 --- a/src/tools/clippy/clippy_lints/src/mut_key.rs +++ b/src/tools/clippy/clippy_lints/src/mut_key.rs @@ -2,7 +2,7 @@ use clippy_utils::diagnostics::span_lint; use clippy_utils::trait_ref_of_method; use rustc_hir as hir; use rustc_lint::{LateContext, LateLintPass}; -use rustc_middle::ty::TypeFoldable; +use rustc_middle::ty::TypeVisitable; use rustc_middle::ty::{Adt, Array, Ref, Slice, Tuple, Ty}; use rustc_session::{declare_lint_pass, declare_tool_lint}; use rustc_span::source_map::Span; diff --git a/src/tools/clippy/clippy_lints/src/needless_bitwise_bool.rs b/src/tools/clippy/clippy_lints/src/needless_bitwise_bool.rs deleted file mode 100644 index 623d22bc9bd..00000000000 --- a/src/tools/clippy/clippy_lints/src/needless_bitwise_bool.rs +++ /dev/null @@ -1,85 +0,0 @@ -use clippy_utils::diagnostics::span_lint_and_then; -use clippy_utils::source::snippet_opt; -use if_chain::if_chain; -use rustc_errors::Applicability; -use rustc_hir::{BinOpKind, Expr, ExprKind}; -use rustc_lint::{LateContext, LateLintPass}; -use rustc_middle::ty; -use rustc_session::{declare_lint_pass, declare_tool_lint}; - -declare_clippy_lint! { - /// ### What it does - /// Checks for uses of bitwise and/or operators between booleans, where performance may be improved by using - /// a lazy and. - /// - /// ### Why is this bad? - /// The bitwise operators do not support short-circuiting, so it may hinder code performance. - /// Additionally, boolean logic "masked" as bitwise logic is not caught by lints like `unnecessary_fold` - /// - /// ### Known problems - /// This lint evaluates only when the right side is determined to have no side effects. At this time, that - /// determination is quite conservative. - /// - /// ### Example - /// ```rust - /// let (x,y) = (true, false); - /// if x & !y {} // where both x and y are booleans - /// ``` - /// Use instead: - /// ```rust - /// let (x,y) = (true, false); - /// if x && !y {} - /// ``` - #[clippy::version = "1.54.0"] - pub NEEDLESS_BITWISE_BOOL, - pedantic, - "Boolean expressions that use bitwise rather than lazy operators" -} - -declare_lint_pass!(NeedlessBitwiseBool => [NEEDLESS_BITWISE_BOOL]); - -fn is_bitwise_operation(cx: &LateContext<'_>, expr: &Expr<'_>) -> bool { - let ty = cx.typeck_results().expr_ty(expr); - if_chain! { - if !expr.span.from_expansion(); - if let (&ExprKind::Binary(ref op, _, right), &ty::Bool) = (&expr.kind, &ty.kind()); - if op.node == BinOpKind::BitAnd || op.node == BinOpKind::BitOr; - if let ExprKind::Call(..) | ExprKind::MethodCall(..) | ExprKind::Binary(..) | ExprKind::Unary(..) = right.kind; - if !right.can_have_side_effects(); - then { - return true; - } - } - false -} - -fn suggestion_snippet(cx: &LateContext<'_>, expr: &Expr<'_>) -> Option<String> { - if let ExprKind::Binary(ref op, left, right) = expr.kind { - if let (Some(l_snippet), Some(r_snippet)) = (snippet_opt(cx, left.span), snippet_opt(cx, right.span)) { - let op_snippet = match op.node { - BinOpKind::BitAnd => "&&", - _ => "||", - }; - return Some(format!("{} {} {}", l_snippet, op_snippet, r_snippet)); - } - } - None -} - -impl LateLintPass<'_> for NeedlessBitwiseBool { - fn check_expr(&mut self, cx: &LateContext<'_>, expr: &Expr<'_>) { - if is_bitwise_operation(cx, expr) { - span_lint_and_then( - cx, - NEEDLESS_BITWISE_BOOL, - expr.span, - "use of bitwise operator instead of lazy operator between booleans", - |diag| { - if let Some(sugg) = suggestion_snippet(cx, expr) { - diag.span_suggestion(expr.span, "try", sugg, Applicability::MachineApplicable); - } - }, - ); - } - } -} diff --git a/src/tools/clippy/clippy_lints/src/needless_pass_by_value.rs b/src/tools/clippy/clippy_lints/src/needless_pass_by_value.rs index 8b273aca7d0..0cbef1c95fe 100644 --- a/src/tools/clippy/clippy_lints/src/needless_pass_by_value.rs +++ b/src/tools/clippy/clippy_lints/src/needless_pass_by_value.rs @@ -13,7 +13,7 @@ use rustc_hir::{HirIdMap, HirIdSet}; use rustc_infer::infer::TyCtxtInferExt; use rustc_lint::{LateContext, LateLintPass}; use rustc_middle::mir::FakeReadCause; -use rustc_middle::ty::{self, TypeFoldable}; +use rustc_middle::ty::{self, TypeVisitable}; use rustc_session::{declare_lint_pass, declare_tool_lint}; use rustc_span::symbol::kw; use rustc_span::{sym, Span}; diff --git a/src/tools/clippy/clippy_lints/src/neg_multiply.rs b/src/tools/clippy/clippy_lints/src/neg_multiply.rs index ce6bb38b7c0..b087cfb36b1 100644 --- a/src/tools/clippy/clippy_lints/src/neg_multiply.rs +++ b/src/tools/clippy/clippy_lints/src/neg_multiply.rs @@ -1,7 +1,9 @@ use clippy_utils::consts::{self, Constant}; use clippy_utils::diagnostics::span_lint_and_sugg; use clippy_utils::source::snippet_with_applicability; +use clippy_utils::sugg::has_enclosing_paren; use if_chain::if_chain; +use rustc_ast::util::parser::PREC_PREFIX; use rustc_errors::Applicability; use rustc_hir::{BinOpKind, Expr, ExprKind, UnOp}; use rustc_lint::{LateContext, LateLintPass}; @@ -58,7 +60,12 @@ fn check_mul(cx: &LateContext<'_>, span: Span, lit: &Expr<'_>, exp: &Expr<'_>) { then { let mut applicability = Applicability::MachineApplicable; - let suggestion = format!("-{}", snippet_with_applicability(cx, exp.span, "..", &mut applicability)); + let snip = snippet_with_applicability(cx, exp.span, "..", &mut applicability); + let suggestion = if exp.precedence().order() < PREC_PREFIX && !has_enclosing_paren(&snip) { + format!("-({})", snip) + } else { + format!("-{}", snip) + }; span_lint_and_sugg( cx, NEG_MULTIPLY, diff --git a/src/tools/clippy/clippy_lints/src/non_copy_const.rs b/src/tools/clippy/clippy_lints/src/non_copy_const.rs index 1727275a4e0..a1ef32ae608 100644 --- a/src/tools/clippy/clippy_lints/src/non_copy_const.rs +++ b/src/tools/clippy/clippy_lints/src/non_copy_const.rs @@ -6,6 +6,7 @@ use std::ptr; use clippy_utils::diagnostics::span_lint_and_then; use clippy_utils::in_constant; +use clippy_utils::macros::macro_backtrace; use if_chain::if_chain; use rustc_hir::def::{DefKind, Res}; use rustc_hir::def_id::DefId; @@ -18,7 +19,7 @@ use rustc_middle::mir::interpret::{ConstValue, ErrorHandled}; use rustc_middle::ty::adjustment::Adjust; use rustc_middle::ty::{self, Ty}; use rustc_session::{declare_lint_pass, declare_tool_lint}; -use rustc_span::{InnerSpan, Span, DUMMY_SP}; +use rustc_span::{sym, InnerSpan, Span, DUMMY_SP}; use rustc_typeck::hir_ty_to_ty; // FIXME: this is a correctness problem but there's no suitable @@ -250,8 +251,14 @@ impl<'tcx> LateLintPass<'tcx> for NonCopyConst { fn check_item(&mut self, cx: &LateContext<'tcx>, it: &'tcx Item<'_>) { if let ItemKind::Const(hir_ty, body_id) = it.kind { let ty = hir_ty_to_ty(cx.tcx, hir_ty); - - if is_unfrozen(cx, ty) && is_value_unfrozen_poly(cx, body_id, ty) { + if !macro_backtrace(it.span).last().map_or(false, |macro_call| { + matches!( + cx.tcx.get_diagnostic_name(macro_call.def_id), + Some(sym::thread_local_macro) + ) + }) && is_unfrozen(cx, ty) + && is_value_unfrozen_poly(cx, body_id, ty) + { lint(cx, Source::Item { item: it.span }); } } diff --git a/src/tools/clippy/clippy_lints/src/non_expressive_names.rs b/src/tools/clippy/clippy_lints/src/non_expressive_names.rs index 7f6b535c7b1..b96af06b8d7 100644 --- a/src/tools/clippy/clippy_lints/src/non_expressive_names.rs +++ b/src/tools/clippy/clippy_lints/src/non_expressive_names.rs @@ -159,12 +159,10 @@ impl<'a, 'tcx, 'b> Visitor<'tcx> for SimilarNamesNameVisitor<'a, 'tcx, 'b> { #[must_use] fn get_exemptions(interned_name: &str) -> Option<&'static [&'static str]> { - for &list in ALLOWED_TO_BE_SIMILAR { - if allowed_to_be_similar(interned_name, list) { - return Some(list); - } - } - None + ALLOWED_TO_BE_SIMILAR + .iter() + .find(|&&list| allowed_to_be_similar(interned_name, list)) + .copied() } #[must_use] @@ -328,7 +326,7 @@ impl<'a, 'tcx> Visitor<'tcx> for SimilarNamesLocalVisitor<'a, 'tcx> { // add the pattern after the expression because the bindings aren't available // yet in the init // expression - SimilarNamesNameVisitor(self).visit_pat(&*local.pat); + SimilarNamesNameVisitor(self).visit_pat(&local.pat); } fn visit_block(&mut self, blk: &'tcx Block) { self.single_char_names.push(vec![]); diff --git a/src/tools/clippy/clippy_lints/src/numeric_arithmetic.rs b/src/tools/clippy/clippy_lints/src/numeric_arithmetic.rs deleted file mode 100644 index 5c4de338149..00000000000 --- a/src/tools/clippy/clippy_lints/src/numeric_arithmetic.rs +++ /dev/null @@ -1,170 +0,0 @@ -use clippy_utils::consts::constant_simple; -use clippy_utils::diagnostics::span_lint; -use rustc_hir as hir; -use rustc_lint::{LateContext, LateLintPass}; -use rustc_session::{declare_tool_lint, impl_lint_pass}; -use rustc_span::source_map::Span; - -declare_clippy_lint! { - /// ### What it does - /// Checks for integer arithmetic operations which could overflow or panic. - /// - /// Specifically, checks for any operators (`+`, `-`, `*`, `<<`, etc) which are capable - /// of overflowing according to the [Rust - /// Reference](https://doc.rust-lang.org/reference/expressions/operator-expr.html#overflow), - /// or which can panic (`/`, `%`). No bounds analysis or sophisticated reasoning is - /// attempted. - /// - /// ### Why is this bad? - /// Integer overflow will trigger a panic in debug builds or will wrap in - /// release mode. Division by zero will cause a panic in either mode. In some applications one - /// wants explicitly checked, wrapping or saturating arithmetic. - /// - /// ### Example - /// ```rust - /// # let a = 0; - /// a + 1; - /// ``` - #[clippy::version = "pre 1.29.0"] - pub INTEGER_ARITHMETIC, - restriction, - "any integer arithmetic expression which could overflow or panic" -} - -declare_clippy_lint! { - /// ### What it does - /// Checks for float arithmetic. - /// - /// ### Why is this bad? - /// For some embedded systems or kernel development, it - /// can be useful to rule out floating-point numbers. - /// - /// ### Example - /// ```rust - /// # let a = 0.0; - /// a + 1.0; - /// ``` - #[clippy::version = "pre 1.29.0"] - pub FLOAT_ARITHMETIC, - restriction, - "any floating-point arithmetic statement" -} - -#[derive(Copy, Clone, Default)] -pub struct NumericArithmetic { - expr_span: Option<Span>, - /// This field is used to check whether expressions are constants, such as in enum discriminants - /// and consts - const_span: Option<Span>, -} - -impl_lint_pass!(NumericArithmetic => [INTEGER_ARITHMETIC, FLOAT_ARITHMETIC]); - -impl<'tcx> LateLintPass<'tcx> for NumericArithmetic { - fn check_expr(&mut self, cx: &LateContext<'tcx>, expr: &'tcx hir::Expr<'_>) { - if self.expr_span.is_some() { - return; - } - - if let Some(span) = self.const_span { - if span.contains(expr.span) { - return; - } - } - match &expr.kind { - hir::ExprKind::Binary(op, l, r) | hir::ExprKind::AssignOp(op, l, r) => { - match op.node { - hir::BinOpKind::And - | hir::BinOpKind::Or - | hir::BinOpKind::BitAnd - | hir::BinOpKind::BitOr - | hir::BinOpKind::BitXor - | hir::BinOpKind::Eq - | hir::BinOpKind::Lt - | hir::BinOpKind::Le - | hir::BinOpKind::Ne - | hir::BinOpKind::Ge - | hir::BinOpKind::Gt => return, - _ => (), - } - - let (l_ty, r_ty) = (cx.typeck_results().expr_ty(l), cx.typeck_results().expr_ty(r)); - if l_ty.peel_refs().is_integral() && r_ty.peel_refs().is_integral() { - match op.node { - hir::BinOpKind::Div | hir::BinOpKind::Rem => match &r.kind { - hir::ExprKind::Lit(_lit) => (), - hir::ExprKind::Unary(hir::UnOp::Neg, expr) => { - if let hir::ExprKind::Lit(lit) = &expr.kind { - if let rustc_ast::ast::LitKind::Int(1, _) = lit.node { - span_lint(cx, INTEGER_ARITHMETIC, expr.span, "integer arithmetic detected"); - self.expr_span = Some(expr.span); - } - } - }, - _ => { - span_lint(cx, INTEGER_ARITHMETIC, expr.span, "integer arithmetic detected"); - self.expr_span = Some(expr.span); - }, - }, - _ => { - span_lint(cx, INTEGER_ARITHMETIC, expr.span, "integer arithmetic detected"); - self.expr_span = Some(expr.span); - }, - } - } else if r_ty.peel_refs().is_floating_point() && r_ty.peel_refs().is_floating_point() { - span_lint(cx, FLOAT_ARITHMETIC, expr.span, "floating-point arithmetic detected"); - self.expr_span = Some(expr.span); - } - }, - hir::ExprKind::Unary(hir::UnOp::Neg, arg) => { - let ty = cx.typeck_results().expr_ty(arg); - if constant_simple(cx, cx.typeck_results(), expr).is_none() { - if ty.is_integral() { - span_lint(cx, INTEGER_ARITHMETIC, expr.span, "integer arithmetic detected"); - self.expr_span = Some(expr.span); - } else if ty.is_floating_point() { - span_lint(cx, FLOAT_ARITHMETIC, expr.span, "floating-point arithmetic detected"); - self.expr_span = Some(expr.span); - } - } - }, - _ => (), - } - } - - fn check_expr_post(&mut self, _: &LateContext<'tcx>, expr: &'tcx hir::Expr<'_>) { - if Some(expr.span) == self.expr_span { - self.expr_span = None; - } - } - - fn check_body(&mut self, cx: &LateContext<'_>, body: &hir::Body<'_>) { - let body_owner = cx.tcx.hir().body_owner_def_id(body.id()); - - match cx.tcx.hir().body_owner_kind(body_owner) { - hir::BodyOwnerKind::Static(_) | hir::BodyOwnerKind::Const => { - let body_span = cx.tcx.def_span(body_owner); - - if let Some(span) = self.const_span { - if span.contains(body_span) { - return; - } - } - self.const_span = Some(body_span); - }, - hir::BodyOwnerKind::Fn | hir::BodyOwnerKind::Closure => (), - } - } - - fn check_body_post(&mut self, cx: &LateContext<'_>, body: &hir::Body<'_>) { - let body_owner = cx.tcx.hir().body_owner(body.id()); - let body_span = cx.tcx.hir().span(body_owner); - - if let Some(span) = self.const_span { - if span.contains(body_span) { - return; - } - } - self.const_span = None; - } -} diff --git a/src/tools/clippy/clippy_lints/src/absurd_extreme_comparisons.rs b/src/tools/clippy/clippy_lints/src/operators/absurd_extreme_comparisons.rs index 7665aa8380b..1ec4240afef 100644 --- a/src/tools/clippy/clippy_lints/src/absurd_extreme_comparisons.rs +++ b/src/tools/clippy/clippy_lints/src/operators/absurd_extreme_comparisons.rs @@ -1,7 +1,6 @@ use rustc_hir::{BinOpKind, Expr, ExprKind}; -use rustc_lint::{LateContext, LateLintPass}; +use rustc_lint::LateContext; use rustc_middle::ty; -use rustc_session::{declare_lint_pass, declare_tool_lint}; use clippy_utils::comparisons::{normalize_comparison, Rel}; use clippy_utils::consts::{constant, Constant}; @@ -10,73 +9,41 @@ use clippy_utils::source::snippet; use clippy_utils::ty::is_isize_or_usize; use clippy_utils::{clip, int_bits, unsext}; -declare_clippy_lint! { - /// ### What it does - /// Checks for comparisons where one side of the relation is - /// either the minimum or maximum value for its type and warns if it involves a - /// case that is always true or always false. Only integer and boolean types are - /// checked. - /// - /// ### Why is this bad? - /// An expression like `min <= x` may misleadingly imply - /// that it is possible for `x` to be less than the minimum. Expressions like - /// `max < x` are probably mistakes. - /// - /// ### Known problems - /// For `usize` the size of the current compile target will - /// be assumed (e.g., 64 bits on 64 bit systems). This means code that uses such - /// a comparison to detect target pointer width will trigger this lint. One can - /// use `mem::sizeof` and compare its value or conditional compilation - /// attributes - /// like `#[cfg(target_pointer_width = "64")] ..` instead. - /// - /// ### Example - /// ```rust - /// let vec: Vec<isize> = Vec::new(); - /// if vec.len() <= 0 {} - /// if 100 > i32::MAX {} - /// ``` - #[clippy::version = "pre 1.29.0"] - pub ABSURD_EXTREME_COMPARISONS, - correctness, - "a comparison with a maximum or minimum value that is always true or false" -} +use super::ABSURD_EXTREME_COMPARISONS; -declare_lint_pass!(AbsurdExtremeComparisons => [ABSURD_EXTREME_COMPARISONS]); - -impl<'tcx> LateLintPass<'tcx> for AbsurdExtremeComparisons { - fn check_expr(&mut self, cx: &LateContext<'tcx>, expr: &'tcx Expr<'_>) { - if let ExprKind::Binary(ref cmp, lhs, rhs) = expr.kind { - if let Some((culprit, result)) = detect_absurd_comparison(cx, cmp.node, lhs, rhs) { - if !expr.span.from_expansion() { - let msg = "this comparison involving the minimum or maximum element for this \ - type contains a case that is always true or always false"; - - let conclusion = match result { - AbsurdComparisonResult::AlwaysFalse => "this comparison is always false".to_owned(), - AbsurdComparisonResult::AlwaysTrue => "this comparison is always true".to_owned(), - AbsurdComparisonResult::InequalityImpossible => format!( - "the case where the two sides are not equal never occurs, consider using `{} == {}` \ - instead", - snippet(cx, lhs.span, "lhs"), - snippet(cx, rhs.span, "rhs") - ), - }; - - let help = format!( - "because `{}` is the {} value for this type, {}", - snippet(cx, culprit.expr.span, "x"), - match culprit.which { - ExtremeType::Minimum => "minimum", - ExtremeType::Maximum => "maximum", - }, - conclusion - ); - - span_lint_and_help(cx, ABSURD_EXTREME_COMPARISONS, expr.span, msg, None, &help); - } - } - } +pub(super) fn check<'tcx>( + cx: &LateContext<'tcx>, + expr: &'tcx Expr<'_>, + op: BinOpKind, + lhs: &'tcx Expr<'_>, + rhs: &'tcx Expr<'_>, +) { + if let Some((culprit, result)) = detect_absurd_comparison(cx, op, lhs, rhs) { + let msg = "this comparison involving the minimum or maximum element for this \ + type contains a case that is always true or always false"; + + let conclusion = match result { + AbsurdComparisonResult::AlwaysFalse => "this comparison is always false".to_owned(), + AbsurdComparisonResult::AlwaysTrue => "this comparison is always true".to_owned(), + AbsurdComparisonResult::InequalityImpossible => format!( + "the case where the two sides are not equal never occurs, consider using `{} == {}` \ + instead", + snippet(cx, lhs.span, "lhs"), + snippet(cx, rhs.span, "rhs") + ), + }; + + let help = format!( + "because `{}` is the {} value for this type, {}", + snippet(cx, culprit.expr.span, "x"), + match culprit.which { + ExtremeType::Minimum => "minimum", + ExtremeType::Maximum => "maximum", + }, + conclusion + ); + + span_lint_and_help(cx, ABSURD_EXTREME_COMPARISONS, expr.span, msg, None, &help); } } diff --git a/src/tools/clippy/clippy_lints/src/operators/assign_op_pattern.rs b/src/tools/clippy/clippy_lints/src/operators/assign_op_pattern.rs new file mode 100644 index 00000000000..979e0a66707 --- /dev/null +++ b/src/tools/clippy/clippy_lints/src/operators/assign_op_pattern.rs @@ -0,0 +1,101 @@ +use clippy_utils::binop_traits; +use clippy_utils::diagnostics::span_lint_and_then; +use clippy_utils::source::snippet_opt; +use clippy_utils::ty::implements_trait; +use clippy_utils::{eq_expr_value, trait_ref_of_method}; +use if_chain::if_chain; +use rustc_errors::Applicability; +use rustc_hir as hir; +use rustc_hir::intravisit::{walk_expr, Visitor}; +use rustc_lint::LateContext; + +use super::ASSIGN_OP_PATTERN; + +pub(super) fn check<'tcx>( + cx: &LateContext<'tcx>, + expr: &'tcx hir::Expr<'_>, + assignee: &'tcx hir::Expr<'_>, + e: &'tcx hir::Expr<'_>, +) { + if let hir::ExprKind::Binary(op, l, r) = &e.kind { + let lint = |assignee: &hir::Expr<'_>, rhs: &hir::Expr<'_>| { + let ty = cx.typeck_results().expr_ty(assignee); + let rty = cx.typeck_results().expr_ty(rhs); + if_chain! { + if let Some((_, lang_item)) = binop_traits(op.node); + if let Ok(trait_id) = cx.tcx.lang_items().require(lang_item); + let parent_fn = cx.tcx.hir().get_parent_item(e.hir_id); + if trait_ref_of_method(cx, parent_fn) + .map_or(true, |t| t.path.res.def_id() != trait_id); + if implements_trait(cx, ty, trait_id, &[rty.into()]); + then { + span_lint_and_then( + cx, + ASSIGN_OP_PATTERN, + expr.span, + "manual implementation of an assign operation", + |diag| { + if let (Some(snip_a), Some(snip_r)) = + (snippet_opt(cx, assignee.span), snippet_opt(cx, rhs.span)) + { + diag.span_suggestion( + expr.span, + "replace it with", + format!("{} {}= {}", snip_a, op.node.as_str(), snip_r), + Applicability::MachineApplicable, + ); + } + }, + ); + } + } + }; + + let mut visitor = ExprVisitor { + assignee, + counter: 0, + cx, + }; + + walk_expr(&mut visitor, e); + + if visitor.counter == 1 { + // a = a op b + if eq_expr_value(cx, assignee, l) { + lint(assignee, r); + } + // a = b commutative_op a + // Limited to primitive type as these ops are know to be commutative + if eq_expr_value(cx, assignee, r) && cx.typeck_results().expr_ty(assignee).is_primitive_ty() { + match op.node { + hir::BinOpKind::Add + | hir::BinOpKind::Mul + | hir::BinOpKind::And + | hir::BinOpKind::Or + | hir::BinOpKind::BitXor + | hir::BinOpKind::BitAnd + | hir::BinOpKind::BitOr => { + lint(assignee, l); + }, + _ => {}, + } + } + } + } +} + +struct ExprVisitor<'a, 'tcx> { + assignee: &'a hir::Expr<'a>, + counter: u8, + cx: &'a LateContext<'tcx>, +} + +impl<'a, 'tcx> Visitor<'tcx> for ExprVisitor<'a, 'tcx> { + fn visit_expr(&mut self, expr: &'tcx hir::Expr<'_>) { + if eq_expr_value(self.cx, self.assignee, expr) { + self.counter += 1; + } + + walk_expr(self, expr); + } +} diff --git a/src/tools/clippy/clippy_lints/src/bit_mask.rs b/src/tools/clippy/clippy_lints/src/operators/bit_mask.rs index dc7e400fdc2..74387fbc87b 100644 --- a/src/tools/clippy/clippy_lints/src/bit_mask.rs +++ b/src/tools/clippy/clippy_lints/src/operators/bit_mask.rs @@ -1,161 +1,23 @@ use clippy_utils::consts::{constant, Constant}; -use clippy_utils::diagnostics::{span_lint, span_lint_and_then}; -use clippy_utils::sugg::Sugg; -use rustc_ast::ast::LitKind; -use rustc_errors::Applicability; +use clippy_utils::diagnostics::span_lint; use rustc_hir::{BinOpKind, Expr, ExprKind}; -use rustc_lint::{LateContext, LateLintPass}; -use rustc_session::{declare_tool_lint, impl_lint_pass}; +use rustc_lint::LateContext; use rustc_span::source_map::Span; -declare_clippy_lint! { - /// ### What it does - /// Checks for incompatible bit masks in comparisons. - /// - /// The formula for detecting if an expression of the type `_ <bit_op> m - /// <cmp_op> c` (where `<bit_op>` is one of {`&`, `|`} and `<cmp_op>` is one of - /// {`!=`, `>=`, `>`, `!=`, `>=`, `>`}) can be determined from the following - /// table: - /// - /// |Comparison |Bit Op|Example |is always|Formula | - /// |------------|------|-------------|---------|----------------------| - /// |`==` or `!=`| `&` |`x & 2 == 3` |`false` |`c & m != c` | - /// |`<` or `>=`| `&` |`x & 2 < 3` |`true` |`m < c` | - /// |`>` or `<=`| `&` |`x & 1 > 1` |`false` |`m <= c` | - /// |`==` or `!=`| `\|` |`x \| 1 == 0`|`false` |`c \| m != c` | - /// |`<` or `>=`| `\|` |`x \| 1 < 1` |`false` |`m >= c` | - /// |`<=` or `>` | `\|` |`x \| 1 > 0` |`true` |`m > c` | - /// - /// ### Why is this bad? - /// If the bits that the comparison cares about are always - /// set to zero or one by the bit mask, the comparison is constant `true` or - /// `false` (depending on mask, compared value, and operators). - /// - /// So the code is actively misleading, and the only reason someone would write - /// this intentionally is to win an underhanded Rust contest or create a - /// test-case for this lint. - /// - /// ### Example - /// ```rust - /// # let x = 1; - /// if (x & 1 == 2) { } - /// ``` - #[clippy::version = "pre 1.29.0"] - pub BAD_BIT_MASK, - correctness, - "expressions of the form `_ & mask == select` that will only ever return `true` or `false`" -} - -declare_clippy_lint! { - /// ### What it does - /// Checks for bit masks in comparisons which can be removed - /// without changing the outcome. The basic structure can be seen in the - /// following table: - /// - /// |Comparison| Bit Op |Example |equals | - /// |----------|----------|------------|-------| - /// |`>` / `<=`|`\|` / `^`|`x \| 2 > 3`|`x > 3`| - /// |`<` / `>=`|`\|` / `^`|`x ^ 1 < 4` |`x < 4`| - /// - /// ### Why is this bad? - /// Not equally evil as [`bad_bit_mask`](#bad_bit_mask), - /// but still a bit misleading, because the bit mask is ineffective. - /// - /// ### Known problems - /// False negatives: This lint will only match instances - /// where we have figured out the math (which is for a power-of-two compared - /// value). This means things like `x | 1 >= 7` (which would be better written - /// as `x >= 6`) will not be reported (but bit masks like this are fairly - /// uncommon). - /// - /// ### Example - /// ```rust - /// # let x = 1; - /// if (x | 1 > 3) { } - /// ``` - #[clippy::version = "pre 1.29.0"] - pub INEFFECTIVE_BIT_MASK, - correctness, - "expressions where a bit mask will be rendered useless by a comparison, e.g., `(x | 1) > 2`" -} - -declare_clippy_lint! { - /// ### What it does - /// Checks for bit masks that can be replaced by a call - /// to `trailing_zeros` - /// - /// ### Why is this bad? - /// `x.trailing_zeros() > 4` is much clearer than `x & 15 - /// == 0` - /// - /// ### Known problems - /// llvm generates better code for `x & 15 == 0` on x86 - /// - /// ### Example - /// ```rust - /// # let x = 1; - /// if x & 0b1111 == 0 { } - /// ``` - #[clippy::version = "pre 1.29.0"] - pub VERBOSE_BIT_MASK, - pedantic, - "expressions where a bit mask is less readable than the corresponding method call" -} +use super::{BAD_BIT_MASK, INEFFECTIVE_BIT_MASK}; -#[derive(Copy, Clone)] -pub struct BitMask { - verbose_bit_mask_threshold: u64, -} - -impl BitMask { - #[must_use] - pub fn new(verbose_bit_mask_threshold: u64) -> Self { - Self { - verbose_bit_mask_threshold, - } - } -} - -impl_lint_pass!(BitMask => [BAD_BIT_MASK, INEFFECTIVE_BIT_MASK, VERBOSE_BIT_MASK]); - -impl<'tcx> LateLintPass<'tcx> for BitMask { - fn check_expr(&mut self, cx: &LateContext<'tcx>, e: &'tcx Expr<'_>) { - if let ExprKind::Binary(cmp, left, right) = &e.kind { - if cmp.node.is_comparison() { - if let Some(cmp_opt) = fetch_int_literal(cx, right) { - check_compare(cx, left, cmp.node, cmp_opt, e.span); - } else if let Some(cmp_val) = fetch_int_literal(cx, left) { - check_compare(cx, right, invert_cmp(cmp.node), cmp_val, e.span); - } - } - } - - if let ExprKind::Binary(op, left, right) = &e.kind - && BinOpKind::Eq == op.node - && let ExprKind::Binary(op1, left1, right1) = &left.kind - && BinOpKind::BitAnd == op1.node - && let ExprKind::Lit(lit) = &right1.kind - && let LitKind::Int(n, _) = lit.node - && let ExprKind::Lit(lit1) = &right.kind - && let LitKind::Int(0, _) = lit1.node - && n.leading_zeros() == n.count_zeros() - && n > u128::from(self.verbose_bit_mask_threshold) - { - span_lint_and_then( - cx, - VERBOSE_BIT_MASK, - e.span, - "bit mask could be simplified with a call to `trailing_zeros`", - |diag| { - let sugg = Sugg::hir(cx, left1, "...").maybe_par(); - diag.span_suggestion( - e.span, - "try", - format!("{}.trailing_zeros() >= {}", sugg, n.count_ones()), - Applicability::MaybeIncorrect, - ); - }, - ); +pub(super) fn check<'tcx>( + cx: &LateContext<'tcx>, + e: &'tcx Expr<'_>, + op: BinOpKind, + left: &'tcx Expr<'_>, + right: &'tcx Expr<'_>, +) { + if op.is_comparison() { + if let Some(cmp_opt) = fetch_int_literal(cx, right) { + check_compare(cx, left, op, cmp_opt, e.span); + } else if let Some(cmp_val) = fetch_int_literal(cx, left) { + check_compare(cx, right, invert_cmp(op), cmp_val, e.span); } } } diff --git a/src/tools/clippy/clippy_lints/src/operators/cmp_nan.rs b/src/tools/clippy/clippy_lints/src/operators/cmp_nan.rs new file mode 100644 index 00000000000..786ae1552ad --- /dev/null +++ b/src/tools/clippy/clippy_lints/src/operators/cmp_nan.rs @@ -0,0 +1,30 @@ +use clippy_utils::consts::{constant, Constant}; +use clippy_utils::diagnostics::span_lint; +use clippy_utils::in_constant; +use rustc_hir::{BinOpKind, Expr}; +use rustc_lint::LateContext; + +use super::CMP_NAN; + +pub(super) fn check(cx: &LateContext<'_>, e: &Expr<'_>, op: BinOpKind, lhs: &Expr<'_>, rhs: &Expr<'_>) { + if op.is_comparison() && !in_constant(cx, e.hir_id) && (is_nan(cx, lhs) || is_nan(cx, rhs)) { + span_lint( + cx, + CMP_NAN, + e.span, + "doomed comparison with `NAN`, use `{f32,f64}::is_nan()` instead", + ); + } +} + +fn is_nan(cx: &LateContext<'_>, e: &Expr<'_>) -> bool { + if let Some((value, _)) = constant(cx, cx.typeck_results(), e) { + match value { + Constant::F32(num) => num.is_nan(), + Constant::F64(num) => num.is_nan(), + _ => false, + } + } else { + false + } +} diff --git a/src/tools/clippy/clippy_lints/src/operators/cmp_owned.rs b/src/tools/clippy/clippy_lints/src/operators/cmp_owned.rs new file mode 100644 index 00000000000..e1f9b5906f6 --- /dev/null +++ b/src/tools/clippy/clippy_lints/src/operators/cmp_owned.rs @@ -0,0 +1,147 @@ +use clippy_utils::diagnostics::span_lint_and_then; +use clippy_utils::source::snippet; +use clippy_utils::ty::{implements_trait, is_copy}; +use clippy_utils::{match_any_def_paths, path_def_id, paths}; +use rustc_errors::Applicability; +use rustc_hir::{BinOpKind, Expr, ExprKind, UnOp}; +use rustc_lint::LateContext; +use rustc_middle::ty::Ty; +use rustc_span::symbol::sym; + +use super::CMP_OWNED; + +pub(super) fn check(cx: &LateContext<'_>, op: BinOpKind, lhs: &Expr<'_>, rhs: &Expr<'_>) { + if op.is_comparison() { + check_op(cx, lhs, rhs, true); + check_op(cx, rhs, lhs, false); + } +} + +#[derive(Default)] +struct EqImpl { + ty_eq_other: bool, + other_eq_ty: bool, +} +impl EqImpl { + fn is_implemented(&self) -> bool { + self.ty_eq_other || self.other_eq_ty + } +} + +fn symmetric_partial_eq<'tcx>(cx: &LateContext<'tcx>, ty: Ty<'tcx>, other: Ty<'tcx>) -> Option<EqImpl> { + cx.tcx.lang_items().eq_trait().map(|def_id| EqImpl { + ty_eq_other: implements_trait(cx, ty, def_id, &[other.into()]), + other_eq_ty: implements_trait(cx, other, def_id, &[ty.into()]), + }) +} + +fn check_op(cx: &LateContext<'_>, expr: &Expr<'_>, other: &Expr<'_>, left: bool) { + let typeck = cx.typeck_results(); + let (arg, arg_span) = match expr.kind { + ExprKind::MethodCall(.., [arg], _) + if typeck + .type_dependent_def_id(expr.hir_id) + .and_then(|id| cx.tcx.trait_of_item(id)) + .map_or(false, |id| { + matches!(cx.tcx.get_diagnostic_name(id), Some(sym::ToString | sym::ToOwned)) + }) => + { + (arg, arg.span) + }, + ExprKind::Call(path, [arg]) + if path_def_id(cx, path) + .and_then(|id| match_any_def_paths(cx, id, &[&paths::FROM_STR_METHOD, &paths::FROM_FROM])) + .map_or(false, |idx| match idx { + 0 => true, + 1 => !is_copy(cx, typeck.expr_ty(expr)), + _ => false, + }) => + { + (arg, arg.span) + }, + _ => return, + }; + + let arg_ty = typeck.expr_ty(arg); + let other_ty = typeck.expr_ty(other); + + let without_deref = symmetric_partial_eq(cx, arg_ty, other_ty).unwrap_or_default(); + let with_deref = arg_ty + .builtin_deref(true) + .and_then(|tam| symmetric_partial_eq(cx, tam.ty, other_ty)) + .unwrap_or_default(); + + if !with_deref.is_implemented() && !without_deref.is_implemented() { + return; + } + + let other_gets_derefed = matches!(other.kind, ExprKind::Unary(UnOp::Deref, _)); + + let lint_span = if other_gets_derefed { + expr.span.to(other.span) + } else { + expr.span + }; + + span_lint_and_then( + cx, + CMP_OWNED, + lint_span, + "this creates an owned instance just for comparison", + |diag| { + // This also catches `PartialEq` implementations that call `to_owned`. + if other_gets_derefed { + diag.span_label(lint_span, "try implementing the comparison without allocating"); + return; + } + + let arg_snip = snippet(cx, arg_span, ".."); + let expr_snip; + let eq_impl; + if with_deref.is_implemented() { + expr_snip = format!("*{}", arg_snip); + eq_impl = with_deref; + } else { + expr_snip = arg_snip.to_string(); + eq_impl = without_deref; + }; + + let span; + let hint; + if (eq_impl.ty_eq_other && left) || (eq_impl.other_eq_ty && !left) { + span = expr.span; + hint = expr_snip; + } else { + span = expr.span.to(other.span); + + let cmp_span = if other.span < expr.span { + other.span.between(expr.span) + } else { + expr.span.between(other.span) + }; + if eq_impl.ty_eq_other { + hint = format!( + "{}{}{}", + expr_snip, + snippet(cx, cmp_span, ".."), + snippet(cx, other.span, "..") + ); + } else { + hint = format!( + "{}{}{}", + snippet(cx, other.span, ".."), + snippet(cx, cmp_span, ".."), + expr_snip + ); + } + } + + diag.span_suggestion( + span, + "try", + hint, + Applicability::MachineApplicable, // snippet + ); + }, + ); +} diff --git a/src/tools/clippy/clippy_lints/src/operators/double_comparison.rs b/src/tools/clippy/clippy_lints/src/operators/double_comparison.rs new file mode 100644 index 00000000000..56a86d0ffa2 --- /dev/null +++ b/src/tools/clippy/clippy_lints/src/operators/double_comparison.rs @@ -0,0 +1,54 @@ +use clippy_utils::diagnostics::span_lint_and_sugg; +use clippy_utils::eq_expr_value; +use clippy_utils::source::snippet_with_applicability; +use rustc_errors::Applicability; +use rustc_hir::{BinOpKind, Expr, ExprKind}; +use rustc_lint::LateContext; +use rustc_span::source_map::Span; + +use super::DOUBLE_COMPARISONS; + +#[expect(clippy::similar_names)] +pub(super) fn check<'tcx>(cx: &LateContext<'tcx>, op: BinOpKind, lhs: &'tcx Expr<'_>, rhs: &'tcx Expr<'_>, span: Span) { + let (lkind, llhs, lrhs, rkind, rlhs, rrhs) = match (&lhs.kind, &rhs.kind) { + (ExprKind::Binary(lb, llhs, lrhs), ExprKind::Binary(rb, rlhs, rrhs)) => { + (lb.node, llhs, lrhs, rb.node, rlhs, rrhs) + }, + _ => return, + }; + if !(eq_expr_value(cx, llhs, rlhs) && eq_expr_value(cx, lrhs, rrhs)) { + return; + } + macro_rules! lint_double_comparison { + ($op:tt) => {{ + let mut applicability = Applicability::MachineApplicable; + let lhs_str = snippet_with_applicability(cx, llhs.span, "", &mut applicability); + let rhs_str = snippet_with_applicability(cx, lrhs.span, "", &mut applicability); + let sugg = format!("{} {} {}", lhs_str, stringify!($op), rhs_str); + span_lint_and_sugg( + cx, + DOUBLE_COMPARISONS, + span, + "this binary expression can be simplified", + "try", + sugg, + applicability, + ); + }}; + } + match (op, lkind, rkind) { + (BinOpKind::Or, BinOpKind::Eq, BinOpKind::Lt) | (BinOpKind::Or, BinOpKind::Lt, BinOpKind::Eq) => { + lint_double_comparison!(<=); + }, + (BinOpKind::Or, BinOpKind::Eq, BinOpKind::Gt) | (BinOpKind::Or, BinOpKind::Gt, BinOpKind::Eq) => { + lint_double_comparison!(>=); + }, + (BinOpKind::Or, BinOpKind::Lt, BinOpKind::Gt) | (BinOpKind::Or, BinOpKind::Gt, BinOpKind::Lt) => { + lint_double_comparison!(!=); + }, + (BinOpKind::And, BinOpKind::Le, BinOpKind::Ge) | (BinOpKind::And, BinOpKind::Ge, BinOpKind::Le) => { + lint_double_comparison!(==); + }, + _ => (), + }; +} diff --git a/src/tools/clippy/clippy_lints/src/operators/duration_subsec.rs b/src/tools/clippy/clippy_lints/src/operators/duration_subsec.rs new file mode 100644 index 00000000000..0d067d1e196 --- /dev/null +++ b/src/tools/clippy/clippy_lints/src/operators/duration_subsec.rs @@ -0,0 +1,44 @@ +use clippy_utils::consts::{constant, Constant}; +use clippy_utils::diagnostics::span_lint_and_sugg; +use clippy_utils::source::snippet_with_applicability; +use clippy_utils::ty::is_type_diagnostic_item; +use rustc_errors::Applicability; +use rustc_hir::{BinOpKind, Expr, ExprKind}; +use rustc_lint::LateContext; +use rustc_span::sym; + +use super::DURATION_SUBSEC; + +pub(crate) fn check<'tcx>( + cx: &LateContext<'tcx>, + expr: &'tcx Expr<'_>, + op: BinOpKind, + left: &'tcx Expr<'_>, + right: &'tcx Expr<'_>, +) { + if op == BinOpKind::Div + && let ExprKind::MethodCall(method_path, [self_arg], _) = left.kind + && is_type_diagnostic_item(cx, cx.typeck_results().expr_ty(self_arg).peel_refs(), sym::Duration) + && let Some((Constant::Int(divisor), _)) = constant(cx, cx.typeck_results(), right) + { + let suggested_fn = match (method_path.ident.as_str(), divisor) { + ("subsec_micros", 1_000) | ("subsec_nanos", 1_000_000) => "subsec_millis", + ("subsec_nanos", 1_000) => "subsec_micros", + _ => return, + }; + let mut applicability = Applicability::MachineApplicable; + span_lint_and_sugg( + cx, + DURATION_SUBSEC, + expr.span, + &format!("calling `{}()` is more concise than this calculation", suggested_fn), + "try", + format!( + "{}.{}()", + snippet_with_applicability(cx, self_arg.span, "_", &mut applicability), + suggested_fn + ), + applicability, + ); + } +} diff --git a/src/tools/clippy/clippy_lints/src/operators/eq_op.rs b/src/tools/clippy/clippy_lints/src/operators/eq_op.rs new file mode 100644 index 00000000000..44cf0bb0612 --- /dev/null +++ b/src/tools/clippy/clippy_lints/src/operators/eq_op.rs @@ -0,0 +1,45 @@ +use clippy_utils::diagnostics::span_lint; +use clippy_utils::macros::{find_assert_eq_args, first_node_macro_backtrace}; +use clippy_utils::{ast_utils::is_useless_with_eq_exprs, eq_expr_value, is_in_test_function}; +use rustc_hir::{BinOpKind, Expr}; +use rustc_lint::LateContext; + +use super::EQ_OP; + +pub(crate) fn check_assert<'tcx>(cx: &LateContext<'tcx>, e: &'tcx Expr<'_>) { + if let Some((macro_call, macro_name)) + = first_node_macro_backtrace(cx, e).find_map(|macro_call| { + let name = cx.tcx.item_name(macro_call.def_id); + matches!(name.as_str(), "assert_eq" | "assert_ne" | "debug_assert_eq" | "debug_assert_ne") + .then(|| (macro_call, name)) + }) + && let Some((lhs, rhs, _)) = find_assert_eq_args(cx, e, macro_call.expn) + && eq_expr_value(cx, lhs, rhs) + && macro_call.is_local() + && !is_in_test_function(cx.tcx, e.hir_id) + { + span_lint( + cx, + EQ_OP, + lhs.span.to(rhs.span), + &format!("identical args used in this `{}!` macro call", macro_name), + ); + } +} + +pub(crate) fn check<'tcx>( + cx: &LateContext<'tcx>, + e: &'tcx Expr<'_>, + op: BinOpKind, + left: &'tcx Expr<'_>, + right: &'tcx Expr<'_>, +) { + if is_useless_with_eq_exprs(op.into()) && eq_expr_value(cx, left, right) && !is_in_test_function(cx.tcx, e.hir_id) { + span_lint( + cx, + EQ_OP, + e.span, + &format!("equal expressions as operands to `{}`", op.as_str()), + ); + } +} diff --git a/src/tools/clippy/clippy_lints/src/operators/erasing_op.rs b/src/tools/clippy/clippy_lints/src/operators/erasing_op.rs new file mode 100644 index 00000000000..066e08f3bd4 --- /dev/null +++ b/src/tools/clippy/clippy_lints/src/operators/erasing_op.rs @@ -0,0 +1,53 @@ +use clippy_utils::consts::{constant_simple, Constant}; +use clippy_utils::diagnostics::span_lint; +use clippy_utils::ty::same_type_and_consts; + +use rustc_hir::{BinOpKind, Expr}; +use rustc_lint::LateContext; +use rustc_middle::ty::TypeckResults; + +use super::ERASING_OP; + +pub(super) fn check<'tcx>( + cx: &LateContext<'tcx>, + e: &'tcx Expr<'_>, + op: BinOpKind, + left: &'tcx Expr<'_>, + right: &'tcx Expr<'_>, +) { + let tck = cx.typeck_results(); + match op { + BinOpKind::Mul | BinOpKind::BitAnd => { + check_op(cx, tck, left, right, e); + check_op(cx, tck, right, left, e); + }, + BinOpKind::Div => check_op(cx, tck, left, right, e), + _ => (), + } +} + +fn different_types(tck: &TypeckResults<'_>, input: &Expr<'_>, output: &Expr<'_>) -> bool { + let input_ty = tck.expr_ty(input).peel_refs(); + let output_ty = tck.expr_ty(output).peel_refs(); + !same_type_and_consts(input_ty, output_ty) +} + +fn check_op<'tcx>( + cx: &LateContext<'tcx>, + tck: &TypeckResults<'tcx>, + op: &Expr<'tcx>, + other: &Expr<'tcx>, + parent: &Expr<'tcx>, +) { + if constant_simple(cx, tck, op) == Some(Constant::Int(0)) { + if different_types(tck, other, parent) { + return; + } + span_lint( + cx, + ERASING_OP, + parent.span, + "this operation will always return zero. This is likely not the intended outcome", + ); + } +} diff --git a/src/tools/clippy/clippy_lints/src/operators/float_cmp.rs b/src/tools/clippy/clippy_lints/src/operators/float_cmp.rs new file mode 100644 index 00000000000..0ef793443ff --- /dev/null +++ b/src/tools/clippy/clippy_lints/src/operators/float_cmp.rs @@ -0,0 +1,139 @@ +use clippy_utils::consts::{constant, Constant}; +use clippy_utils::diagnostics::span_lint_and_then; +use clippy_utils::get_item_name; +use clippy_utils::sugg::Sugg; +use if_chain::if_chain; +use rustc_errors::Applicability; +use rustc_hir::{BinOpKind, Expr, ExprKind, UnOp}; +use rustc_lint::LateContext; +use rustc_middle::ty; + +use super::{FLOAT_CMP, FLOAT_CMP_CONST}; + +pub(crate) fn check<'tcx>( + cx: &LateContext<'tcx>, + expr: &'tcx Expr<'_>, + op: BinOpKind, + left: &'tcx Expr<'_>, + right: &'tcx Expr<'_>, +) { + if (op == BinOpKind::Eq || op == BinOpKind::Ne) && (is_float(cx, left) || is_float(cx, right)) { + if is_allowed(cx, left) || is_allowed(cx, right) { + return; + } + + // Allow comparing the results of signum() + if is_signum(cx, left) && is_signum(cx, right) { + return; + } + + if let Some(name) = get_item_name(cx, expr) { + let name = name.as_str(); + if name == "eq" || name == "ne" || name == "is_nan" || name.starts_with("eq_") || name.ends_with("_eq") { + return; + } + } + let is_comparing_arrays = is_array(cx, left) || is_array(cx, right); + let (lint, msg) = get_lint_and_message( + is_named_constant(cx, left) || is_named_constant(cx, right), + is_comparing_arrays, + ); + span_lint_and_then(cx, lint, expr.span, msg, |diag| { + let lhs = Sugg::hir(cx, left, ".."); + let rhs = Sugg::hir(cx, right, ".."); + + if !is_comparing_arrays { + diag.span_suggestion( + expr.span, + "consider comparing them within some margin of error", + format!( + "({}).abs() {} error_margin", + lhs - rhs, + if op == BinOpKind::Eq { '<' } else { '>' } + ), + Applicability::HasPlaceholders, // snippet + ); + } + diag.note("`f32::EPSILON` and `f64::EPSILON` are available for the `error_margin`"); + }); + } +} + +fn get_lint_and_message( + is_comparing_constants: bool, + is_comparing_arrays: bool, +) -> (&'static rustc_lint::Lint, &'static str) { + if is_comparing_constants { + ( + FLOAT_CMP_CONST, + if is_comparing_arrays { + "strict comparison of `f32` or `f64` constant arrays" + } else { + "strict comparison of `f32` or `f64` constant" + }, + ) + } else { + ( + FLOAT_CMP, + if is_comparing_arrays { + "strict comparison of `f32` or `f64` arrays" + } else { + "strict comparison of `f32` or `f64`" + }, + ) + } +} + +fn is_named_constant<'tcx>(cx: &LateContext<'tcx>, expr: &'tcx Expr<'_>) -> bool { + if let Some((_, res)) = constant(cx, cx.typeck_results(), expr) { + res + } else { + false + } +} + +fn is_allowed<'tcx>(cx: &LateContext<'tcx>, expr: &'tcx Expr<'_>) -> bool { + match constant(cx, cx.typeck_results(), expr) { + Some((Constant::F32(f), _)) => f == 0.0 || f.is_infinite(), + Some((Constant::F64(f), _)) => f == 0.0 || f.is_infinite(), + Some((Constant::Vec(vec), _)) => vec.iter().all(|f| match f { + Constant::F32(f) => *f == 0.0 || (*f).is_infinite(), + Constant::F64(f) => *f == 0.0 || (*f).is_infinite(), + _ => false, + }), + _ => false, + } +} + +// Return true if `expr` is the result of `signum()` invoked on a float value. +fn is_signum(cx: &LateContext<'_>, expr: &Expr<'_>) -> bool { + // The negation of a signum is still a signum + if let ExprKind::Unary(UnOp::Neg, child_expr) = expr.kind { + return is_signum(cx, child_expr); + } + + if_chain! { + if let ExprKind::MethodCall(method_name, [ref self_arg, ..], _) = expr.kind; + if sym!(signum) == method_name.ident.name; + // Check that the receiver of the signum() is a float (expressions[0] is the receiver of + // the method call) + then { + return is_float(cx, self_arg); + } + } + false +} + +fn is_float(cx: &LateContext<'_>, expr: &Expr<'_>) -> bool { + let value = &cx.typeck_results().expr_ty(expr).peel_refs().kind(); + + if let ty::Array(arr_ty, _) = value { + return matches!(arr_ty.kind(), ty::Float(_)); + }; + + matches!(value, ty::Float(_)) +} + +fn is_array(cx: &LateContext<'_>, expr: &Expr<'_>) -> bool { + matches!(&cx.typeck_results().expr_ty(expr).peel_refs().kind(), ty::Array(_, _)) +} diff --git a/src/tools/clippy/clippy_lints/src/operators/float_equality_without_abs.rs b/src/tools/clippy/clippy_lints/src/operators/float_equality_without_abs.rs new file mode 100644 index 00000000000..a0a8b6aabd9 --- /dev/null +++ b/src/tools/clippy/clippy_lints/src/operators/float_equality_without_abs.rs @@ -0,0 +1,71 @@ +use clippy_utils::diagnostics::span_lint_and_then; +use clippy_utils::{match_def_path, paths, sugg}; +use if_chain::if_chain; +use rustc_ast::util::parser::AssocOp; +use rustc_errors::Applicability; +use rustc_hir::def::{DefKind, Res}; +use rustc_hir::{BinOpKind, Expr, ExprKind}; +use rustc_lint::LateContext; +use rustc_middle::ty; +use rustc_span::source_map::Spanned; + +use super::FLOAT_EQUALITY_WITHOUT_ABS; + +pub(crate) fn check<'tcx>( + cx: &LateContext<'tcx>, + expr: &'tcx Expr<'_>, + op: BinOpKind, + lhs: &'tcx Expr<'_>, + rhs: &'tcx Expr<'_>, +) { + let (lhs, rhs) = match op { + BinOpKind::Lt => (lhs, rhs), + BinOpKind::Gt => (rhs, lhs), + _ => return, + }; + + if_chain! { + // left hand side is a subtraction + if let ExprKind::Binary( + Spanned { + node: BinOpKind::Sub, + .. + }, + val_l, + val_r, + ) = lhs.kind; + + // right hand side matches either f32::EPSILON or f64::EPSILON + if let ExprKind::Path(ref epsilon_path) = rhs.kind; + if let Res::Def(DefKind::AssocConst, def_id) = cx.qpath_res(epsilon_path, rhs.hir_id); + if match_def_path(cx, def_id, &paths::F32_EPSILON) || match_def_path(cx, def_id, &paths::F64_EPSILON); + + // values of the subtractions on the left hand side are of the type float + let t_val_l = cx.typeck_results().expr_ty(val_l); + let t_val_r = cx.typeck_results().expr_ty(val_r); + if let ty::Float(_) = t_val_l.kind(); + if let ty::Float(_) = t_val_r.kind(); + + then { + let sug_l = sugg::Sugg::hir(cx, val_l, ".."); + let sug_r = sugg::Sugg::hir(cx, val_r, ".."); + // format the suggestion + let suggestion = format!("{}.abs()", sugg::make_assoc(AssocOp::Subtract, &sug_l, &sug_r).maybe_par()); + // spans the lint + span_lint_and_then( + cx, + FLOAT_EQUALITY_WITHOUT_ABS, + expr.span, + "float equality check without `.abs()`", + | diag | { + diag.span_suggestion( + lhs.span, + "add `.abs()`", + suggestion, + Applicability::MaybeIncorrect, + ); + } + ); + } + } +} diff --git a/src/tools/clippy/clippy_lints/src/identity_op.rs b/src/tools/clippy/clippy_lints/src/operators/identity_op.rs index 419ea5a6811..b48d6c4e2e2 100644 --- a/src/tools/clippy/clippy_lints/src/identity_op.rs +++ b/src/tools/clippy/clippy_lints/src/operators/identity_op.rs @@ -3,61 +3,40 @@ use clippy_utils::diagnostics::span_lint_and_sugg; use clippy_utils::source::snippet_with_applicability; use clippy_utils::{clip, unsext}; use rustc_errors::Applicability; -use rustc_hir::{BinOp, BinOpKind, Expr, ExprKind, Node}; -use rustc_lint::{LateContext, LateLintPass}; +use rustc_hir::{BinOpKind, Expr, ExprKind, Node}; +use rustc_lint::LateContext; use rustc_middle::ty; -use rustc_session::{declare_lint_pass, declare_tool_lint}; use rustc_span::source_map::Span; -declare_clippy_lint! { - /// ### What it does - /// Checks for identity operations, e.g., `x + 0`. - /// - /// ### Why is this bad? - /// This code can be removed without changing the - /// meaning. So it just obscures what's going on. Delete it mercilessly. - /// - /// ### Example - /// ```rust - /// # let x = 1; - /// x / 1 + 0 * 1 - 0 | 0; - /// ``` - #[clippy::version = "pre 1.29.0"] - pub IDENTITY_OP, - complexity, - "using identity operations, e.g., `x + 0` or `y / 1`" -} - -declare_lint_pass!(IdentityOp => [IDENTITY_OP]); +use super::IDENTITY_OP; -impl<'tcx> LateLintPass<'tcx> for IdentityOp { - fn check_expr(&mut self, cx: &LateContext<'tcx>, expr: &'tcx Expr<'_>) { - if expr.span.from_expansion() { - return; - } - if let ExprKind::Binary(cmp, left, right) = &expr.kind { - if !is_allowed(cx, *cmp, left, right) { - match cmp.node { - BinOpKind::Add | BinOpKind::BitOr | BinOpKind::BitXor => { - check(cx, left, 0, expr.span, right.span, needs_parenthesis(cx, expr, right)); - check(cx, right, 0, expr.span, left.span, Parens::Unneeded); - }, - BinOpKind::Shl | BinOpKind::Shr | BinOpKind::Sub => { - check(cx, right, 0, expr.span, left.span, Parens::Unneeded); - }, - BinOpKind::Mul => { - check(cx, left, 1, expr.span, right.span, needs_parenthesis(cx, expr, right)); - check(cx, right, 1, expr.span, left.span, Parens::Unneeded); - }, - BinOpKind::Div => check(cx, right, 1, expr.span, left.span, Parens::Unneeded), - BinOpKind::BitAnd => { - check(cx, left, -1, expr.span, right.span, needs_parenthesis(cx, expr, right)); - check(cx, right, -1, expr.span, left.span, Parens::Unneeded); - }, - BinOpKind::Rem => check_remainder(cx, left, right, expr.span, left.span), - _ => (), - } - } +pub(crate) fn check<'tcx>( + cx: &LateContext<'tcx>, + expr: &'tcx Expr<'_>, + op: BinOpKind, + left: &'tcx Expr<'_>, + right: &'tcx Expr<'_>, +) { + if !is_allowed(cx, op, left, right) { + match op { + BinOpKind::Add | BinOpKind::BitOr | BinOpKind::BitXor => { + check_op(cx, left, 0, expr.span, right.span, needs_parenthesis(cx, expr, right)); + check_op(cx, right, 0, expr.span, left.span, Parens::Unneeded); + }, + BinOpKind::Shl | BinOpKind::Shr | BinOpKind::Sub => { + check_op(cx, right, 0, expr.span, left.span, Parens::Unneeded); + }, + BinOpKind::Mul => { + check_op(cx, left, 1, expr.span, right.span, needs_parenthesis(cx, expr, right)); + check_op(cx, right, 1, expr.span, left.span, Parens::Unneeded); + }, + BinOpKind::Div => check_op(cx, right, 1, expr.span, left.span, Parens::Unneeded), + BinOpKind::BitAnd => { + check_op(cx, left, -1, expr.span, right.span, needs_parenthesis(cx, expr, right)); + check_op(cx, right, -1, expr.span, left.span, Parens::Unneeded); + }, + BinOpKind::Rem => check_remainder(cx, left, right, expr.span, left.span), + _ => (), } } } @@ -108,12 +87,12 @@ fn needs_parenthesis(cx: &LateContext<'_>, binary: &Expr<'_>, right: &Expr<'_>) Parens::Needed } -fn is_allowed(cx: &LateContext<'_>, cmp: BinOp, left: &Expr<'_>, right: &Expr<'_>) -> bool { +fn is_allowed(cx: &LateContext<'_>, cmp: BinOpKind, left: &Expr<'_>, right: &Expr<'_>) -> bool { // This lint applies to integers !cx.typeck_results().expr_ty(left).peel_refs().is_integral() || !cx.typeck_results().expr_ty(right).peel_refs().is_integral() // `1 << 0` is a common pattern in bit manipulation code - || (cmp.node == BinOpKind::Shl + || (cmp == BinOpKind::Shl && constant_simple(cx, cx.typeck_results(), right) == Some(Constant::Int(0)) && constant_simple(cx, cx.typeck_results(), left) == Some(Constant::Int(1))) } @@ -130,7 +109,7 @@ fn check_remainder(cx: &LateContext<'_>, left: &Expr<'_>, right: &Expr<'_>, span } } -fn check(cx: &LateContext<'_>, e: &Expr<'_>, m: i8, span: Span, arg: Span, parens: Parens) { +fn check_op(cx: &LateContext<'_>, e: &Expr<'_>, m: i8, span: Span, arg: Span, parens: Parens) { if let Some(Constant::Int(v)) = constant_simple(cx, cx.typeck_results(), e).map(Constant::peel_refs) { let check = match *cx.typeck_results().expr_ty(e).peel_refs().kind() { ty::Int(ity) => unsext(cx.tcx, -1_i128, ity), diff --git a/src/tools/clippy/clippy_lints/src/operators/integer_division.rs b/src/tools/clippy/clippy_lints/src/operators/integer_division.rs new file mode 100644 index 00000000000..631d10f4a72 --- /dev/null +++ b/src/tools/clippy/clippy_lints/src/operators/integer_division.rs @@ -0,0 +1,27 @@ +use clippy_utils::diagnostics::span_lint_and_help; +use rustc_hir as hir; +use rustc_lint::LateContext; + +use super::INTEGER_DIVISION; + +pub(crate) fn check<'tcx>( + cx: &LateContext<'tcx>, + expr: &'tcx hir::Expr<'_>, + op: hir::BinOpKind, + left: &'tcx hir::Expr<'_>, + right: &'tcx hir::Expr<'_>, +) { + if op == hir::BinOpKind::Div + && cx.typeck_results().expr_ty(left).is_integral() + && cx.typeck_results().expr_ty(right).is_integral() + { + span_lint_and_help( + cx, + INTEGER_DIVISION, + expr.span, + "integer division", + None, + "division of integers may cause loss of precision. consider using floats", + ); + } +} diff --git a/src/tools/clippy/clippy_lints/src/operators/misrefactored_assign_op.rs b/src/tools/clippy/clippy_lints/src/operators/misrefactored_assign_op.rs new file mode 100644 index 00000000000..0024384d927 --- /dev/null +++ b/src/tools/clippy/clippy_lints/src/operators/misrefactored_assign_op.rs @@ -0,0 +1,84 @@ +use clippy_utils::diagnostics::span_lint_and_then; +use clippy_utils::eq_expr_value; +use clippy_utils::source::snippet_opt; +use clippy_utils::sugg; +use rustc_errors::Applicability; +use rustc_hir as hir; +use rustc_lint::LateContext; + +use super::MISREFACTORED_ASSIGN_OP; + +pub(super) fn check<'tcx>( + cx: &LateContext<'tcx>, + expr: &'tcx hir::Expr<'_>, + op: hir::BinOpKind, + lhs: &'tcx hir::Expr<'_>, + rhs: &'tcx hir::Expr<'_>, +) { + if let hir::ExprKind::Binary(binop, l, r) = &rhs.kind { + if op != binop.node { + return; + } + // lhs op= l op r + if eq_expr_value(cx, lhs, l) { + lint_misrefactored_assign_op(cx, expr, op, rhs, lhs, r); + } + // lhs op= l commutative_op r + if is_commutative(op) && eq_expr_value(cx, lhs, r) { + lint_misrefactored_assign_op(cx, expr, op, rhs, lhs, l); + } + } +} + +fn lint_misrefactored_assign_op( + cx: &LateContext<'_>, + expr: &hir::Expr<'_>, + op: hir::BinOpKind, + rhs: &hir::Expr<'_>, + assignee: &hir::Expr<'_>, + rhs_other: &hir::Expr<'_>, +) { + span_lint_and_then( + cx, + MISREFACTORED_ASSIGN_OP, + expr.span, + "variable appears on both sides of an assignment operation", + |diag| { + if let (Some(snip_a), Some(snip_r)) = (snippet_opt(cx, assignee.span), snippet_opt(cx, rhs_other.span)) { + let a = &sugg::Sugg::hir(cx, assignee, ".."); + let r = &sugg::Sugg::hir(cx, rhs, ".."); + let long = format!("{} = {}", snip_a, sugg::make_binop(op.into(), a, r)); + diag.span_suggestion( + expr.span, + &format!( + "did you mean `{} = {} {} {}` or `{}`? Consider replacing it with", + snip_a, + snip_a, + op.as_str(), + snip_r, + long + ), + format!("{} {}= {}", snip_a, op.as_str(), snip_r), + Applicability::MaybeIncorrect, + ); + diag.span_suggestion( + expr.span, + "or", + long, + Applicability::MaybeIncorrect, // snippet + ); + } + }, + ); +} + +#[must_use] +fn is_commutative(op: hir::BinOpKind) -> bool { + use rustc_hir::BinOpKind::{ + Add, And, BitAnd, BitOr, BitXor, Div, Eq, Ge, Gt, Le, Lt, Mul, Ne, Or, Rem, Shl, Shr, Sub, + }; + match op { + Add | Mul | And | Or | BitXor | BitAnd | BitOr | Eq | Ne => true, + Sub | Div | Rem | Shl | Shr | Lt | Le | Ge | Gt => false, + } +} diff --git a/src/tools/clippy/clippy_lints/src/operators/mod.rs b/src/tools/clippy/clippy_lints/src/operators/mod.rs new file mode 100644 index 00000000000..35fe405bcf1 --- /dev/null +++ b/src/tools/clippy/clippy_lints/src/operators/mod.rs @@ -0,0 +1,849 @@ +use rustc_hir::{Body, Expr, ExprKind, UnOp}; +use rustc_lint::{LateContext, LateLintPass}; +use rustc_session::{declare_tool_lint, impl_lint_pass}; + +mod absurd_extreme_comparisons; +mod assign_op_pattern; +mod bit_mask; +mod cmp_nan; +mod cmp_owned; +mod double_comparison; +mod duration_subsec; +mod eq_op; +mod erasing_op; +mod float_cmp; +mod float_equality_without_abs; +mod identity_op; +mod integer_division; +mod misrefactored_assign_op; +mod modulo_arithmetic; +mod modulo_one; +mod needless_bitwise_bool; +mod numeric_arithmetic; +mod op_ref; +mod ptr_eq; +mod self_assignment; +mod verbose_bit_mask; + +declare_clippy_lint! { + /// ### What it does + /// Checks for comparisons where one side of the relation is + /// either the minimum or maximum value for its type and warns if it involves a + /// case that is always true or always false. Only integer and boolean types are + /// checked. + /// + /// ### Why is this bad? + /// An expression like `min <= x` may misleadingly imply + /// that it is possible for `x` to be less than the minimum. Expressions like + /// `max < x` are probably mistakes. + /// + /// ### Known problems + /// For `usize` the size of the current compile target will + /// be assumed (e.g., 64 bits on 64 bit systems). This means code that uses such + /// a comparison to detect target pointer width will trigger this lint. One can + /// use `mem::sizeof` and compare its value or conditional compilation + /// attributes + /// like `#[cfg(target_pointer_width = "64")] ..` instead. + /// + /// ### Example + /// ```rust + /// let vec: Vec<isize> = Vec::new(); + /// if vec.len() <= 0 {} + /// if 100 > i32::MAX {} + /// ``` + #[clippy::version = "pre 1.29.0"] + pub ABSURD_EXTREME_COMPARISONS, + correctness, + "a comparison with a maximum or minimum value that is always true or false" +} + +declare_clippy_lint! { + /// ### What it does + /// Checks for integer arithmetic operations which could overflow or panic. + /// + /// Specifically, checks for any operators (`+`, `-`, `*`, `<<`, etc) which are capable + /// of overflowing according to the [Rust + /// Reference](https://doc.rust-lang.org/reference/expressions/operator-expr.html#overflow), + /// or which can panic (`/`, `%`). No bounds analysis or sophisticated reasoning is + /// attempted. + /// + /// ### Why is this bad? + /// Integer overflow will trigger a panic in debug builds or will wrap in + /// release mode. Division by zero will cause a panic in either mode. In some applications one + /// wants explicitly checked, wrapping or saturating arithmetic. + /// + /// ### Example + /// ```rust + /// # let a = 0; + /// a + 1; + /// ``` + #[clippy::version = "pre 1.29.0"] + pub INTEGER_ARITHMETIC, + restriction, + "any integer arithmetic expression which could overflow or panic" +} + +declare_clippy_lint! { + /// ### What it does + /// Checks for float arithmetic. + /// + /// ### Why is this bad? + /// For some embedded systems or kernel development, it + /// can be useful to rule out floating-point numbers. + /// + /// ### Example + /// ```rust + /// # let a = 0.0; + /// a + 1.0; + /// ``` + #[clippy::version = "pre 1.29.0"] + pub FLOAT_ARITHMETIC, + restriction, + "any floating-point arithmetic statement" +} + +declare_clippy_lint! { + /// ### What it does + /// Checks for `a = a op b` or `a = b commutative_op a` + /// patterns. + /// + /// ### Why is this bad? + /// These can be written as the shorter `a op= b`. + /// + /// ### Known problems + /// While forbidden by the spec, `OpAssign` traits may have + /// implementations that differ from the regular `Op` impl. + /// + /// ### Example + /// ```rust + /// let mut a = 5; + /// let b = 0; + /// // ... + /// + /// a = a + b; + /// ``` + /// + /// Use instead: + /// ```rust + /// let mut a = 5; + /// let b = 0; + /// // ... + /// + /// a += b; + /// ``` + #[clippy::version = "pre 1.29.0"] + pub ASSIGN_OP_PATTERN, + style, + "assigning the result of an operation on a variable to that same variable" +} + +declare_clippy_lint! { + /// ### What it does + /// Checks for `a op= a op b` or `a op= b op a` patterns. + /// + /// ### Why is this bad? + /// Most likely these are bugs where one meant to write `a + /// op= b`. + /// + /// ### Known problems + /// Clippy cannot know for sure if `a op= a op b` should have + /// been `a = a op a op b` or `a = a op b`/`a op= b`. Therefore, it suggests both. + /// If `a op= a op b` is really the correct behavior it should be + /// written as `a = a op a op b` as it's less confusing. + /// + /// ### Example + /// ```rust + /// let mut a = 5; + /// let b = 2; + /// // ... + /// a += a + b; + /// ``` + #[clippy::version = "pre 1.29.0"] + pub MISREFACTORED_ASSIGN_OP, + suspicious, + "having a variable on both sides of an assign op" +} + +declare_clippy_lint! { + /// ### What it does + /// Checks for incompatible bit masks in comparisons. + /// + /// The formula for detecting if an expression of the type `_ <bit_op> m + /// <cmp_op> c` (where `<bit_op>` is one of {`&`, `|`} and `<cmp_op>` is one of + /// {`!=`, `>=`, `>`, `!=`, `>=`, `>`}) can be determined from the following + /// table: + /// + /// |Comparison |Bit Op|Example |is always|Formula | + /// |------------|------|-------------|---------|----------------------| + /// |`==` or `!=`| `&` |`x & 2 == 3` |`false` |`c & m != c` | + /// |`<` or `>=`| `&` |`x & 2 < 3` |`true` |`m < c` | + /// |`>` or `<=`| `&` |`x & 1 > 1` |`false` |`m <= c` | + /// |`==` or `!=`| `\|` |`x \| 1 == 0`|`false` |`c \| m != c` | + /// |`<` or `>=`| `\|` |`x \| 1 < 1` |`false` |`m >= c` | + /// |`<=` or `>` | `\|` |`x \| 1 > 0` |`true` |`m > c` | + /// + /// ### Why is this bad? + /// If the bits that the comparison cares about are always + /// set to zero or one by the bit mask, the comparison is constant `true` or + /// `false` (depending on mask, compared value, and operators). + /// + /// So the code is actively misleading, and the only reason someone would write + /// this intentionally is to win an underhanded Rust contest or create a + /// test-case for this lint. + /// + /// ### Example + /// ```rust + /// # let x = 1; + /// if (x & 1 == 2) { } + /// ``` + #[clippy::version = "pre 1.29.0"] + pub BAD_BIT_MASK, + correctness, + "expressions of the form `_ & mask == select` that will only ever return `true` or `false`" +} + +declare_clippy_lint! { + /// ### What it does + /// Checks for bit masks in comparisons which can be removed + /// without changing the outcome. The basic structure can be seen in the + /// following table: + /// + /// |Comparison| Bit Op |Example |equals | + /// |----------|----------|------------|-------| + /// |`>` / `<=`|`\|` / `^`|`x \| 2 > 3`|`x > 3`| + /// |`<` / `>=`|`\|` / `^`|`x ^ 1 < 4` |`x < 4`| + /// + /// ### Why is this bad? + /// Not equally evil as [`bad_bit_mask`](#bad_bit_mask), + /// but still a bit misleading, because the bit mask is ineffective. + /// + /// ### Known problems + /// False negatives: This lint will only match instances + /// where we have figured out the math (which is for a power-of-two compared + /// value). This means things like `x | 1 >= 7` (which would be better written + /// as `x >= 6`) will not be reported (but bit masks like this are fairly + /// uncommon). + /// + /// ### Example + /// ```rust + /// # let x = 1; + /// if (x | 1 > 3) { } + /// ``` + #[clippy::version = "pre 1.29.0"] + pub INEFFECTIVE_BIT_MASK, + correctness, + "expressions where a bit mask will be rendered useless by a comparison, e.g., `(x | 1) > 2`" +} + +declare_clippy_lint! { + /// ### What it does + /// Checks for bit masks that can be replaced by a call + /// to `trailing_zeros` + /// + /// ### Why is this bad? + /// `x.trailing_zeros() > 4` is much clearer than `x & 15 + /// == 0` + /// + /// ### Known problems + /// llvm generates better code for `x & 15 == 0` on x86 + /// + /// ### Example + /// ```rust + /// # let x = 1; + /// if x & 0b1111 == 0 { } + /// ``` + #[clippy::version = "pre 1.29.0"] + pub VERBOSE_BIT_MASK, + pedantic, + "expressions where a bit mask is less readable than the corresponding method call" +} + +declare_clippy_lint! { + /// ### What it does + /// Checks for double comparisons that could be simplified to a single expression. + /// + /// + /// ### Why is this bad? + /// Readability. + /// + /// ### Example + /// ```rust + /// # let x = 1; + /// # let y = 2; + /// if x == y || x < y {} + /// ``` + /// + /// Use instead: + /// + /// ```rust + /// # let x = 1; + /// # let y = 2; + /// if x <= y {} + /// ``` + #[clippy::version = "pre 1.29.0"] + pub DOUBLE_COMPARISONS, + complexity, + "unnecessary double comparisons that can be simplified" +} + +declare_clippy_lint! { + /// ### What it does + /// Checks for calculation of subsecond microseconds or milliseconds + /// from other `Duration` methods. + /// + /// ### Why is this bad? + /// It's more concise to call `Duration::subsec_micros()` or + /// `Duration::subsec_millis()` than to calculate them. + /// + /// ### Example + /// ```rust + /// # use std::time::Duration; + /// # let duration = Duration::new(5, 0); + /// let micros = duration.subsec_nanos() / 1_000; + /// let millis = duration.subsec_nanos() / 1_000_000; + /// ``` + /// + /// Use instead: + /// ```rust + /// # use std::time::Duration; + /// # let duration = Duration::new(5, 0); + /// let micros = duration.subsec_micros(); + /// let millis = duration.subsec_millis(); + /// ``` + #[clippy::version = "pre 1.29.0"] + pub DURATION_SUBSEC, + complexity, + "checks for calculation of subsecond microseconds or milliseconds" +} + +declare_clippy_lint! { + /// ### What it does + /// Checks for equal operands to comparison, logical and + /// bitwise, difference and division binary operators (`==`, `>`, etc., `&&`, + /// `||`, `&`, `|`, `^`, `-` and `/`). + /// + /// ### Why is this bad? + /// This is usually just a typo or a copy and paste error. + /// + /// ### Known problems + /// False negatives: We had some false positives regarding + /// calls (notably [racer](https://github.com/phildawes/racer) had one instance + /// of `x.pop() && x.pop()`), so we removed matching any function or method + /// calls. We may introduce a list of known pure functions in the future. + /// + /// ### Example + /// ```rust + /// # let x = 1; + /// if x + 1 == x + 1 {} + /// + /// // or + /// + /// # let a = 3; + /// # let b = 4; + /// assert_eq!(a, a); + /// ``` + #[clippy::version = "pre 1.29.0"] + pub EQ_OP, + correctness, + "equal operands on both sides of a comparison or bitwise combination (e.g., `x == x`)" +} + +declare_clippy_lint! { + /// ### What it does + /// Checks for arguments to `==` which have their address + /// taken to satisfy a bound + /// and suggests to dereference the other argument instead + /// + /// ### Why is this bad? + /// It is more idiomatic to dereference the other argument. + /// + /// ### Example + /// ```rust,ignore + /// &x == y + /// ``` + /// + /// Use instead: + /// ```rust,ignore + /// x == *y + /// ``` + #[clippy::version = "pre 1.29.0"] + pub OP_REF, + style, + "taking a reference to satisfy the type constraints on `==`" +} + +declare_clippy_lint! { + /// ### What it does + /// Checks for erasing operations, e.g., `x * 0`. + /// + /// ### Why is this bad? + /// The whole expression can be replaced by zero. + /// This is most likely not the intended outcome and should probably be + /// corrected + /// + /// ### Example + /// ```rust + /// let x = 1; + /// 0 / x; + /// 0 * x; + /// x & 0; + /// ``` + #[clippy::version = "pre 1.29.0"] + pub ERASING_OP, + correctness, + "using erasing operations, e.g., `x * 0` or `y & 0`" +} + +declare_clippy_lint! { + /// ### What it does + /// Checks for statements of the form `(a - b) < f32::EPSILON` or + /// `(a - b) < f64::EPSILON`. Notes the missing `.abs()`. + /// + /// ### Why is this bad? + /// The code without `.abs()` is more likely to have a bug. + /// + /// ### Known problems + /// If the user can ensure that b is larger than a, the `.abs()` is + /// technically unnecessary. However, it will make the code more robust and doesn't have any + /// large performance implications. If the abs call was deliberately left out for performance + /// reasons, it is probably better to state this explicitly in the code, which then can be done + /// with an allow. + /// + /// ### Example + /// ```rust + /// pub fn is_roughly_equal(a: f32, b: f32) -> bool { + /// (a - b) < f32::EPSILON + /// } + /// ``` + /// Use instead: + /// ```rust + /// pub fn is_roughly_equal(a: f32, b: f32) -> bool { + /// (a - b).abs() < f32::EPSILON + /// } + /// ``` + #[clippy::version = "1.48.0"] + pub FLOAT_EQUALITY_WITHOUT_ABS, + suspicious, + "float equality check without `.abs()`" +} + +declare_clippy_lint! { + /// ### What it does + /// Checks for identity operations, e.g., `x + 0`. + /// + /// ### Why is this bad? + /// This code can be removed without changing the + /// meaning. So it just obscures what's going on. Delete it mercilessly. + /// + /// ### Example + /// ```rust + /// # let x = 1; + /// x / 1 + 0 * 1 - 0 | 0; + /// ``` + #[clippy::version = "pre 1.29.0"] + pub IDENTITY_OP, + complexity, + "using identity operations, e.g., `x + 0` or `y / 1`" +} + +declare_clippy_lint! { + /// ### What it does + /// Checks for division of integers + /// + /// ### Why is this bad? + /// When outside of some very specific algorithms, + /// integer division is very often a mistake because it discards the + /// remainder. + /// + /// ### Example + /// ```rust + /// let x = 3 / 2; + /// println!("{}", x); + /// ``` + /// + /// Use instead: + /// ```rust + /// let x = 3f32 / 2f32; + /// println!("{}", x); + /// ``` + #[clippy::version = "1.37.0"] + pub INTEGER_DIVISION, + restriction, + "integer division may cause loss of precision" +} + +declare_clippy_lint! { + /// ### What it does + /// Checks for comparisons to NaN. + /// + /// ### Why is this bad? + /// NaN does not compare meaningfully to anything – not + /// even itself – so those comparisons are simply wrong. + /// + /// ### Example + /// ```rust + /// # let x = 1.0; + /// if x == f32::NAN { } + /// ``` + /// + /// Use instead: + /// ```rust + /// # let x = 1.0f32; + /// if x.is_nan() { } + /// ``` + #[clippy::version = "pre 1.29.0"] + pub CMP_NAN, + correctness, + "comparisons to `NAN`, which will always return false, probably not intended" +} + +declare_clippy_lint! { + /// ### What it does + /// Checks for conversions to owned values just for the sake + /// of a comparison. + /// + /// ### Why is this bad? + /// The comparison can operate on a reference, so creating + /// an owned value effectively throws it away directly afterwards, which is + /// needlessly consuming code and heap space. + /// + /// ### Example + /// ```rust + /// # let x = "foo"; + /// # let y = String::from("foo"); + /// if x.to_owned() == y {} + /// ``` + /// + /// Use instead: + /// ```rust + /// # let x = "foo"; + /// # let y = String::from("foo"); + /// if x == y {} + /// ``` + #[clippy::version = "pre 1.29.0"] + pub CMP_OWNED, + perf, + "creating owned instances for comparing with others, e.g., `x == \"foo\".to_string()`" +} + +declare_clippy_lint! { + /// ### What it does + /// Checks for (in-)equality comparisons on floating-point + /// values (apart from zero), except in functions called `*eq*` (which probably + /// implement equality for a type involving floats). + /// + /// ### Why is this bad? + /// Floating point calculations are usually imprecise, so + /// asking if two values are *exactly* equal is asking for trouble. For a good + /// guide on what to do, see [the floating point + /// guide](http://www.floating-point-gui.de/errors/comparison). + /// + /// ### Example + /// ```rust + /// let x = 1.2331f64; + /// let y = 1.2332f64; + /// + /// if y == 1.23f64 { } + /// if y != x {} // where both are floats + /// ``` + /// + /// Use instead: + /// ```rust + /// # let x = 1.2331f64; + /// # let y = 1.2332f64; + /// let error_margin = f64::EPSILON; // Use an epsilon for comparison + /// // Or, if Rust <= 1.42, use `std::f64::EPSILON` constant instead. + /// // let error_margin = std::f64::EPSILON; + /// if (y - 1.23f64).abs() < error_margin { } + /// if (y - x).abs() > error_margin { } + /// ``` + #[clippy::version = "pre 1.29.0"] + pub FLOAT_CMP, + pedantic, + "using `==` or `!=` on float values instead of comparing difference with an epsilon" +} + +declare_clippy_lint! { + /// ### What it does + /// Checks for (in-)equality comparisons on floating-point + /// value and constant, except in functions called `*eq*` (which probably + /// implement equality for a type involving floats). + /// + /// ### Why is this bad? + /// Floating point calculations are usually imprecise, so + /// asking if two values are *exactly* equal is asking for trouble. For a good + /// guide on what to do, see [the floating point + /// guide](http://www.floating-point-gui.de/errors/comparison). + /// + /// ### Example + /// ```rust + /// let x: f64 = 1.0; + /// const ONE: f64 = 1.00; + /// + /// if x == ONE { } // where both are floats + /// ``` + /// + /// Use instead: + /// ```rust + /// # let x: f64 = 1.0; + /// # const ONE: f64 = 1.00; + /// let error_margin = f64::EPSILON; // Use an epsilon for comparison + /// // Or, if Rust <= 1.42, use `std::f64::EPSILON` constant instead. + /// // let error_margin = std::f64::EPSILON; + /// if (x - ONE).abs() < error_margin { } + /// ``` + #[clippy::version = "pre 1.29.0"] + pub FLOAT_CMP_CONST, + restriction, + "using `==` or `!=` on float constants instead of comparing difference with an epsilon" +} + +declare_clippy_lint! { + /// ### What it does + /// Checks for getting the remainder of a division by one or minus + /// one. + /// + /// ### Why is this bad? + /// The result for a divisor of one can only ever be zero; for + /// minus one it can cause panic/overflow (if the left operand is the minimal value of + /// the respective integer type) or results in zero. No one will write such code + /// deliberately, unless trying to win an Underhanded Rust Contest. Even for that + /// contest, it's probably a bad idea. Use something more underhanded. + /// + /// ### Example + /// ```rust + /// # let x = 1; + /// let a = x % 1; + /// let a = x % -1; + /// ``` + #[clippy::version = "pre 1.29.0"] + pub MODULO_ONE, + correctness, + "taking a number modulo +/-1, which can either panic/overflow or always returns 0" +} + +declare_clippy_lint! { + /// ### What it does + /// Checks for modulo arithmetic. + /// + /// ### Why is this bad? + /// The results of modulo (%) operation might differ + /// depending on the language, when negative numbers are involved. + /// If you interop with different languages it might be beneficial + /// to double check all places that use modulo arithmetic. + /// + /// For example, in Rust `17 % -3 = 2`, but in Python `17 % -3 = -1`. + /// + /// ### Example + /// ```rust + /// let x = -17 % 3; + /// ``` + #[clippy::version = "1.42.0"] + pub MODULO_ARITHMETIC, + restriction, + "any modulo arithmetic statement" +} + +declare_clippy_lint! { + /// ### What it does + /// Checks for uses of bitwise and/or operators between booleans, where performance may be improved by using + /// a lazy and. + /// + /// ### Why is this bad? + /// The bitwise operators do not support short-circuiting, so it may hinder code performance. + /// Additionally, boolean logic "masked" as bitwise logic is not caught by lints like `unnecessary_fold` + /// + /// ### Known problems + /// This lint evaluates only when the right side is determined to have no side effects. At this time, that + /// determination is quite conservative. + /// + /// ### Example + /// ```rust + /// let (x,y) = (true, false); + /// if x & !y {} // where both x and y are booleans + /// ``` + /// Use instead: + /// ```rust + /// let (x,y) = (true, false); + /// if x && !y {} + /// ``` + #[clippy::version = "1.54.0"] + pub NEEDLESS_BITWISE_BOOL, + pedantic, + "Boolean expressions that use bitwise rather than lazy operators" +} + +declare_clippy_lint! { + /// ### What it does + /// Use `std::ptr::eq` when applicable + /// + /// ### Why is this bad? + /// `ptr::eq` can be used to compare `&T` references + /// (which coerce to `*const T` implicitly) by their address rather than + /// comparing the values they point to. + /// + /// ### Example + /// ```rust + /// let a = &[1, 2, 3]; + /// let b = &[1, 2, 3]; + /// + /// assert!(a as *const _ as usize == b as *const _ as usize); + /// ``` + /// Use instead: + /// ```rust + /// let a = &[1, 2, 3]; + /// let b = &[1, 2, 3]; + /// + /// assert!(std::ptr::eq(a, b)); + /// ``` + #[clippy::version = "1.49.0"] + pub PTR_EQ, + style, + "use `std::ptr::eq` when comparing raw pointers" +} + +declare_clippy_lint! { + /// ### What it does + /// Checks for explicit self-assignments. + /// + /// ### Why is this bad? + /// Self-assignments are redundant and unlikely to be + /// intentional. + /// + /// ### Known problems + /// If expression contains any deref coercions or + /// indexing operations they are assumed not to have any side effects. + /// + /// ### Example + /// ```rust + /// struct Event { + /// x: i32, + /// } + /// + /// fn copy_position(a: &mut Event, b: &Event) { + /// a.x = a.x; + /// } + /// ``` + /// + /// Should be: + /// ```rust + /// struct Event { + /// x: i32, + /// } + /// + /// fn copy_position(a: &mut Event, b: &Event) { + /// a.x = b.x; + /// } + /// ``` + #[clippy::version = "1.48.0"] + pub SELF_ASSIGNMENT, + correctness, + "explicit self-assignment" +} + +pub struct Operators { + arithmetic_context: numeric_arithmetic::Context, + verbose_bit_mask_threshold: u64, +} +impl_lint_pass!(Operators => [ + ABSURD_EXTREME_COMPARISONS, + INTEGER_ARITHMETIC, + FLOAT_ARITHMETIC, + ASSIGN_OP_PATTERN, + MISREFACTORED_ASSIGN_OP, + BAD_BIT_MASK, + INEFFECTIVE_BIT_MASK, + VERBOSE_BIT_MASK, + DOUBLE_COMPARISONS, + DURATION_SUBSEC, + EQ_OP, + OP_REF, + ERASING_OP, + FLOAT_EQUALITY_WITHOUT_ABS, + IDENTITY_OP, + INTEGER_DIVISION, + CMP_NAN, + CMP_OWNED, + FLOAT_CMP, + FLOAT_CMP_CONST, + MODULO_ONE, + MODULO_ARITHMETIC, + NEEDLESS_BITWISE_BOOL, + PTR_EQ, + SELF_ASSIGNMENT, +]); +impl Operators { + pub fn new(verbose_bit_mask_threshold: u64) -> Self { + Self { + arithmetic_context: numeric_arithmetic::Context::default(), + verbose_bit_mask_threshold, + } + } +} +impl<'tcx> LateLintPass<'tcx> for Operators { + fn check_expr(&mut self, cx: &LateContext<'tcx>, e: &'tcx Expr<'_>) { + eq_op::check_assert(cx, e); + match e.kind { + ExprKind::Binary(op, lhs, rhs) => { + if !e.span.from_expansion() { + absurd_extreme_comparisons::check(cx, e, op.node, lhs, rhs); + if !(macro_with_not_op(lhs) || macro_with_not_op(rhs)) { + eq_op::check(cx, e, op.node, lhs, rhs); + op_ref::check(cx, e, op.node, lhs, rhs); + } + erasing_op::check(cx, e, op.node, lhs, rhs); + identity_op::check(cx, e, op.node, lhs, rhs); + needless_bitwise_bool::check(cx, e, op.node, lhs, rhs); + ptr_eq::check(cx, e, op.node, lhs, rhs); + } + self.arithmetic_context.check_binary(cx, e, op.node, lhs, rhs); + bit_mask::check(cx, e, op.node, lhs, rhs); + verbose_bit_mask::check(cx, e, op.node, lhs, rhs, self.verbose_bit_mask_threshold); + double_comparison::check(cx, op.node, lhs, rhs, e.span); + duration_subsec::check(cx, e, op.node, lhs, rhs); + float_equality_without_abs::check(cx, e, op.node, lhs, rhs); + integer_division::check(cx, e, op.node, lhs, rhs); + cmp_nan::check(cx, e, op.node, lhs, rhs); + cmp_owned::check(cx, op.node, lhs, rhs); + float_cmp::check(cx, e, op.node, lhs, rhs); + modulo_one::check(cx, e, op.node, rhs); + modulo_arithmetic::check(cx, e, op.node, lhs, rhs); + }, + ExprKind::AssignOp(op, lhs, rhs) => { + self.arithmetic_context.check_binary(cx, e, op.node, lhs, rhs); + misrefactored_assign_op::check(cx, e, op.node, lhs, rhs); + modulo_arithmetic::check(cx, e, op.node, lhs, rhs); + }, + ExprKind::Assign(lhs, rhs, _) => { + assign_op_pattern::check(cx, e, lhs, rhs); + self_assignment::check(cx, e, lhs, rhs); + }, + ExprKind::Unary(op, arg) => { + if op == UnOp::Neg { + self.arithmetic_context.check_negate(cx, e, arg); + } + }, + _ => (), + } + } + + fn check_expr_post(&mut self, _: &LateContext<'_>, e: &Expr<'_>) { + self.arithmetic_context.expr_post(e.hir_id); + } + + fn check_body(&mut self, cx: &LateContext<'tcx>, b: &'tcx Body<'_>) { + self.arithmetic_context.enter_body(cx, b); + } + + fn check_body_post(&mut self, cx: &LateContext<'tcx>, b: &'tcx Body<'_>) { + self.arithmetic_context.body_post(cx, b); + } +} + +fn macro_with_not_op(e: &Expr<'_>) -> bool { + if let ExprKind::Unary(_, e) = e.kind { + e.span.from_expansion() + } else { + false + } +} diff --git a/src/tools/clippy/clippy_lints/src/modulo_arithmetic.rs b/src/tools/clippy/clippy_lints/src/operators/modulo_arithmetic.rs index 195b2e5c2ee..af4e74947f4 100644 --- a/src/tools/clippy/clippy_lints/src/modulo_arithmetic.rs +++ b/src/tools/clippy/clippy_lints/src/operators/modulo_arithmetic.rs @@ -2,35 +2,35 @@ use clippy_utils::consts::{constant, Constant}; use clippy_utils::diagnostics::span_lint_and_then; use clippy_utils::sext; use if_chain::if_chain; -use rustc_hir::{BinOpKind, Expr, ExprKind}; -use rustc_lint::{LateContext, LateLintPass}; +use rustc_hir::{BinOpKind, Expr}; +use rustc_lint::LateContext; use rustc_middle::ty::{self, Ty}; -use rustc_session::{declare_lint_pass, declare_tool_lint}; use std::fmt::Display; -declare_clippy_lint! { - /// ### What it does - /// Checks for modulo arithmetic. - /// - /// ### Why is this bad? - /// The results of modulo (%) operation might differ - /// depending on the language, when negative numbers are involved. - /// If you interop with different languages it might be beneficial - /// to double check all places that use modulo arithmetic. - /// - /// For example, in Rust `17 % -3 = 2`, but in Python `17 % -3 = -1`. - /// - /// ### Example - /// ```rust - /// let x = -17 % 3; - /// ``` - #[clippy::version = "1.42.0"] - pub MODULO_ARITHMETIC, - restriction, - "any modulo arithmetic statement" -} +use super::MODULO_ARITHMETIC; -declare_lint_pass!(ModuloArithmetic => [MODULO_ARITHMETIC]); +pub(super) fn check<'tcx>( + cx: &LateContext<'tcx>, + e: &'tcx Expr<'_>, + op: BinOpKind, + lhs: &'tcx Expr<'_>, + rhs: &'tcx Expr<'_>, +) { + if op == BinOpKind::Rem { + let lhs_operand = analyze_operand(lhs, cx, e); + let rhs_operand = analyze_operand(rhs, cx, e); + if_chain! { + if let Some(lhs_operand) = lhs_operand; + if let Some(rhs_operand) = rhs_operand; + then { + check_const_operands(cx, e, &lhs_operand, &rhs_operand); + } + else { + check_non_const_operands(cx, e, lhs); + } + } + }; +} struct OperandInfo { string_representation: Option<String>, @@ -124,27 +124,3 @@ fn check_non_const_operands<'tcx>(cx: &LateContext<'tcx>, expr: &'tcx Expr<'_>, ); } } - -impl<'tcx> LateLintPass<'tcx> for ModuloArithmetic { - fn check_expr(&mut self, cx: &LateContext<'tcx>, expr: &'tcx Expr<'_>) { - match &expr.kind { - ExprKind::Binary(op, lhs, rhs) | ExprKind::AssignOp(op, lhs, rhs) => { - if op.node == BinOpKind::Rem { - let lhs_operand = analyze_operand(lhs, cx, expr); - let rhs_operand = analyze_operand(rhs, cx, expr); - if_chain! { - if let Some(lhs_operand) = lhs_operand; - if let Some(rhs_operand) = rhs_operand; - then { - check_const_operands(cx, expr, &lhs_operand, &rhs_operand); - } - else { - check_non_const_operands(cx, expr, lhs); - } - } - }; - }, - _ => {}, - } - } -} diff --git a/src/tools/clippy/clippy_lints/src/operators/modulo_one.rs b/src/tools/clippy/clippy_lints/src/operators/modulo_one.rs new file mode 100644 index 00000000000..54eea14833f --- /dev/null +++ b/src/tools/clippy/clippy_lints/src/operators/modulo_one.rs @@ -0,0 +1,26 @@ +use clippy_utils::diagnostics::span_lint; +use clippy_utils::{is_integer_const, unsext}; +use rustc_hir::{BinOpKind, Expr}; +use rustc_lint::LateContext; +use rustc_middle::ty; + +use super::MODULO_ONE; + +pub(crate) fn check(cx: &LateContext<'_>, expr: &Expr<'_>, op: BinOpKind, right: &Expr<'_>) { + if op == BinOpKind::Rem { + if is_integer_const(cx, right, 1) { + span_lint(cx, MODULO_ONE, expr.span, "any number modulo 1 will be 0"); + } + + if let ty::Int(ity) = cx.typeck_results().expr_ty(right).kind() { + if is_integer_const(cx, right, unsext(cx.tcx, -1, *ity)) { + span_lint( + cx, + MODULO_ONE, + expr.span, + "any number modulo -1 will panic/overflow or result in 0", + ); + } + }; + } +} diff --git a/src/tools/clippy/clippy_lints/src/operators/needless_bitwise_bool.rs b/src/tools/clippy/clippy_lints/src/operators/needless_bitwise_bool.rs new file mode 100644 index 00000000000..e902235a014 --- /dev/null +++ b/src/tools/clippy/clippy_lints/src/operators/needless_bitwise_bool.rs @@ -0,0 +1,36 @@ +use clippy_utils::diagnostics::span_lint_and_then; +use clippy_utils::source::snippet_opt; +use rustc_errors::Applicability; +use rustc_hir::{BinOpKind, Expr, ExprKind}; +use rustc_lint::LateContext; + +use super::NEEDLESS_BITWISE_BOOL; + +pub(super) fn check(cx: &LateContext<'_>, e: &Expr<'_>, op: BinOpKind, lhs: &Expr<'_>, rhs: &Expr<'_>) { + let op_str = match op { + BinOpKind::BitAnd => "&&", + BinOpKind::BitOr => "||", + _ => return, + }; + if matches!( + rhs.kind, + ExprKind::Call(..) | ExprKind::MethodCall(..) | ExprKind::Binary(..) | ExprKind::Unary(..) + ) && cx.typeck_results().expr_ty(e).is_bool() + && !rhs.can_have_side_effects() + { + span_lint_and_then( + cx, + NEEDLESS_BITWISE_BOOL, + e.span, + "use of bitwise operator instead of lazy operator between booleans", + |diag| { + if let Some(lhs_snip) = snippet_opt(cx, lhs.span) + && let Some(rhs_snip) = snippet_opt(cx, rhs.span) + { + let sugg = format!("{} {} {}", lhs_snip, op_str, rhs_snip); + diag.span_suggestion(e.span, "try", sugg, Applicability::MachineApplicable); + } + }, + ); + } +} diff --git a/src/tools/clippy/clippy_lints/src/operators/numeric_arithmetic.rs b/src/tools/clippy/clippy_lints/src/operators/numeric_arithmetic.rs new file mode 100644 index 00000000000..b6097710dc6 --- /dev/null +++ b/src/tools/clippy/clippy_lints/src/operators/numeric_arithmetic.rs @@ -0,0 +1,128 @@ +use clippy_utils::consts::constant_simple; +use clippy_utils::diagnostics::span_lint; +use rustc_hir as hir; +use rustc_lint::LateContext; +use rustc_span::source_map::Span; + +use super::{FLOAT_ARITHMETIC, INTEGER_ARITHMETIC}; + +#[derive(Default)] +pub struct Context { + expr_id: Option<hir::HirId>, + /// This field is used to check whether expressions are constants, such as in enum discriminants + /// and consts + const_span: Option<Span>, +} +impl Context { + fn skip_expr(&mut self, e: &hir::Expr<'_>) -> bool { + self.expr_id.is_some() || self.const_span.map_or(false, |span| span.contains(e.span)) + } + + pub fn check_binary<'tcx>( + &mut self, + cx: &LateContext<'tcx>, + expr: &'tcx hir::Expr<'_>, + op: hir::BinOpKind, + l: &'tcx hir::Expr<'_>, + r: &'tcx hir::Expr<'_>, + ) { + if self.skip_expr(expr) { + return; + } + match op { + hir::BinOpKind::And + | hir::BinOpKind::Or + | hir::BinOpKind::BitAnd + | hir::BinOpKind::BitOr + | hir::BinOpKind::BitXor + | hir::BinOpKind::Eq + | hir::BinOpKind::Lt + | hir::BinOpKind::Le + | hir::BinOpKind::Ne + | hir::BinOpKind::Ge + | hir::BinOpKind::Gt => return, + _ => (), + } + + let (l_ty, r_ty) = (cx.typeck_results().expr_ty(l), cx.typeck_results().expr_ty(r)); + if l_ty.peel_refs().is_integral() && r_ty.peel_refs().is_integral() { + match op { + hir::BinOpKind::Div | hir::BinOpKind::Rem => match &r.kind { + hir::ExprKind::Lit(_lit) => (), + hir::ExprKind::Unary(hir::UnOp::Neg, expr) => { + if let hir::ExprKind::Lit(lit) = &expr.kind { + if let rustc_ast::ast::LitKind::Int(1, _) = lit.node { + span_lint(cx, INTEGER_ARITHMETIC, expr.span, "integer arithmetic detected"); + self.expr_id = Some(expr.hir_id); + } + } + }, + _ => { + span_lint(cx, INTEGER_ARITHMETIC, expr.span, "integer arithmetic detected"); + self.expr_id = Some(expr.hir_id); + }, + }, + _ => { + span_lint(cx, INTEGER_ARITHMETIC, expr.span, "integer arithmetic detected"); + self.expr_id = Some(expr.hir_id); + }, + } + } else if r_ty.peel_refs().is_floating_point() && r_ty.peel_refs().is_floating_point() { + span_lint(cx, FLOAT_ARITHMETIC, expr.span, "floating-point arithmetic detected"); + self.expr_id = Some(expr.hir_id); + } + } + + pub fn check_negate<'tcx>(&mut self, cx: &LateContext<'tcx>, expr: &'tcx hir::Expr<'_>, arg: &'tcx hir::Expr<'_>) { + if self.skip_expr(expr) { + return; + } + let ty = cx.typeck_results().expr_ty(arg); + if constant_simple(cx, cx.typeck_results(), expr).is_none() { + if ty.is_integral() { + span_lint(cx, INTEGER_ARITHMETIC, expr.span, "integer arithmetic detected"); + self.expr_id = Some(expr.hir_id); + } else if ty.is_floating_point() { + span_lint(cx, FLOAT_ARITHMETIC, expr.span, "floating-point arithmetic detected"); + self.expr_id = Some(expr.hir_id); + } + } + } + + pub fn expr_post(&mut self, id: hir::HirId) { + if Some(id) == self.expr_id { + self.expr_id = None; + } + } + + pub fn enter_body(&mut self, cx: &LateContext<'_>, body: &hir::Body<'_>) { + let body_owner = cx.tcx.hir().body_owner(body.id()); + let body_owner_def_id = cx.tcx.hir().local_def_id(body_owner); + + match cx.tcx.hir().body_owner_kind(body_owner_def_id) { + hir::BodyOwnerKind::Static(_) | hir::BodyOwnerKind::Const => { + let body_span = cx.tcx.hir().span_with_body(body_owner); + + if let Some(span) = self.const_span { + if span.contains(body_span) { + return; + } + } + self.const_span = Some(body_span); + }, + hir::BodyOwnerKind::Fn | hir::BodyOwnerKind::Closure => (), + } + } + + pub fn body_post(&mut self, cx: &LateContext<'_>, body: &hir::Body<'_>) { + let body_owner = cx.tcx.hir().body_owner(body.id()); + let body_span = cx.tcx.hir().span_with_body(body_owner); + + if let Some(span) = self.const_span { + if span.contains(body_span) { + return; + } + } + self.const_span = None; + } +} diff --git a/src/tools/clippy/clippy_lints/src/operators/op_ref.rs b/src/tools/clippy/clippy_lints/src/operators/op_ref.rs new file mode 100644 index 00000000000..1805672e372 --- /dev/null +++ b/src/tools/clippy/clippy_lints/src/operators/op_ref.rs @@ -0,0 +1,218 @@ +use clippy_utils::diagnostics::{multispan_sugg, span_lint_and_then}; +use clippy_utils::get_enclosing_block; +use clippy_utils::source::snippet; +use clippy_utils::ty::{implements_trait, is_copy}; +use if_chain::if_chain; +use rustc_errors::Applicability; +use rustc_hir::{def::Res, def_id::DefId, BinOpKind, BorrowKind, Expr, ExprKind, GenericArg, ItemKind, QPath, TyKind}; +use rustc_lint::LateContext; +use rustc_middle::ty::{self, Ty}; + +use super::OP_REF; + +#[expect(clippy::similar_names, clippy::too_many_lines)] +pub(crate) fn check<'tcx>( + cx: &LateContext<'tcx>, + e: &'tcx Expr<'_>, + op: BinOpKind, + left: &'tcx Expr<'_>, + right: &'tcx Expr<'_>, +) { + let (trait_id, requires_ref) = match op { + BinOpKind::Add => (cx.tcx.lang_items().add_trait(), false), + BinOpKind::Sub => (cx.tcx.lang_items().sub_trait(), false), + BinOpKind::Mul => (cx.tcx.lang_items().mul_trait(), false), + BinOpKind::Div => (cx.tcx.lang_items().div_trait(), false), + BinOpKind::Rem => (cx.tcx.lang_items().rem_trait(), false), + // don't lint short circuiting ops + BinOpKind::And | BinOpKind::Or => return, + BinOpKind::BitXor => (cx.tcx.lang_items().bitxor_trait(), false), + BinOpKind::BitAnd => (cx.tcx.lang_items().bitand_trait(), false), + BinOpKind::BitOr => (cx.tcx.lang_items().bitor_trait(), false), + BinOpKind::Shl => (cx.tcx.lang_items().shl_trait(), false), + BinOpKind::Shr => (cx.tcx.lang_items().shr_trait(), false), + BinOpKind::Ne | BinOpKind::Eq => (cx.tcx.lang_items().eq_trait(), true), + BinOpKind::Lt | BinOpKind::Le | BinOpKind::Ge | BinOpKind::Gt => { + (cx.tcx.lang_items().partial_ord_trait(), true) + }, + }; + if let Some(trait_id) = trait_id { + match (&left.kind, &right.kind) { + // do not suggest to dereference literals + (&ExprKind::Lit(..), _) | (_, &ExprKind::Lit(..)) => {}, + // &foo == &bar + (&ExprKind::AddrOf(BorrowKind::Ref, _, l), &ExprKind::AddrOf(BorrowKind::Ref, _, r)) => { + let lty = cx.typeck_results().expr_ty(l); + let rty = cx.typeck_results().expr_ty(r); + let lcpy = is_copy(cx, lty); + let rcpy = is_copy(cx, rty); + if let Some((self_ty, other_ty)) = in_impl(cx, e, trait_id) { + if (are_equal(cx, rty, self_ty) && are_equal(cx, lty, other_ty)) + || (are_equal(cx, rty, other_ty) && are_equal(cx, lty, self_ty)) + { + return; // Don't lint + } + } + // either operator autorefs or both args are copyable + if (requires_ref || (lcpy && rcpy)) && implements_trait(cx, lty, trait_id, &[rty.into()]) { + span_lint_and_then( + cx, + OP_REF, + e.span, + "needlessly taken reference of both operands", + |diag| { + let lsnip = snippet(cx, l.span, "...").to_string(); + let rsnip = snippet(cx, r.span, "...").to_string(); + multispan_sugg( + diag, + "use the values directly", + vec![(left.span, lsnip), (right.span, rsnip)], + ); + }, + ); + } else if lcpy + && !rcpy + && implements_trait(cx, lty, trait_id, &[cx.typeck_results().expr_ty(right).into()]) + { + span_lint_and_then( + cx, + OP_REF, + e.span, + "needlessly taken reference of left operand", + |diag| { + let lsnip = snippet(cx, l.span, "...").to_string(); + diag.span_suggestion( + left.span, + "use the left value directly", + lsnip, + Applicability::MaybeIncorrect, // FIXME #2597 + ); + }, + ); + } else if !lcpy + && rcpy + && implements_trait(cx, cx.typeck_results().expr_ty(left), trait_id, &[rty.into()]) + { + span_lint_and_then( + cx, + OP_REF, + e.span, + "needlessly taken reference of right operand", + |diag| { + let rsnip = snippet(cx, r.span, "...").to_string(); + diag.span_suggestion( + right.span, + "use the right value directly", + rsnip, + Applicability::MaybeIncorrect, // FIXME #2597 + ); + }, + ); + } + }, + // &foo == bar + (&ExprKind::AddrOf(BorrowKind::Ref, _, l), _) => { + let lty = cx.typeck_results().expr_ty(l); + if let Some((self_ty, other_ty)) = in_impl(cx, e, trait_id) { + let rty = cx.typeck_results().expr_ty(right); + if (are_equal(cx, rty, self_ty) && are_equal(cx, lty, other_ty)) + || (are_equal(cx, rty, other_ty) && are_equal(cx, lty, self_ty)) + { + return; // Don't lint + } + } + let lcpy = is_copy(cx, lty); + if (requires_ref || lcpy) + && implements_trait(cx, lty, trait_id, &[cx.typeck_results().expr_ty(right).into()]) + { + span_lint_and_then( + cx, + OP_REF, + e.span, + "needlessly taken reference of left operand", + |diag| { + let lsnip = snippet(cx, l.span, "...").to_string(); + diag.span_suggestion( + left.span, + "use the left value directly", + lsnip, + Applicability::MaybeIncorrect, // FIXME #2597 + ); + }, + ); + } + }, + // foo == &bar + (_, &ExprKind::AddrOf(BorrowKind::Ref, _, r)) => { + let rty = cx.typeck_results().expr_ty(r); + if let Some((self_ty, other_ty)) = in_impl(cx, e, trait_id) { + let lty = cx.typeck_results().expr_ty(left); + if (are_equal(cx, rty, self_ty) && are_equal(cx, lty, other_ty)) + || (are_equal(cx, rty, other_ty) && are_equal(cx, lty, self_ty)) + { + return; // Don't lint + } + } + let rcpy = is_copy(cx, rty); + if (requires_ref || rcpy) + && implements_trait(cx, cx.typeck_results().expr_ty(left), trait_id, &[rty.into()]) + { + span_lint_and_then(cx, OP_REF, e.span, "taken reference of right operand", |diag| { + let rsnip = snippet(cx, r.span, "...").to_string(); + diag.span_suggestion( + right.span, + "use the right value directly", + rsnip, + Applicability::MaybeIncorrect, // FIXME #2597 + ); + }); + } + }, + _ => {}, + } + } +} + +fn in_impl<'tcx>( + cx: &LateContext<'tcx>, + e: &'tcx Expr<'_>, + bin_op: DefId, +) -> Option<(&'tcx rustc_hir::Ty<'tcx>, &'tcx rustc_hir::Ty<'tcx>)> { + if_chain! { + if let Some(block) = get_enclosing_block(cx, e.hir_id); + if let Some(impl_def_id) = cx.tcx.impl_of_method(block.hir_id.owner.to_def_id()); + let item = cx.tcx.hir().expect_item(impl_def_id.expect_local()); + if let ItemKind::Impl(item) = &item.kind; + if let Some(of_trait) = &item.of_trait; + if let Some(seg) = of_trait.path.segments.last(); + if let Some(Res::Def(_, trait_id)) = seg.res; + if trait_id == bin_op; + if let Some(generic_args) = seg.args; + if let Some(GenericArg::Type(other_ty)) = generic_args.args.last(); + + then { + Some((item.self_ty, other_ty)) + } + else { + None + } + } +} + +fn are_equal<'tcx>(cx: &LateContext<'tcx>, middle_ty: Ty<'_>, hir_ty: &rustc_hir::Ty<'_>) -> bool { + if_chain! { + if let ty::Adt(adt_def, _) = middle_ty.kind(); + if let Some(local_did) = adt_def.did().as_local(); + let item = cx.tcx.hir().expect_item(local_did); + let middle_ty_id = item.def_id.to_def_id(); + if let TyKind::Path(QPath::Resolved(_, path)) = hir_ty.kind; + if let Res::Def(_, hir_ty_id) = path.res; + + then { + hir_ty_id == middle_ty_id + } + else { + false + } + } +} diff --git a/src/tools/clippy/clippy_lints/src/operators/ptr_eq.rs b/src/tools/clippy/clippy_lints/src/operators/ptr_eq.rs new file mode 100644 index 00000000000..1aefc2741c2 --- /dev/null +++ b/src/tools/clippy/clippy_lints/src/operators/ptr_eq.rs @@ -0,0 +1,65 @@ +use clippy_utils::diagnostics::span_lint_and_sugg; +use clippy_utils::source::snippet_opt; +use if_chain::if_chain; +use rustc_errors::Applicability; +use rustc_hir::{BinOpKind, Expr, ExprKind}; +use rustc_lint::LateContext; + +use super::PTR_EQ; + +static LINT_MSG: &str = "use `std::ptr::eq` when comparing raw pointers"; + +pub(super) fn check<'tcx>( + cx: &LateContext<'tcx>, + expr: &'tcx Expr<'_>, + op: BinOpKind, + left: &'tcx Expr<'_>, + right: &'tcx Expr<'_>, +) { + if BinOpKind::Eq == op { + let (left, right) = match (expr_as_cast_to_usize(cx, left), expr_as_cast_to_usize(cx, right)) { + (Some(lhs), Some(rhs)) => (lhs, rhs), + _ => (left, right), + }; + + if_chain! { + if let Some(left_var) = expr_as_cast_to_raw_pointer(cx, left); + if let Some(right_var) = expr_as_cast_to_raw_pointer(cx, right); + if let Some(left_snip) = snippet_opt(cx, left_var.span); + if let Some(right_snip) = snippet_opt(cx, right_var.span); + then { + span_lint_and_sugg( + cx, + PTR_EQ, + expr.span, + LINT_MSG, + "try", + format!("std::ptr::eq({}, {})", left_snip, right_snip), + Applicability::MachineApplicable, + ); + } + } + } +} + +// If the given expression is a cast to a usize, return the lhs of the cast +// E.g., `foo as *const _ as usize` returns `foo as *const _`. +fn expr_as_cast_to_usize<'tcx>(cx: &LateContext<'tcx>, cast_expr: &'tcx Expr<'_>) -> Option<&'tcx Expr<'tcx>> { + if cx.typeck_results().expr_ty(cast_expr) == cx.tcx.types.usize { + if let ExprKind::Cast(expr, _) = cast_expr.kind { + return Some(expr); + } + } + None +} + +// If the given expression is a cast to a `*const` pointer, return the lhs of the cast +// E.g., `foo as *const _` returns `foo`. +fn expr_as_cast_to_raw_pointer<'tcx>(cx: &LateContext<'tcx>, cast_expr: &'tcx Expr<'_>) -> Option<&'tcx Expr<'tcx>> { + if cx.typeck_results().expr_ty(cast_expr).is_unsafe_ptr() { + if let ExprKind::Cast(expr, _) = cast_expr.kind { + return Some(expr); + } + } + None +} diff --git a/src/tools/clippy/clippy_lints/src/operators/self_assignment.rs b/src/tools/clippy/clippy_lints/src/operators/self_assignment.rs new file mode 100644 index 00000000000..9d6bec05bf0 --- /dev/null +++ b/src/tools/clippy/clippy_lints/src/operators/self_assignment.rs @@ -0,0 +1,20 @@ +use clippy_utils::diagnostics::span_lint; +use clippy_utils::eq_expr_value; +use clippy_utils::source::snippet; +use rustc_hir::Expr; +use rustc_lint::LateContext; + +use super::SELF_ASSIGNMENT; + +pub(super) fn check<'tcx>(cx: &LateContext<'tcx>, e: &'tcx Expr<'_>, lhs: &'tcx Expr<'_>, rhs: &'tcx Expr<'_>) { + if eq_expr_value(cx, lhs, rhs) { + let lhs = snippet(cx, lhs.span, "<lhs>"); + let rhs = snippet(cx, rhs.span, "<rhs>"); + span_lint( + cx, + SELF_ASSIGNMENT, + e.span, + &format!("self-assignment of `{}` to `{}`", rhs, lhs), + ); + } +} diff --git a/src/tools/clippy/clippy_lints/src/operators/verbose_bit_mask.rs b/src/tools/clippy/clippy_lints/src/operators/verbose_bit_mask.rs new file mode 100644 index 00000000000..ff85fd55429 --- /dev/null +++ b/src/tools/clippy/clippy_lints/src/operators/verbose_bit_mask.rs @@ -0,0 +1,44 @@ +use clippy_utils::diagnostics::span_lint_and_then; +use clippy_utils::sugg::Sugg; +use rustc_ast::ast::LitKind; +use rustc_errors::Applicability; +use rustc_hir::{BinOpKind, Expr, ExprKind}; +use rustc_lint::LateContext; + +use super::VERBOSE_BIT_MASK; + +pub(super) fn check<'tcx>( + cx: &LateContext<'tcx>, + e: &'tcx Expr<'_>, + op: BinOpKind, + left: &'tcx Expr<'_>, + right: &'tcx Expr<'_>, + threshold: u64, +) { + if BinOpKind::Eq == op + && let ExprKind::Binary(op1, left1, right1) = &left.kind + && BinOpKind::BitAnd == op1.node + && let ExprKind::Lit(lit) = &right1.kind + && let LitKind::Int(n, _) = lit.node + && let ExprKind::Lit(lit1) = &right.kind + && let LitKind::Int(0, _) = lit1.node + && n.leading_zeros() == n.count_zeros() + && n > u128::from(threshold) + { + span_lint_and_then( + cx, + VERBOSE_BIT_MASK, + e.span, + "bit mask could be simplified with a call to `trailing_zeros`", + |diag| { + let sugg = Sugg::hir(cx, left1, "...").maybe_par(); + diag.span_suggestion( + e.span, + "try", + format!("{}.trailing_zeros() >= {}", sugg, n.count_ones()), + Applicability::MaybeIncorrect, + ); + }, + ); + } +} diff --git a/src/tools/clippy/clippy_lints/src/pass_by_ref_or_value.rs b/src/tools/clippy/clippy_lints/src/pass_by_ref_or_value.rs index 05ab62786f4..5fa4fd74853 100644 --- a/src/tools/clippy/clippy_lints/src/pass_by_ref_or_value.rs +++ b/src/tools/clippy/clippy_lints/src/pass_by_ref_or_value.rs @@ -3,17 +3,20 @@ use std::iter; use clippy_utils::diagnostics::span_lint_and_sugg; use clippy_utils::source::snippet; -use clippy_utils::ty::is_copy; +use clippy_utils::ty::{for_each_top_level_late_bound_region, is_copy}; use clippy_utils::{is_self, is_self_ty}; +use core::ops::ControlFlow; use if_chain::if_chain; use rustc_ast::attr; +use rustc_data_structures::fx::FxHashSet; use rustc_errors::Applicability; use rustc_hir as hir; use rustc_hir::intravisit::FnKind; use rustc_hir::{BindingAnnotation, Body, FnDecl, HirId, Impl, ItemKind, MutTy, Mutability, Node, PatKind}; use rustc_lint::{LateContext, LateLintPass}; -use rustc_middle::ty; +use rustc_middle::ty::adjustment::{Adjust, PointerCast}; use rustc_middle::ty::layout::LayoutOf; +use rustc_middle::ty::{self, RegionKind}; use rustc_session::{declare_tool_lint, impl_lint_pass}; use rustc_span::def_id::LocalDefId; use rustc_span::{sym, Span}; @@ -141,50 +144,76 @@ impl<'tcx> PassByRefOrValue { } let fn_sig = cx.tcx.fn_sig(def_id); - let fn_sig = cx.tcx.erase_late_bound_regions(fn_sig); - let fn_body = cx.enclosing_body.map(|id| cx.tcx.hir().body(id)); - for (index, (input, &ty)) in iter::zip(decl.inputs, fn_sig.inputs()).enumerate() { + // Gather all the lifetimes found in the output type which may affect whether + // `TRIVIALLY_COPY_PASS_BY_REF` should be linted. + let mut output_regions = FxHashSet::default(); + for_each_top_level_late_bound_region(fn_sig.skip_binder().output(), |region| -> ControlFlow<!> { + output_regions.insert(region); + ControlFlow::Continue(()) + }); + + for (index, (input, ty)) in iter::zip( + decl.inputs, + fn_sig.skip_binder().inputs().iter().map(|&ty| fn_sig.rebind(ty)), + ) + .enumerate() + { // All spans generated from a proc-macro invocation are the same... match span { - Some(s) if s == input.span => return, + Some(s) if s == input.span => continue, _ => (), } - match ty.kind() { - ty::Ref(input_lt, ty, Mutability::Not) => { - // Use lifetimes to determine if we're returning a reference to the - // argument. In that case we can't switch to pass-by-value as the - // argument will not live long enough. - let output_lts = match *fn_sig.output().kind() { - ty::Ref(output_lt, _, _) => vec![output_lt], - ty::Adt(_, substs) => substs.regions().collect(), - _ => vec![], - }; + match *ty.skip_binder().kind() { + ty::Ref(lt, ty, Mutability::Not) => { + match lt.kind() { + RegionKind::ReLateBound(index, region) + if index.as_u32() == 0 && output_regions.contains(®ion) => + { + continue; + }, + // Early bound regions on functions are either from the containing item, are bounded by another + // lifetime, or are used as a bound for a type or lifetime. + RegionKind::ReEarlyBound(..) => continue, + _ => (), + } - if_chain! { - if !output_lts.contains(input_lt); - if is_copy(cx, *ty); - if let Some(size) = cx.layout_of(*ty).ok().map(|l| l.size.bytes()); - if size <= self.ref_min_size; - if let hir::TyKind::Rptr(_, MutTy { ty: decl_ty, .. }) = input.kind; - then { - let value_type = if fn_body.and_then(|body| body.params.get(index)).map_or(false, is_self) { - "self".into() - } else { - snippet(cx, decl_ty.span, "_").into() - }; - span_lint_and_sugg( - cx, - TRIVIALLY_COPY_PASS_BY_REF, - input.span, - &format!("this argument ({} byte) is passed by reference, but would be more efficient if passed by value (limit: {} byte)", size, self.ref_min_size), - "consider passing by value instead", - value_type, - Applicability::Unspecified, - ); + let ty = cx.tcx.erase_late_bound_regions(fn_sig.rebind(ty)); + if is_copy(cx, ty) + && let Some(size) = cx.layout_of(ty).ok().map(|l| l.size.bytes()) + && size <= self.ref_min_size + && let hir::TyKind::Rptr(_, MutTy { ty: decl_ty, .. }) = input.kind + { + if let Some(typeck) = cx.maybe_typeck_results() { + // Don't lint if an unsafe pointer is created. + // TODO: Limit the check only to unsafe pointers to the argument (or part of the argument) + // which escape the current function. + if typeck.node_types().iter().any(|(_, &ty)| ty.is_unsafe_ptr()) + || typeck + .adjustments() + .iter() + .flat_map(|(_, a)| a) + .any(|a| matches!(a.kind, Adjust::Pointer(PointerCast::UnsafeFnPointer))) + { + continue; + } } + let value_type = if fn_body.and_then(|body| body.params.get(index)).map_or(false, is_self) { + "self".into() + } else { + snippet(cx, decl_ty.span, "_").into() + }; + span_lint_and_sugg( + cx, + TRIVIALLY_COPY_PASS_BY_REF, + input.span, + &format!("this argument ({} byte) is passed by reference, but would be more efficient if passed by value (limit: {} byte)", size, self.ref_min_size), + "consider passing by value instead", + value_type, + Applicability::Unspecified, + ); } }, @@ -196,6 +225,7 @@ impl<'tcx> PassByRefOrValue { _ => continue, } } + let ty = cx.tcx.erase_late_bound_regions(ty); if_chain! { if is_copy(cx, ty); diff --git a/src/tools/clippy/clippy_lints/src/ptr.rs b/src/tools/clippy/clippy_lints/src/ptr.rs index b06eba13d2f..25b73918c0a 100644 --- a/src/tools/clippy/clippy_lints/src/ptr.rs +++ b/src/tools/clippy/clippy_lints/src/ptr.rs @@ -1,6 +1,6 @@ //! Checks for usage of `&Vec[_]` and `&String`. -use clippy_utils::diagnostics::{span_lint, span_lint_and_sugg, span_lint_and_then}; +use clippy_utils::diagnostics::{span_lint, span_lint_and_sugg, span_lint_and_then, span_lint_hir_and_then}; use clippy_utils::source::snippet_opt; use clippy_utils::ty::expr_sig; use clippy_utils::visitors::contains_unsafe_block; @@ -166,15 +166,14 @@ impl<'tcx> LateLintPass<'tcx> for Ptr { ) .filter(|arg| arg.mutability() == Mutability::Not) { - span_lint_and_sugg( - cx, - PTR_ARG, - arg.span, - &arg.build_msg(), - "change this to", - format!("{}{}", arg.ref_prefix, arg.deref_ty.display(cx)), - Applicability::Unspecified, - ); + span_lint_hir_and_then(cx, PTR_ARG, arg.emission_id, arg.span, &arg.build_msg(), |diag| { + diag.span_suggestion( + arg.span, + "change this to", + format!("{}{}", arg.ref_prefix, arg.deref_ty.display(cx)), + Applicability::Unspecified, + ); + }); } } } @@ -221,7 +220,7 @@ impl<'tcx> LateLintPass<'tcx> for Ptr { let results = check_ptr_arg_usage(cx, body, &lint_args); for (result, args) in results.iter().zip(lint_args.iter()).filter(|(r, _)| !r.skip) { - span_lint_and_then(cx, PTR_ARG, args.span, &args.build_msg(), |diag| { + span_lint_hir_and_then(cx, PTR_ARG, args.emission_id, args.span, &args.build_msg(), |diag| { diag.multipart_suggestion( "change this to", iter::once((args.span, format!("{}{}", args.ref_prefix, args.deref_ty.display(cx)))) @@ -315,6 +314,7 @@ struct PtrArgReplacement { struct PtrArg<'tcx> { idx: usize, + emission_id: hir::HirId, span: Span, ty_did: DefId, ty_name: Symbol, @@ -419,10 +419,8 @@ fn check_fn_args<'cx, 'tcx: 'cx>( if let [.., name] = path.segments; if cx.tcx.item_name(adt.did()) == name.ident.name; - if !is_lint_allowed(cx, PTR_ARG, hir_ty.hir_id); - if params.get(i).map_or(true, |p| !is_lint_allowed(cx, PTR_ARG, p.hir_id)); - then { + let emission_id = params.get(i).map_or(hir_ty.hir_id, |param| param.hir_id); let (method_renames, deref_ty) = match cx.tcx.get_diagnostic_name(adt.did()) { Some(sym::Vec) => ( [("clone", ".to_owned()")].as_slice(), @@ -455,14 +453,20 @@ fn check_fn_args<'cx, 'tcx: 'cx>( }) .and_then(|arg| snippet_opt(cx, arg.span)) .unwrap_or_else(|| substs.type_at(1).to_string()); - span_lint_and_sugg( + span_lint_hir_and_then( cx, PTR_ARG, + emission_id, hir_ty.span, "using a reference to `Cow` is not recommended", - "change this to", - format!("&{}{}", mutability.prefix_str(), ty_name), - Applicability::Unspecified, + |diag| { + diag.span_suggestion( + hir_ty.span, + "change this to", + format!("&{}{}", mutability.prefix_str(), ty_name), + Applicability::Unspecified, + ); + } ); return None; }, @@ -470,6 +474,7 @@ fn check_fn_args<'cx, 'tcx: 'cx>( }; return Some(PtrArg { idx: i, + emission_id, span: hir_ty.span, ty_did: adt.did(), ty_name: name.ident.name, @@ -574,14 +579,13 @@ fn check_ptr_arg_usage<'tcx>(cx: &LateContext<'tcx>, body: &'tcx Body<'_>, args: Some((Node::Expr(e), child_id)) => match e.kind { ExprKind::Call(f, expr_args) => { let i = expr_args.iter().position(|arg| arg.hir_id == child_id).unwrap_or(0); - if expr_sig(self.cx, f) - .map(|sig| sig.input(i).skip_binder().peel_refs()) - .map_or(true, |ty| match *ty.kind() { + if expr_sig(self.cx, f).and_then(|sig| sig.input(i)).map_or(true, |ty| { + match *ty.skip_binder().peel_refs().kind() { ty::Param(_) => true, ty::Adt(def, _) => def.did() == args.ty_did, _ => false, - }) - { + } + }) { // Passed to a function taking the non-dereferenced type. set_skip_flag(); } diff --git a/src/tools/clippy/clippy_lints/src/ptr_eq.rs b/src/tools/clippy/clippy_lints/src/ptr_eq.rs deleted file mode 100644 index 2bec93ac606..00000000000 --- a/src/tools/clippy/clippy_lints/src/ptr_eq.rs +++ /dev/null @@ -1,97 +0,0 @@ -use clippy_utils::diagnostics::span_lint_and_sugg; -use clippy_utils::source::snippet_opt; -use if_chain::if_chain; -use rustc_errors::Applicability; -use rustc_hir::{BinOpKind, Expr, ExprKind}; -use rustc_lint::{LateContext, LateLintPass}; -use rustc_session::{declare_lint_pass, declare_tool_lint}; - -declare_clippy_lint! { - /// ### What it does - /// Use `std::ptr::eq` when applicable - /// - /// ### Why is this bad? - /// `ptr::eq` can be used to compare `&T` references - /// (which coerce to `*const T` implicitly) by their address rather than - /// comparing the values they point to. - /// - /// ### Example - /// ```rust - /// let a = &[1, 2, 3]; - /// let b = &[1, 2, 3]; - /// - /// assert!(a as *const _ as usize == b as *const _ as usize); - /// ``` - /// Use instead: - /// ```rust - /// let a = &[1, 2, 3]; - /// let b = &[1, 2, 3]; - /// - /// assert!(std::ptr::eq(a, b)); - /// ``` - #[clippy::version = "1.49.0"] - pub PTR_EQ, - style, - "use `std::ptr::eq` when comparing raw pointers" -} - -declare_lint_pass!(PtrEq => [PTR_EQ]); - -static LINT_MSG: &str = "use `std::ptr::eq` when comparing raw pointers"; - -impl<'tcx> LateLintPass<'tcx> for PtrEq { - fn check_expr(&mut self, cx: &LateContext<'tcx>, expr: &'tcx Expr<'_>) { - if expr.span.from_expansion() { - return; - } - - if let ExprKind::Binary(ref op, left, right) = expr.kind { - if BinOpKind::Eq == op.node { - let (left, right) = match (expr_as_cast_to_usize(cx, left), expr_as_cast_to_usize(cx, right)) { - (Some(lhs), Some(rhs)) => (lhs, rhs), - _ => (left, right), - }; - - if_chain! { - if let Some(left_var) = expr_as_cast_to_raw_pointer(cx, left); - if let Some(right_var) = expr_as_cast_to_raw_pointer(cx, right); - if let Some(left_snip) = snippet_opt(cx, left_var.span); - if let Some(right_snip) = snippet_opt(cx, right_var.span); - then { - span_lint_and_sugg( - cx, - PTR_EQ, - expr.span, - LINT_MSG, - "try", - format!("std::ptr::eq({}, {})", left_snip, right_snip), - Applicability::MachineApplicable, - ); - } - } - } - } - } -} - -// If the given expression is a cast to a usize, return the lhs of the cast -// E.g., `foo as *const _ as usize` returns `foo as *const _`. -fn expr_as_cast_to_usize<'tcx>(cx: &LateContext<'tcx>, cast_expr: &'tcx Expr<'_>) -> Option<&'tcx Expr<'tcx>> { - if cx.typeck_results().expr_ty(cast_expr) == cx.tcx.types.usize { - if let ExprKind::Cast(expr, _) = cast_expr.kind { - return Some(expr); - } - } - None -} - -// If the given expression is a cast to a `*const` pointer, return the lhs of the cast -// E.g., `foo as *const _` returns `foo`. -fn expr_as_cast_to_raw_pointer<'tcx>(cx: &LateContext<'tcx>, cast_expr: &'tcx Expr<'_>) -> Option<&'tcx Expr<'tcx>> { - if cx.typeck_results().expr_ty(cast_expr).is_unsafe_ptr() { - if let ExprKind::Cast(expr, _) = cast_expr.kind { - return Some(expr); - } - } - None -} diff --git a/src/tools/clippy/clippy_lints/src/redundant_clone.rs b/src/tools/clippy/clippy_lints/src/redundant_clone.rs index 3b11cbc3760..6d0b9a0f03f 100644 --- a/src/tools/clippy/clippy_lints/src/redundant_clone.rs +++ b/src/tools/clippy/clippy_lints/src/redundant_clone.rs @@ -14,7 +14,7 @@ use rustc_middle::mir::{ visit::{MutatingUseContext, NonMutatingUseContext, PlaceContext, Visitor as _}, Mutability, }; -use rustc_middle::ty::{self, fold::TypeVisitor, Ty}; +use rustc_middle::ty::{self, visit::TypeVisitor, Ty}; use rustc_mir_dataflow::{Analysis, AnalysisDomain, CallReturnPlaces, GenKill, GenKillAnalysis, ResultsCursor}; use rustc_session::{declare_lint_pass, declare_tool_lint}; use rustc_span::source_map::{BytePos, Span}; diff --git a/src/tools/clippy/clippy_lints/src/redundant_static_lifetimes.rs b/src/tools/clippy/clippy_lints/src/redundant_static_lifetimes.rs index 0825f00f421..f8801f769e8 100644 --- a/src/tools/clippy/clippy_lints/src/redundant_static_lifetimes.rs +++ b/src/tools/clippy/clippy_lints/src/redundant_static_lifetimes.rs @@ -87,7 +87,7 @@ impl RedundantStaticLifetimes { _ => {}, } } - self.visit_type(&*borrow_type.ty, cx, reason); + self.visit_type(&borrow_type.ty, cx, reason); }, _ => {}, } diff --git a/src/tools/clippy/clippy_lints/src/returns.rs b/src/tools/clippy/clippy_lints/src/returns.rs index e525eba53e2..5ae04947b82 100644 --- a/src/tools/clippy/clippy_lints/src/returns.rs +++ b/src/tools/clippy/clippy_lints/src/returns.rs @@ -1,4 +1,4 @@ -use clippy_utils::diagnostics::{span_lint_and_sugg, span_lint_and_then}; +use clippy_utils::diagnostics::span_lint_hir_and_then; use clippy_utils::source::{snippet_opt, snippet_with_context}; use clippy_utils::{fn_def_id, path_to_local_id}; use if_chain::if_chain; @@ -94,9 +94,10 @@ impl<'tcx> LateLintPass<'tcx> for Return { if !in_external_macro(cx.sess(), retexpr.span); if !local.span.from_expansion(); then { - span_lint_and_then( + span_lint_hir_and_then( cx, LET_AND_RETURN, + retexpr.hir_id, retexpr.span, "returning the result of a `let` binding from a block", |err| { @@ -185,6 +186,7 @@ fn check_final_expr<'tcx>( if !borrows { emit_return_lint( cx, + inner.map_or(expr.hir_id, |inner| inner.hir_id), span.expect("`else return` is not possible"), inner.as_ref().map(|i| i.span), replacement, @@ -220,50 +222,81 @@ fn check_final_expr<'tcx>( } } -fn emit_return_lint(cx: &LateContext<'_>, ret_span: Span, inner_span: Option<Span>, replacement: RetReplacement) { +fn emit_return_lint( + cx: &LateContext<'_>, + emission_place: HirId, + ret_span: Span, + inner_span: Option<Span>, + replacement: RetReplacement, +) { if ret_span.from_expansion() { return; } match inner_span { Some(inner_span) => { let mut applicability = Applicability::MachineApplicable; - span_lint_and_then(cx, NEEDLESS_RETURN, ret_span, "unneeded `return` statement", |diag| { - let (snippet, _) = snippet_with_context(cx, inner_span, ret_span.ctxt(), "..", &mut applicability); - diag.span_suggestion(ret_span, "remove `return`", snippet, applicability); - }); + span_lint_hir_and_then( + cx, + NEEDLESS_RETURN, + emission_place, + ret_span, + "unneeded `return` statement", + |diag| { + let (snippet, _) = snippet_with_context(cx, inner_span, ret_span.ctxt(), "..", &mut applicability); + diag.span_suggestion(ret_span, "remove `return`", snippet, applicability); + }, + ); }, None => match replacement { RetReplacement::Empty => { - span_lint_and_sugg( + span_lint_hir_and_then( cx, NEEDLESS_RETURN, + emission_place, ret_span, "unneeded `return` statement", - "remove `return`", - String::new(), - Applicability::MachineApplicable, + |diag| { + diag.span_suggestion( + ret_span, + "remove `return`", + String::new(), + Applicability::MachineApplicable, + ); + }, ); }, RetReplacement::Block => { - span_lint_and_sugg( + span_lint_hir_and_then( cx, NEEDLESS_RETURN, + emission_place, ret_span, "unneeded `return` statement", - "replace `return` with an empty block", - "{}".to_string(), - Applicability::MachineApplicable, + |diag| { + diag.span_suggestion( + ret_span, + "replace `return` with an empty block", + "{}".to_string(), + Applicability::MachineApplicable, + ); + }, ); }, RetReplacement::Unit => { - span_lint_and_sugg( + span_lint_hir_and_then( cx, NEEDLESS_RETURN, + emission_place, ret_span, "unneeded `return` statement", - "replace `return` with a unit value", - "()".to_string(), - Applicability::MachineApplicable, + |diag| { + diag.span_suggestion( + ret_span, + "replace `return` with a unit value", + "()".to_string(), + Applicability::MachineApplicable, + ); + }, ); }, }, diff --git a/src/tools/clippy/clippy_lints/src/self_assignment.rs b/src/tools/clippy/clippy_lints/src/self_assignment.rs deleted file mode 100644 index b14f0518bdb..00000000000 --- a/src/tools/clippy/clippy_lints/src/self_assignment.rs +++ /dev/null @@ -1,56 +0,0 @@ -use clippy_utils::diagnostics::span_lint; -use clippy_utils::eq_expr_value; -use clippy_utils::source::snippet; -use rustc_hir::{Expr, ExprKind}; -use rustc_lint::{LateContext, LateLintPass}; -use rustc_session::{declare_lint_pass, declare_tool_lint}; - -declare_clippy_lint! { - /// ### What it does - /// Checks for explicit self-assignments. - /// - /// ### Why is this bad? - /// Self-assignments are redundant and unlikely to be - /// intentional. - /// - /// ### Known problems - /// If expression contains any deref coercions or - /// indexing operations they are assumed not to have any side effects. - /// - /// ### Example - /// ```rust - /// struct Event { - /// id: usize, - /// x: i32, - /// y: i32, - /// } - /// - /// fn copy_position(a: &mut Event, b: &Event) { - /// a.x = b.x; - /// a.y = a.y; - /// } - /// ``` - #[clippy::version = "1.48.0"] - pub SELF_ASSIGNMENT, - correctness, - "explicit self-assignment" -} - -declare_lint_pass!(SelfAssignment => [SELF_ASSIGNMENT]); - -impl<'tcx> LateLintPass<'tcx> for SelfAssignment { - fn check_expr(&mut self, cx: &LateContext<'tcx>, expr: &'tcx Expr<'_>) { - if let ExprKind::Assign(lhs, rhs, _) = &expr.kind { - if eq_expr_value(cx, lhs, rhs) { - let lhs = snippet(cx, lhs.span, "<lhs>"); - let rhs = snippet(cx, rhs.span, "<rhs>"); - span_lint( - cx, - SELF_ASSIGNMENT, - expr.span, - &format!("self-assignment of `{}` to `{}`", rhs, lhs), - ); - } - } - } -} diff --git a/src/tools/clippy/clippy_lints/src/slow_vector_initialization.rs b/src/tools/clippy/clippy_lints/src/slow_vector_initialization.rs index 975a0a06e38..2c8aa17e80d 100644 --- a/src/tools/clippy/clippy_lints/src/slow_vector_initialization.rs +++ b/src/tools/clippy/clippy_lints/src/slow_vector_initialization.rs @@ -26,6 +26,9 @@ declare_clippy_lint! { /// let mut vec1 = Vec::with_capacity(len); /// vec1.resize(len, 0); /// + /// let mut vec1 = Vec::with_capacity(len); + /// vec1.resize(vec1.capacity(), 0); + /// /// let mut vec2 = Vec::with_capacity(len); /// vec2.extend(repeat(0).take(len)); /// ``` @@ -211,23 +214,20 @@ impl<'a, 'tcx> VectorInitializationVisitor<'a, 'tcx> { /// Checks if the given expression is resizing a vector with 0 fn search_slow_resize_filling(&mut self, expr: &'tcx Expr<'_>) { - if_chain! { - if self.initialization_found; - if let ExprKind::MethodCall(path, [self_arg, len_arg, fill_arg], _) = expr.kind; - if path_to_local_id(self_arg, self.vec_alloc.local_id); - if path.ident.name == sym!(resize); - + if self.initialization_found + && let ExprKind::MethodCall(path, [self_arg, len_arg, fill_arg], _) = expr.kind + && path_to_local_id(self_arg, self.vec_alloc.local_id) + && path.ident.name == sym!(resize) // Check that is filled with 0 - if let ExprKind::Lit(ref lit) = fill_arg.kind; - if let LitKind::Int(0, _) = lit.node; - - // Check that len expression is equals to `with_capacity` expression - if SpanlessEq::new(self.cx).eq_expr(len_arg, self.vec_alloc.len_expr); - - then { - self.slow_expression = Some(InitializationType::Resize(expr)); + && let ExprKind::Lit(ref lit) = fill_arg.kind + && let LitKind::Int(0, _) = lit.node { + // Check that len expression is equals to `with_capacity` expression + if SpanlessEq::new(self.cx).eq_expr(len_arg, self.vec_alloc.len_expr) { + self.slow_expression = Some(InitializationType::Resize(expr)); + } else if let ExprKind::MethodCall(path, _, _) = len_arg.kind && path.ident.as_str() == "capacity" { + self.slow_expression = Some(InitializationType::Resize(expr)); + } } - } } /// Returns `true` if give expression is `repeat(0).take(...)` @@ -240,12 +240,15 @@ impl<'a, 'tcx> VectorInitializationVisitor<'a, 'tcx> { if let Some(repeat_expr) = take_args.get(0); if self.is_repeat_zero(repeat_expr); - // Check that len expression is equals to `with_capacity` expression if let Some(len_arg) = take_args.get(1); - if SpanlessEq::new(self.cx).eq_expr(len_arg, self.vec_alloc.len_expr); then { - return true; + // Check that len expression is equals to `with_capacity` expression + if SpanlessEq::new(self.cx).eq_expr(len_arg, self.vec_alloc.len_expr) { + return true; + } else if let ExprKind::MethodCall(path, _, _) = len_arg.kind && path.ident.as_str() == "capacity" { + return true; + } } } diff --git a/src/tools/clippy/clippy_lints/src/strings.rs b/src/tools/clippy/clippy_lints/src/strings.rs index 71f3e6b6a6e..eb704a07451 100644 --- a/src/tools/clippy/clippy_lints/src/strings.rs +++ b/src/tools/clippy/clippy_lints/src/strings.rs @@ -60,6 +60,12 @@ declare_clippy_lint! { /// let x = "Hello".to_owned(); /// x + ", World"; /// ``` + /// + /// Use instead: + /// ```rust + /// let mut x = "Hello".to_owned(); + /// x.push_str(", World"); + /// ``` #[clippy::version = "pre 1.29.0"] pub STRING_ADD, restriction, diff --git a/src/tools/clippy/clippy_lints/src/transmute/mod.rs b/src/tools/clippy/clippy_lints/src/transmute/mod.rs index cbe1406728b..5f3e98144f4 100644 --- a/src/tools/clippy/clippy_lints/src/transmute/mod.rs +++ b/src/tools/clippy/clippy_lints/src/transmute/mod.rs @@ -16,9 +16,10 @@ mod wrong_transmute; use clippy_utils::in_constant; use if_chain::if_chain; -use rustc_hir::{Expr, ExprKind}; +use rustc_hir::{Expr, ExprKind, QPath}; use rustc_lint::{LateContext, LateLintPass}; -use rustc_session::{declare_lint_pass, declare_tool_lint}; +use rustc_semver::RustcVersion; +use rustc_session::{declare_tool_lint, impl_lint_pass}; use rustc_span::symbol::sym; declare_clippy_lint! { @@ -385,7 +386,10 @@ declare_clippy_lint! { "transmute to or from a type with an undefined representation" } -declare_lint_pass!(Transmute => [ +pub struct Transmute { + msrv: Option<RustcVersion>, +} +impl_lint_pass!(Transmute => [ CROSSPOINTER_TRANSMUTE, TRANSMUTE_PTR_TO_REF, TRANSMUTE_PTR_TO_PTR, @@ -401,13 +405,18 @@ declare_lint_pass!(Transmute => [ TRANSMUTES_EXPRESSIBLE_AS_PTR_CASTS, TRANSMUTE_UNDEFINED_REPR, ]); - +impl Transmute { + #[must_use] + pub fn new(msrv: Option<RustcVersion>) -> Self { + Self { msrv } + } +} impl<'tcx> LateLintPass<'tcx> for Transmute { fn check_expr(&mut self, cx: &LateContext<'tcx>, e: &'tcx Expr<'_>) { if_chain! { if let ExprKind::Call(path_expr, [arg]) = e.kind; - if let ExprKind::Path(ref qpath) = path_expr.kind; - if let Some(def_id) = cx.qpath_res(qpath, path_expr.hir_id).opt_def_id(); + if let ExprKind::Path(QPath::Resolved(None, path)) = path_expr.kind; + if let Some(def_id) = path.res.opt_def_id(); if cx.tcx.is_diagnostic_item(sym::transmute, def_id); then { // Avoid suggesting non-const operations in const contexts: @@ -427,7 +436,7 @@ impl<'tcx> LateLintPass<'tcx> for Transmute { let linted = wrong_transmute::check(cx, e, from_ty, to_ty) | crosspointer_transmute::check(cx, e, from_ty, to_ty) - | transmute_ptr_to_ref::check(cx, e, from_ty, to_ty, arg, qpath) + | transmute_ptr_to_ref::check(cx, e, from_ty, to_ty, arg, path, self.msrv) | transmute_int_to_char::check(cx, e, from_ty, to_ty, arg, const_context) | transmute_ref_to_ref::check(cx, e, from_ty, to_ty, arg, const_context) | transmute_ptr_to_ptr::check(cx, e, from_ty, to_ty, arg) @@ -446,4 +455,6 @@ impl<'tcx> LateLintPass<'tcx> for Transmute { } } } + + extract_msrv_attr!(LateContext); } diff --git a/src/tools/clippy/clippy_lints/src/transmute/transmute_ptr_to_ref.rs b/src/tools/clippy/clippy_lints/src/transmute/transmute_ptr_to_ref.rs index f3653199b37..5eb03275b8e 100644 --- a/src/tools/clippy/clippy_lints/src/transmute/transmute_ptr_to_ref.rs +++ b/src/tools/clippy/clippy_lints/src/transmute/transmute_ptr_to_ref.rs @@ -1,11 +1,12 @@ -use super::utils::get_type_snippet; use super::TRANSMUTE_PTR_TO_REF; use clippy_utils::diagnostics::span_lint_and_then; -use clippy_utils::sugg; +use clippy_utils::source::snippet_with_applicability; +use clippy_utils::{meets_msrv, msrvs, sugg}; use rustc_errors::Applicability; -use rustc_hir::{Expr, Mutability, QPath}; +use rustc_hir::{self as hir, Expr, GenericArg, Mutability, Path, TyKind}; use rustc_lint::LateContext; -use rustc_middle::ty::{self, Ty}; +use rustc_middle::ty::{self, Ty, TypeVisitable}; +use rustc_semver::RustcVersion; /// Checks for `transmute_ptr_to_ref` lint. /// Returns `true` if it's triggered, otherwise returns `false`. @@ -15,7 +16,8 @@ pub(super) fn check<'tcx>( from_ty: Ty<'tcx>, to_ty: Ty<'tcx>, arg: &'tcx Expr<'_>, - qpath: &'tcx QPath<'_>, + path: &'tcx Path<'_>, + msrv: Option<RustcVersion>, ) -> bool { match (&from_ty.kind(), &to_ty.kind()) { (ty::RawPtr(from_ptr_ty), ty::Ref(_, to_ref_ty, mutbl)) => { @@ -34,19 +36,34 @@ pub(super) fn check<'tcx>( } else { ("&*", "*const") }; + let mut app = Applicability::MachineApplicable; - let arg = if from_ptr_ty.ty == *to_ref_ty { - arg + let sugg = if let Some(ty) = get_explicit_type(path) { + let ty_snip = snippet_with_applicability(cx, ty.span, "..", &mut app); + if meets_msrv(msrv, msrvs::POINTER_CAST) { + format!("{}{}.cast::<{}>()", deref, arg.maybe_par(), ty_snip) + } else if from_ptr_ty.has_erased_regions() { + sugg::make_unop(deref, arg.as_ty(format!("{} () as {} {}", cast, cast, ty_snip))) + .to_string() + } else { + sugg::make_unop(deref, arg.as_ty(format!("{} {}", cast, ty_snip))).to_string() + } + } else if from_ptr_ty.ty == *to_ref_ty { + if from_ptr_ty.has_erased_regions() { + if meets_msrv(msrv, msrvs::POINTER_CAST) { + format!("{}{}.cast::<{}>()", deref, arg.maybe_par(), to_ref_ty) + } else { + sugg::make_unop(deref, arg.as_ty(format!("{} () as {} {}", cast, cast, to_ref_ty))) + .to_string() + } + } else { + sugg::make_unop(deref, arg).to_string() + } } else { - arg.as_ty(&format!("{} {}", cast, get_type_snippet(cx, qpath, *to_ref_ty))) + sugg::make_unop(deref, arg.as_ty(format!("{} {}", cast, to_ref_ty))).to_string() }; - diag.span_suggestion( - e.span, - "try", - sugg::make_unop(deref, arg).to_string(), - Applicability::Unspecified, - ); + diag.span_suggestion(e.span, "try", sugg, app); }, ); true @@ -54,3 +71,14 @@ pub(super) fn check<'tcx>( _ => false, } } + +/// Gets the type `Bar` in `…::transmute<Foo, &Bar>`. +fn get_explicit_type<'tcx>(path: &'tcx Path<'tcx>) -> Option<&'tcx hir::Ty<'tcx>> { + if let GenericArg::Type(ty) = path.segments.last()?.args?.args.get(1)? + && let TyKind::Rptr(_, ty) = &ty.kind + { + Some(ty.ty) + } else { + None + } +} diff --git a/src/tools/clippy/clippy_lints/src/transmute/useless_transmute.rs b/src/tools/clippy/clippy_lints/src/transmute/useless_transmute.rs index 8ea985a8984..8122cd716e0 100644 --- a/src/tools/clippy/clippy_lints/src/transmute/useless_transmute.rs +++ b/src/tools/clippy/clippy_lints/src/transmute/useless_transmute.rs @@ -4,7 +4,7 @@ use clippy_utils::sugg; use rustc_errors::Applicability; use rustc_hir::Expr; use rustc_lint::LateContext; -use rustc_middle::ty::{self, Ty, TypeFoldable}; +use rustc_middle::ty::{self, Ty, TypeVisitable}; /// Checks for `useless_transmute` lint. /// Returns `true` if it's triggered, otherwise returns `false`. diff --git a/src/tools/clippy/clippy_lints/src/transmute/utils.rs b/src/tools/clippy/clippy_lints/src/transmute/utils.rs index 0cbf5ccefa6..74927570b40 100644 --- a/src/tools/clippy/clippy_lints/src/transmute/utils.rs +++ b/src/tools/clippy/clippy_lints/src/transmute/utils.rs @@ -1,35 +1,9 @@ -use clippy_utils::last_path_segment; -use clippy_utils::source::snippet; -use if_chain::if_chain; -use rustc_hir::{Expr, GenericArg, QPath, TyKind}; +use rustc_hir::Expr; use rustc_lint::LateContext; use rustc_middle::ty::{cast::CastKind, Ty}; use rustc_span::DUMMY_SP; use rustc_typeck::check::{cast::CastCheck, FnCtxt, Inherited}; -/// Gets the snippet of `Bar` in `…::transmute<Foo, &Bar>`. If that snippet is -/// not available , use -/// the type's `ToString` implementation. In weird cases it could lead to types -/// with invalid `'_` -/// lifetime, but it should be rare. -pub(super) fn get_type_snippet(cx: &LateContext<'_>, path: &QPath<'_>, to_ref_ty: Ty<'_>) -> String { - let seg = last_path_segment(path); - if_chain! { - if let Some(params) = seg.args; - if !params.parenthesized; - if let Some(to_ty) = params.args.iter().filter_map(|arg| match arg { - GenericArg::Type(ty) => Some(ty), - _ => None, - }).nth(1); - if let TyKind::Rptr(_, ref to_ty) = to_ty.kind; - then { - return snippet(cx, to_ty.ty.span, &to_ref_ty.to_string()).to_string(); - } - } - - to_ref_ty.to_string() -} - // check if the component types of the transmuted collection and the result have different ABI, // size or alignment pub(super) fn is_layout_incompatible<'tcx>(cx: &LateContext<'tcx>, from: Ty<'tcx>, to: Ty<'tcx>) -> bool { diff --git a/src/tools/clippy/clippy_lints/src/types/vec_box.rs b/src/tools/clippy/clippy_lints/src/types/vec_box.rs index c632f822544..b2f536ca781 100644 --- a/src/tools/clippy/clippy_lints/src/types/vec_box.rs +++ b/src/tools/clippy/clippy_lints/src/types/vec_box.rs @@ -6,7 +6,7 @@ use rustc_errors::Applicability; use rustc_hir::{self as hir, def_id::DefId, GenericArg, QPath, TyKind}; use rustc_lint::LateContext; use rustc_middle::ty::layout::LayoutOf; -use rustc_middle::ty::TypeFoldable; +use rustc_middle::ty::TypeVisitable; use rustc_span::symbol::sym; use rustc_typeck::hir_ty_to_ty; diff --git a/src/tools/clippy/clippy_lints/src/unit_types/let_unit_value.rs b/src/tools/clippy/clippy_lints/src/unit_types/let_unit_value.rs index 27678c8ba3c..cf509455aad 100644 --- a/src/tools/clippy/clippy_lints/src/unit_types/let_unit_value.rs +++ b/src/tools/clippy/clippy_lints/src/unit_types/let_unit_value.rs @@ -7,7 +7,7 @@ use rustc_hir::def::{DefKind, Res}; use rustc_hir::{Expr, ExprKind, PatKind, Stmt, StmtKind}; use rustc_lint::{LateContext, LintContext}; use rustc_middle::lint::in_external_macro; -use rustc_middle::ty::{self, Ty, TypeFoldable, TypeSuperFoldable, TypeVisitor}; +use rustc_middle::ty::{self, Ty, TypeVisitable, TypeSuperVisitable, TypeVisitor}; use super::LET_UNIT_VALUE; diff --git a/src/tools/clippy/clippy_lints/src/unused_async.rs b/src/tools/clippy/clippy_lints/src/unused_async.rs index c8ec4442ab1..a832dfcccaf 100644 --- a/src/tools/clippy/clippy_lints/src/unused_async.rs +++ b/src/tools/clippy/clippy_lints/src/unused_async.rs @@ -1,6 +1,6 @@ use clippy_utils::diagnostics::span_lint_and_help; use rustc_hir::intravisit::{walk_expr, walk_fn, FnKind, Visitor}; -use rustc_hir::{Body, Expr, ExprKind, FnDecl, FnHeader, HirId, IsAsync, YieldSource}; +use rustc_hir::{Body, Expr, ExprKind, FnDecl, HirId, IsAsync, YieldSource}; use rustc_lint::{LateContext, LateLintPass}; use rustc_middle::hir::nested_filter; use rustc_session::{declare_lint_pass, declare_tool_lint}; @@ -68,20 +68,18 @@ impl<'tcx> LateLintPass<'tcx> for UnusedAsync { span: Span, hir_id: HirId, ) { - if let FnKind::ItemFn(_, _, FnHeader { asyncness, .. }) = &fn_kind { - if matches!(asyncness, IsAsync::Async) { - let mut visitor = AsyncFnVisitor { cx, found_await: false }; - walk_fn(&mut visitor, fn_kind, fn_decl, body.id(), span, hir_id); - if !visitor.found_await { - span_lint_and_help( - cx, - UNUSED_ASYNC, - span, - "unused `async` for function with no await statements", - None, - "consider removing the `async` from this function", - ); - } + if !span.from_expansion() && fn_kind.asyncness() == IsAsync::Async { + let mut visitor = AsyncFnVisitor { cx, found_await: false }; + walk_fn(&mut visitor, fn_kind, fn_decl, body.id(), span, hir_id); + if !visitor.found_await { + span_lint_and_help( + cx, + UNUSED_ASYNC, + span, + "unused `async` for function with no await statements", + None, + "consider removing the `async` from this function", + ); } } } diff --git a/src/tools/clippy/clippy_lints/src/unwrap.rs b/src/tools/clippy/clippy_lints/src/unwrap.rs index 9b9e25326f9..d3f9e5abfd7 100644 --- a/src/tools/clippy/clippy_lints/src/unwrap.rs +++ b/src/tools/clippy/clippy_lints/src/unwrap.rs @@ -1,4 +1,4 @@ -use clippy_utils::diagnostics::span_lint_and_then; +use clippy_utils::diagnostics::span_lint_hir_and_then; use clippy_utils::higher; use clippy_utils::ty::is_type_diagnostic_item; use clippy_utils::{path_to_local, usage::is_potentially_mutated}; @@ -251,9 +251,10 @@ impl<'a, 'tcx> Visitor<'tcx> for UnwrappableVariablesVisitor<'a, 'tcx> { unwrappable.kind.error_variant_pattern() }; - span_lint_and_then( + span_lint_hir_and_then( self.cx, UNNECESSARY_UNWRAP, + expr.hir_id, expr.span, &format!( "called `{}` on `{}` after checking its variant with `{}`", @@ -283,9 +284,10 @@ impl<'a, 'tcx> Visitor<'tcx> for UnwrappableVariablesVisitor<'a, 'tcx> { }, ); } else { - span_lint_and_then( + span_lint_hir_and_then( self.cx, PANICKING_UNWRAP, + expr.hir_id, expr.span, &format!("this call to `{}()` will always panic", method_name.ident.name), diff --git a/src/tools/clippy/clippy_lints/src/utils/internal_lints.rs b/src/tools/clippy/clippy_lints/src/utils/internal_lints.rs index b885e5132f1..a94f0357977 100644 --- a/src/tools/clippy/clippy_lints/src/utils/internal_lints.rs +++ b/src/tools/clippy/clippy_lints/src/utils/internal_lints.rs @@ -1,3 +1,4 @@ +use crate::utils::internal_lints::metadata_collector::is_deprecated_lint; use clippy_utils::consts::{constant_simple, Constant}; use clippy_utils::diagnostics::{span_lint, span_lint_and_help, span_lint_and_sugg, span_lint_and_then}; use clippy_utils::macros::root_macro_call_first_node; @@ -338,6 +339,46 @@ declare_clippy_lint! { "checking if all necessary steps were taken when adding a MSRV to a lint" } +declare_clippy_lint! { + /// ### What it does + /// Checks for cases of an auto-generated deprecated lint without an updated reason, + /// i.e. `"default deprecation note"`. + /// + /// ### Why is this bad? + /// Indicates that the documentation is incomplete. + /// + /// ### Example + /// ```rust,ignore + /// declare_deprecated_lint! { + /// /// ### What it does + /// /// Nothing. This lint has been deprecated. + /// /// + /// /// ### Deprecation reason + /// /// TODO + /// #[clippy::version = "1.63.0"] + /// pub COOL_LINT, + /// "default deprecation note" + /// } + /// ``` + /// + /// Use instead: + /// ```rust,ignore + /// declare_deprecated_lint! { + /// /// ### What it does + /// /// Nothing. This lint has been deprecated. + /// /// + /// /// ### Deprecation reason + /// /// This lint has been replaced by `cooler_lint` + /// #[clippy::version = "1.63.0"] + /// pub COOL_LINT, + /// "this lint has been replaced by `cooler_lint`" + /// } + /// ``` + pub DEFAULT_DEPRECATION_REASON, + internal, + "found 'default deprecation note' in a deprecated lint declaration" +} + declare_lint_pass!(ClippyLintsInternal => [CLIPPY_LINTS_INTERNAL]); impl EarlyLintPass for ClippyLintsInternal { @@ -375,42 +416,67 @@ pub struct LintWithoutLintPass { registered_lints: FxHashSet<Symbol>, } -impl_lint_pass!(LintWithoutLintPass => [DEFAULT_LINT, LINT_WITHOUT_LINT_PASS, INVALID_CLIPPY_VERSION_ATTRIBUTE, MISSING_CLIPPY_VERSION_ATTRIBUTE]); +impl_lint_pass!(LintWithoutLintPass => [DEFAULT_LINT, LINT_WITHOUT_LINT_PASS, INVALID_CLIPPY_VERSION_ATTRIBUTE, MISSING_CLIPPY_VERSION_ATTRIBUTE, DEFAULT_DEPRECATION_REASON]); impl<'tcx> LateLintPass<'tcx> for LintWithoutLintPass { fn check_item(&mut self, cx: &LateContext<'tcx>, item: &'tcx Item<'_>) { - if is_lint_allowed(cx, DEFAULT_LINT, item.hir_id()) { + if is_lint_allowed(cx, DEFAULT_LINT, item.hir_id()) + || is_lint_allowed(cx, DEFAULT_DEPRECATION_REASON, item.hir_id()) + { return; } if let hir::ItemKind::Static(ty, Mutability::Not, body_id) = item.kind { - if is_lint_ref_type(cx, ty) { + let is_lint_ref_ty = is_lint_ref_type(cx, ty); + if is_deprecated_lint(cx, ty) || is_lint_ref_ty { check_invalid_clippy_version_attribute(cx, item); let expr = &cx.tcx.hir().body(body_id).value; - if_chain! { - if let ExprKind::AddrOf(_, _, inner_exp) = expr.kind; - if let ExprKind::Struct(_, fields, _) = inner_exp.kind; - let field = fields - .iter() - .find(|f| f.ident.as_str() == "desc") - .expect("lints must have a description field"); - if let ExprKind::Lit(Spanned { - node: LitKind::Str(ref sym, _), - .. - }) = field.expr.kind; - if sym.as_str() == "default lint description"; - - then { + let fields; + if is_lint_ref_ty { + if let ExprKind::AddrOf(_, _, inner_exp) = expr.kind + && let ExprKind::Struct(_, struct_fields, _) = inner_exp.kind { + fields = struct_fields; + } else { + return; + } + } else if let ExprKind::Struct(_, struct_fields, _) = expr.kind { + fields = struct_fields; + } else { + return; + } + + let field = fields + .iter() + .find(|f| f.ident.as_str() == "desc") + .expect("lints must have a description field"); + + if let ExprKind::Lit(Spanned { + node: LitKind::Str(ref sym, _), + .. + }) = field.expr.kind + { + let sym_str = sym.as_str(); + if is_lint_ref_ty { + if sym_str == "default lint description" { + span_lint( + cx, + DEFAULT_LINT, + item.span, + &format!("the lint `{}` has the default lint description", item.ident.name), + ); + } + + self.declared_lints.insert(item.ident.name, item.span); + } else if sym_str == "default deprecation note" { span_lint( cx, - DEFAULT_LINT, + DEFAULT_DEPRECATION_REASON, item.span, - &format!("the lint `{}` has the default lint description", item.ident.name), + &format!("the lint `{}` has the default deprecation reason", item.ident.name), ); } } - self.declared_lints.insert(item.ident.name, item.span); } } else if let Some(macro_call) = root_macro_call_first_node(cx, item) { if !matches!( @@ -668,6 +734,7 @@ impl<'tcx> LateLintPass<'tcx> for CollapsibleCalls { let body = cx.tcx.hir().body(*body); let only_expr = peel_blocks_with_stmt(&body.value); if let ExprKind::MethodCall(ps, span_call_args, _) = &only_expr.kind; + if let ExprKind::Path(..) = span_call_args[0].kind; then { let and_then_snippets = get_and_then_snippets(cx, and_then_args); let mut sle = SpanlessEq::new(cx).deny_side_effects(); 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 2564099f4db..6518e0a6ea0 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 @@ -104,7 +104,7 @@ macro_rules! RENAME_VALUE_TEMPLATE { }; } -const LINT_EMISSION_FUNCTIONS: [&[&str]; 8] = [ +const LINT_EMISSION_FUNCTIONS: [&[&str]; 7] = [ &["clippy_utils", "diagnostics", "span_lint"], &["clippy_utils", "diagnostics", "span_lint_and_help"], &["clippy_utils", "diagnostics", "span_lint_and_note"], @@ -190,7 +190,12 @@ impl MetadataCollector { lints: BinaryHeap::<LintMetadata>::default(), applicability_info: FxHashMap::<String, ApplicabilityInfo>::default(), config: collect_configs(), - clippy_project_root: clippy_dev::clippy_project_root(), + clippy_project_root: std::env::current_dir() + .expect("failed to get current dir") + .ancestors() + .nth(1) + .expect("failed to get project root") + .to_path_buf(), } } @@ -841,7 +846,7 @@ fn get_lint_level_from_group(lint_group: &str) -> Option<&'static str> { .find_map(|(group_name, group_level)| (*group_name == lint_group).then(|| *group_level)) } -fn is_deprecated_lint(cx: &LateContext<'_>, ty: &hir::Ty<'_>) -> bool { +pub(super) fn is_deprecated_lint(cx: &LateContext<'_>, ty: &hir::Ty<'_>) -> bool { if let hir::TyKind::Path(ref path) = ty.kind { if let hir::def::Res::Def(DefKind::Struct, def_id) = cx.qpath_res(path, ty.hir_id) { return match_def_path(cx, def_id, &DEPRECATED_LINT_TYPE); diff --git a/src/tools/clippy/clippy_lints/src/vec_resize_to_zero.rs b/src/tools/clippy/clippy_lints/src/vec_resize_to_zero.rs index 4d86abd0fa1..0fee3e812d2 100644 --- a/src/tools/clippy/clippy_lints/src/vec_resize_to_zero.rs +++ b/src/tools/clippy/clippy_lints/src/vec_resize_to_zero.rs @@ -20,6 +20,11 @@ declare_clippy_lint! { /// ```rust /// vec!(1, 2, 3, 4, 5).resize(0, 5) /// ``` + /// + /// Use instead: + /// ```rust + /// vec!(1, 2, 3, 4, 5).clear() + /// ``` #[clippy::version = "1.46.0"] pub VEC_RESIZE_TO_ZERO, correctness, diff --git a/src/tools/clippy/clippy_lints/src/zero_sized_map_values.rs b/src/tools/clippy/clippy_lints/src/zero_sized_map_values.rs index 70b0560e676..8dc43c0e294 100644 --- a/src/tools/clippy/clippy_lints/src/zero_sized_map_values.rs +++ b/src/tools/clippy/clippy_lints/src/zero_sized_map_values.rs @@ -4,7 +4,7 @@ use if_chain::if_chain; use rustc_hir::{self as hir, HirId, ItemKind, Node}; use rustc_lint::{LateContext, LateLintPass}; use rustc_middle::ty::layout::LayoutOf as _; -use rustc_middle::ty::{Adt, Ty, TypeFoldable}; +use rustc_middle::ty::{Adt, Ty, TypeVisitable}; use rustc_session::{declare_lint_pass, declare_tool_lint}; use rustc_span::sym; use rustc_typeck::hir_ty_to_ty; diff --git a/src/tools/clippy/clippy_utils/Cargo.toml b/src/tools/clippy/clippy_utils/Cargo.toml index c4e0b8448ab..bb443bdc116 100644 --- a/src/tools/clippy/clippy_utils/Cargo.toml +++ b/src/tools/clippy/clippy_utils/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "clippy_utils" -version = "0.1.63" +version = "0.1.64" edition = "2021" publish = false diff --git a/src/tools/clippy/clippy_utils/src/hir_utils.rs b/src/tools/clippy/clippy_utils/src/hir_utils.rs index af62c4afd5a..793e3cc58c2 100644 --- a/src/tools/clippy/clippy_utils/src/hir_utils.rs +++ b/src/tools/clippy/clippy_utils/src/hir_utils.rs @@ -1,4 +1,5 @@ use crate::consts::constant_simple; +use crate::macros::macro_backtrace; use crate::source::snippet_opt; use rustc_ast::ast::InlineAsmTemplatePiece; use rustc_data_structures::fx::FxHasher; @@ -12,9 +13,13 @@ use rustc_hir::{ use rustc_lexer::{tokenize, TokenKind}; use rustc_lint::LateContext; use rustc_middle::ty::TypeckResults; -use rustc_span::Symbol; +use rustc_span::{sym, Symbol}; use std::hash::{Hash, Hasher}; +/// Callback that is called when two expressions are not equal in the sense of `SpanlessEq`, but +/// other conditions would make them equal. +type SpanlessEqCallback<'a> = dyn FnMut(&Expr<'_>, &Expr<'_>) -> bool + 'a; + /// Type used to check whether two ast are the same. This is different from the /// operator `==` on ast types as this operator would compare true equality with /// ID and span. @@ -25,7 +30,7 @@ pub struct SpanlessEq<'a, 'tcx> { cx: &'a LateContext<'tcx>, maybe_typeck_results: Option<(&'tcx TypeckResults<'tcx>, &'tcx TypeckResults<'tcx>)>, allow_side_effects: bool, - expr_fallback: Option<Box<dyn FnMut(&Expr<'_>, &Expr<'_>) -> bool + 'a>>, + expr_fallback: Option<Box<SpanlessEqCallback<'a>>>, } impl<'a, 'tcx> SpanlessEq<'a, 'tcx> { @@ -121,6 +126,9 @@ impl HirEqInterExpr<'_, '_, '_> { /// Checks whether two blocks are the same. fn eq_block(&mut self, left: &Block<'_>, right: &Block<'_>) -> bool { + if self.cannot_be_compared_block(left) || self.cannot_be_compared_block(right) { + return false; + } match (left.stmts, left.expr, right.stmts, right.expr) { ([], None, [], None) => { // For empty blocks, check to see if the tokens are equal. This will catch the case where a macro @@ -171,6 +179,38 @@ impl HirEqInterExpr<'_, '_, '_> { } } + fn cannot_be_compared_block(&mut self, block: &Block<'_>) -> bool { + if block.stmts.last().map_or(false, |stmt| { + matches!( + stmt.kind, + StmtKind::Semi(semi_expr) if self.should_ignore(semi_expr) + ) + }) { + return true; + } + + if let Some(block_expr) = block.expr + && self.should_ignore(block_expr) + { + return true + } + + false + } + + fn should_ignore(&mut self, expr: &Expr<'_>) -> bool { + if macro_backtrace(expr.span).last().map_or(false, |macro_call| { + matches!( + &self.inner.cx.tcx.get_diagnostic_name(macro_call.def_id), + Some(sym::todo_macro | sym::unimplemented_macro) + ) + }) { + return true; + } + + false + } + pub fn eq_array_length(&mut self, left: ArrayLen, right: ArrayLen) -> bool { match (left, right) { (ArrayLen::Infer(..), ArrayLen::Infer(..)) => true, diff --git a/src/tools/clippy/clippy_utils/src/lib.rs b/src/tools/clippy/clippy_utils/src/lib.rs index 5106c39b5c6..1b32f0aaeb8 100644 --- a/src/tools/clippy/clippy_utils/src/lib.rs +++ b/src/tools/clippy/clippy_utils/src/lib.rs @@ -93,7 +93,7 @@ use rustc_middle::ty::fast_reject::SimplifiedTypeGen::{ ArraySimplifiedType, BoolSimplifiedType, CharSimplifiedType, FloatSimplifiedType, IntSimplifiedType, PtrSimplifiedType, SliceSimplifiedType, StrSimplifiedType, UintSimplifiedType, }; -use rustc_middle::ty::{layout::IntegerExt, BorrowKind, DefIdTree, Ty, TyCtxt, TypeAndMut, TypeFoldable, UpvarCapture}; +use rustc_middle::ty::{layout::IntegerExt, BorrowKind, DefIdTree, Ty, TyCtxt, TypeAndMut, TypeVisitable, UpvarCapture}; use rustc_middle::ty::{FloatTy, IntTy, UintTy}; use rustc_semver::RustcVersion; use rustc_session::Session; @@ -183,7 +183,7 @@ pub fn expr_or_init<'a, 'b, 'tcx: 'b>(cx: &LateContext<'tcx>, mut expr: &'a Expr pub fn find_binding_init<'tcx>(cx: &LateContext<'tcx>, hir_id: HirId) -> Option<&'tcx Expr<'tcx>> { let hir = cx.tcx.hir(); if_chain! { - if let Some(Node::Binding(pat)) = hir.find(hir_id); + if let Some(Node::Pat(pat)) = hir.find(hir_id); if matches!(pat.kind, PatKind::Binding(BindingAnnotation::Unannotated, ..)); let parent = hir.get_parent_node(hir_id); if let Some(Node::Local(local)) = hir.find(parent); @@ -1539,9 +1539,13 @@ pub fn is_try<'tcx>(cx: &LateContext<'_>, expr: &'tcx Expr<'tcx>) -> Option<&'tc None } -/// Returns `true` if the lint is allowed in the current context +/// Returns `true` if the lint is allowed in the current context. This is useful for +/// skipping long running code when it's unnecessary /// -/// Useful for skipping long running code when it's unnecessary +/// This function should check the lint level for the same node, that the lint will +/// be emitted at. If the information is buffered to be emitted at a later point, please +/// make sure to use `span_lint_hir` functions to emit the lint. This ensures that +/// expectations at the checked nodes will be fulfilled. pub fn is_lint_allowed(cx: &LateContext<'_>, lint: &'static Lint, id: HirId) -> bool { cx.tcx.lint_level_at_node(lint, id).0 == Level::Allow } @@ -2058,6 +2062,21 @@ pub fn peel_hir_expr_refs<'a>(expr: &'a Expr<'a>) -> (&'a Expr<'a>, usize) { (e, count) } +/// Peels off all references on the type. Returns the underlying type and the number of references +/// removed. +pub fn peel_hir_ty_refs<'a>(mut ty: &'a hir::Ty<'a>) -> (&'a hir::Ty<'a>, usize) { + let mut count = 0; + loop { + match &ty.kind { + TyKind::Rptr(_, ref_ty) => { + ty = ref_ty.ty; + count += 1; + }, + _ => break (ty, count), + } + } +} + /// Removes `AddrOf` operators (`&`) or deref operators (`*`), but only if a reference type is /// dereferenced. An overloaded deref such as `Vec` to slice would not be removed. pub fn peel_ref_operators<'hir>(cx: &LateContext<'_>, mut expr: &'hir Expr<'hir>) -> &'hir Expr<'hir> { @@ -2110,7 +2129,7 @@ fn with_test_item_names<'tcx>(tcx: TyCtxt<'tcx>, module: LocalDefId, f: impl Fn( } } names.sort_unstable(); - f(&*entry.insert(names)) + f(entry.insert(names)) }, } } @@ -2168,6 +2187,50 @@ pub fn is_test_module_or_function(tcx: TyCtxt<'_>, item: &Item<'_>) -> bool { && item.ident.name.as_str().split('_').any(|a| a == "test" || a == "tests") } +/// Walks the HIR tree from the given expression, up to the node where the value produced by the +/// expression is consumed. Calls the function for every node encountered this way until it returns +/// `Some`. +/// +/// This allows walking through `if`, `match`, `break`, block expressions to find where the value +/// produced by the expression is consumed. +pub fn walk_to_expr_usage<'tcx, T>( + cx: &LateContext<'tcx>, + e: &Expr<'tcx>, + mut f: impl FnMut(Node<'tcx>, HirId) -> Option<T>, +) -> Option<T> { + let map = cx.tcx.hir(); + let mut iter = map.parent_iter(e.hir_id); + let mut child_id = e.hir_id; + + while let Some((parent_id, parent)) = iter.next() { + if let Some(x) = f(parent, child_id) { + return Some(x); + } + let parent = match parent { + Node::Expr(e) => e, + Node::Block(Block { expr: Some(body), .. }) | Node::Arm(Arm { body, .. }) if body.hir_id == child_id => { + child_id = parent_id; + continue; + }, + Node::Arm(a) if a.body.hir_id == child_id => { + child_id = parent_id; + continue; + }, + _ => return None, + }; + match parent.kind { + ExprKind::If(child, ..) | ExprKind::Match(child, ..) if child.hir_id != child_id => child_id = parent_id, + ExprKind::Break(Destination { target_id: Ok(id), .. }, _) => { + child_id = id; + iter = map.parent_iter(id); + }, + ExprKind::Block(..) => child_id = parent_id, + _ => return None, + } + } + None +} + macro_rules! op_utils { ($($name:ident $assign:ident)*) => { /// Binary operation traits like `LangItem::Add` diff --git a/src/tools/clippy/clippy_utils/src/msrvs.rs b/src/tools/clippy/clippy_utils/src/msrvs.rs index b9ec2c19fdd..b09c929f76e 100644 --- a/src/tools/clippy/clippy_utils/src/msrvs.rs +++ b/src/tools/clippy/clippy_utils/src/msrvs.rs @@ -12,8 +12,8 @@ macro_rules! msrv_aliases { // names may refer to stabilized feature flags or library items msrv_aliases! { - 1,53,0 { OR_PATTERNS, MANUAL_BITS } - 1,52,0 { STR_SPLIT_ONCE } + 1,53,0 { OR_PATTERNS, MANUAL_BITS, BTREE_MAP_RETAIN, BTREE_SET_RETAIN } + 1,52,0 { STR_SPLIT_ONCE, REM_EUCLID_CONST } 1,51,0 { BORROW_AS_PTR, UNSIGNED_ABS } 1,50,0 { BOOL_THEN } 1,47,0 { TAU } @@ -23,14 +23,15 @@ msrv_aliases! { 1,42,0 { MATCHES_MACRO, SLICE_PATTERNS, PTR_SLICE_RAW_PARTS } 1,41,0 { RE_REBALANCING_COHERENCE, RESULT_MAP_OR_ELSE } 1,40,0 { MEM_TAKE, NON_EXHAUSTIVE, OPTION_AS_DEREF } - 1,38,0 { POINTER_CAST } + 1,38,0 { POINTER_CAST, REM_EUCLID } 1,37,0 { TYPE_ALIAS_ENUM_VARIANTS } 1,36,0 { ITERATOR_COPIED } 1,35,0 { OPTION_COPIED, RANGE_CONTAINS } 1,34,0 { TRY_FROM } 1,30,0 { ITERATOR_FIND_MAP, TOOL_ATTRIBUTES } 1,28,0 { FROM_BOOL } - 1,26,0 { RANGE_INCLUSIVE } + 1,26,0 { RANGE_INCLUSIVE, STRING_RETAIN } + 1,18,0 { HASH_MAP_RETAIN, HASH_SET_RETAIN } 1,17,0 { FIELD_INIT_SHORTHAND, STATIC_IN_CONST, EXPECT_ERR } 1,16,0 { STR_REPEAT } 1,24,0 { IS_ASCII_DIGIT } diff --git a/src/tools/clippy/clippy_utils/src/paths.rs b/src/tools/clippy/clippy_utils/src/paths.rs index 89789c3d851..6542e77113b 100644 --- a/src/tools/clippy/clippy_utils/src/paths.rs +++ b/src/tools/clippy/clippy_utils/src/paths.rs @@ -21,8 +21,14 @@ pub const ASREF_TRAIT: [&str; 3] = ["core", "convert", "AsRef"]; pub const BTREEMAP_CONTAINS_KEY: [&str; 6] = ["alloc", "collections", "btree", "map", "BTreeMap", "contains_key"]; pub const BTREEMAP_ENTRY: [&str; 6] = ["alloc", "collections", "btree", "map", "entry", "Entry"]; pub const BTREEMAP_INSERT: [&str; 6] = ["alloc", "collections", "btree", "map", "BTreeMap", "insert"]; +pub const BTREESET_ITER: [&str; 6] = ["alloc", "collections", "btree", "set", "BTreeSet", "iter"]; pub const CLONE_TRAIT_METHOD: [&str; 4] = ["core", "clone", "Clone", "clone"]; pub const COW: [&str; 3] = ["alloc", "borrow", "Cow"]; +pub const CORE_ITER_COLLECT: [&str; 6] = ["core", "iter", "traits", "iterator", "Iterator", "collect"]; +pub const CORE_ITER_CLONED: [&str; 6] = ["core", "iter", "traits", "iterator", "Iterator", "cloned"]; +pub const CORE_ITER_COPIED: [&str; 6] = ["core", "iter", "traits", "iterator", "Iterator", "copied"]; +pub const CORE_ITER_FILTER: [&str; 6] = ["core", "iter", "traits", "iterator", "Iterator", "filter"]; +pub const CORE_ITER_INTO_ITER: [&str; 6] = ["core", "iter", "traits", "collect", "IntoIterator", "into_iter"]; pub const CSTRING_AS_C_STR: [&str; 5] = ["alloc", "ffi", "c_str", "CString", "as_c_str"]; pub const DEFAULT_TRAIT_METHOD: [&str; 4] = ["core", "default", "Default", "default"]; pub const DEREF_MUT_TRAIT_METHOD: [&str; 5] = ["core", "ops", "deref", "DerefMut", "deref_mut"]; @@ -50,6 +56,7 @@ pub const FUTURES_IO_ASYNCWRITEEXT: [&str; 3] = ["futures_util", "io", "AsyncWri pub const HASHMAP_CONTAINS_KEY: [&str; 6] = ["std", "collections", "hash", "map", "HashMap", "contains_key"]; pub const HASHMAP_ENTRY: [&str; 5] = ["std", "collections", "hash", "map", "Entry"]; pub const HASHMAP_INSERT: [&str; 6] = ["std", "collections", "hash", "map", "HashMap", "insert"]; +pub const HASHSET_ITER: [&str; 6] = ["std", "collections", "hash", "set", "HashSet", "iter"]; #[cfg(feature = "internal")] pub const IDENT: [&str; 3] = ["rustc_span", "symbol", "Ident"]; #[cfg(feature = "internal")] @@ -62,6 +69,7 @@ pub const IO_WRITE: [&str; 3] = ["std", "io", "Write"]; pub const IPADDR_V4: [&str; 5] = ["std", "net", "ip", "IpAddr", "V4"]; pub const IPADDR_V6: [&str; 5] = ["std", "net", "ip", "IpAddr", "V6"]; pub const ITER_COUNT: [&str; 6] = ["core", "iter", "traits", "iterator", "Iterator", "count"]; +pub const ITER_EMPTY: [&str; 5] = ["core", "iter", "sources", "empty", "Empty"]; pub const ITER_REPEAT: [&str; 5] = ["core", "iter", "sources", "repeat", "repeat"]; #[expect(clippy::invalid_paths)] // internal lints do not know about all external crates pub const ITERTOOLS_NEXT_TUPLE: [&str; 3] = ["itertools", "Itertools", "next_tuple"]; @@ -83,8 +91,6 @@ pub const OPTION_SOME: [&str; 4] = ["core", "option", "Option", "Some"]; pub const ORD: [&str; 3] = ["core", "cmp", "Ord"]; pub const OS_STRING_AS_OS_STR: [&str; 5] = ["std", "ffi", "os_str", "OsString", "as_os_str"]; pub const OS_STR_TO_OS_STRING: [&str; 5] = ["std", "ffi", "os_str", "OsStr", "to_os_string"]; -pub const PARKING_LOT_RAWMUTEX: [&str; 3] = ["parking_lot", "raw_mutex", "RawMutex"]; -pub const PARKING_LOT_RAWRWLOCK: [&str; 3] = ["parking_lot", "raw_rwlock", "RawRwLock"]; pub const PARKING_LOT_MUTEX_GUARD: [&str; 3] = ["lock_api", "mutex", "MutexGuard"]; pub const PARKING_LOT_RWLOCK_READ_GUARD: [&str; 3] = ["lock_api", "rwlock", "RwLockReadGuard"]; pub const PARKING_LOT_RWLOCK_WRITE_GUARD: [&str; 3] = ["lock_api", "rwlock", "RwLockWriteGuard"]; @@ -144,6 +150,7 @@ pub const SLICE_FROM_RAW_PARTS: [&str; 4] = ["core", "slice", "raw", "from_raw_p pub const SLICE_FROM_RAW_PARTS_MUT: [&str; 4] = ["core", "slice", "raw", "from_raw_parts_mut"]; pub const SLICE_GET: [&str; 4] = ["core", "slice", "<impl [T]>", "get"]; pub const SLICE_INTO_VEC: [&str; 4] = ["alloc", "slice", "<impl [T]>", "into_vec"]; +pub const SLICE_INTO: [&str; 4] = ["core", "slice", "<impl [T]>", "iter"]; pub const SLICE_ITER: [&str; 4] = ["core", "slice", "iter", "Iter"]; pub const STDERR: [&str; 4] = ["std", "io", "stdio", "stderr"]; pub const STDOUT: [&str; 4] = ["std", "io", "stdio", "stdout"]; @@ -153,6 +160,7 @@ pub const STRING_AS_MUT_STR: [&str; 4] = ["alloc", "string", "String", "as_mut_s pub const STRING_AS_STR: [&str; 4] = ["alloc", "string", "String", "as_str"]; pub const STRING_NEW: [&str; 4] = ["alloc", "string", "String", "new"]; pub const STR_BYTES: [&str; 4] = ["core", "str", "<impl str>", "bytes"]; +pub const STR_CHARS: [&str; 4] = ["core", "str", "<impl str>", "chars"]; pub const STR_ENDS_WITH: [&str; 4] = ["core", "str", "<impl str>", "ends_with"]; pub const STR_FROM_UTF8: [&str; 4] = ["core", "str", "converts", "from_utf8"]; pub const STR_LEN: [&str; 4] = ["core", "str", "<impl str>", "len"]; @@ -178,6 +186,7 @@ pub const TOKIO_IO_ASYNCWRITEEXT: [&str; 5] = ["tokio", "io", "util", "async_wri pub const TRY_FROM: [&str; 4] = ["core", "convert", "TryFrom", "try_from"]; pub const VEC_AS_MUT_SLICE: [&str; 4] = ["alloc", "vec", "Vec", "as_mut_slice"]; pub const VEC_AS_SLICE: [&str; 4] = ["alloc", "vec", "Vec", "as_slice"]; +pub const VEC_DEQUE_ITER: [&str; 5] = ["alloc", "collections", "vec_deque", "VecDeque", "iter"]; pub const VEC_FROM_ELEM: [&str; 3] = ["alloc", "vec", "from_elem"]; pub const VEC_NEW: [&str; 4] = ["alloc", "vec", "Vec", "new"]; pub const VEC_RESIZE: [&str; 4] = ["alloc", "vec", "Vec", "resize"]; diff --git a/src/tools/clippy/clippy_utils/src/ty.rs b/src/tools/clippy/clippy_utils/src/ty.rs index 227e97d37ec..a426fa1b0ff 100644 --- a/src/tools/clippy/clippy_utils/src/ty.rs +++ b/src/tools/clippy/clippy_utils/src/ty.rs @@ -2,19 +2,20 @@ #![allow(clippy::module_name_repetitions)] +use core::ops::ControlFlow; use rustc_ast::ast::Mutability; use rustc_data_structures::fx::{FxHashMap, FxHashSet}; use rustc_hir as hir; -use rustc_hir::def::{CtorKind, DefKind, Res}; +use rustc_hir::def::{CtorKind, CtorOf, DefKind, Res}; use rustc_hir::def_id::DefId; -use rustc_hir::{Expr, LangItem, TyKind, Unsafety}; +use rustc_hir::{Expr, FnDecl, LangItem, TyKind, Unsafety}; use rustc_infer::infer::TyCtxtInferExt; use rustc_lint::LateContext; use rustc_middle::mir::interpret::{ConstValue, Scalar}; use rustc_middle::ty::subst::{GenericArg, GenericArgKind, Subst}; use rustc_middle::ty::{ - self, AdtDef, Binder, FnSig, IntTy, ParamEnv, Predicate, PredicateKind, Ty, TyCtxt, TypeFoldable, UintTy, - VariantDiscr, + self, AdtDef, Binder, BoundRegion, DefIdTree, FnSig, IntTy, ParamEnv, Predicate, PredicateKind, ProjectionTy, + Region, RegionKind, Ty, TyCtxt, TypeSuperVisitable, TypeVisitable, TypeVisitor, UintTy, VariantDef, VariantDiscr, }; use rustc_span::symbol::Ident; use rustc_span::{sym, Span, Symbol, DUMMY_SP}; @@ -501,16 +502,46 @@ pub fn all_predicates_of(tcx: TyCtxt<'_>, id: DefId) -> impl Iterator<Item = &(P #[derive(Clone, Copy)] pub enum ExprFnSig<'tcx> { Sig(Binder<'tcx, FnSig<'tcx>>), - Closure(Binder<'tcx, FnSig<'tcx>>), + Closure(Option<&'tcx FnDecl<'tcx>>, Binder<'tcx, FnSig<'tcx>>), Trait(Binder<'tcx, Ty<'tcx>>, Option<Binder<'tcx, Ty<'tcx>>>), } impl<'tcx> ExprFnSig<'tcx> { - /// Gets the argument type at the given offset. - pub fn input(self, i: usize) -> Binder<'tcx, Ty<'tcx>> { + /// Gets the argument type at the given offset. This will return `None` when the index is out of + /// bounds only for variadic functions, otherwise this will panic. + pub fn input(self, i: usize) -> Option<Binder<'tcx, Ty<'tcx>>> { match self { - Self::Sig(sig) => sig.input(i), - Self::Closure(sig) => sig.input(0).map_bound(|ty| ty.tuple_fields()[i]), - Self::Trait(inputs, _) => inputs.map_bound(|ty| ty.tuple_fields()[i]), + Self::Sig(sig) => { + if sig.c_variadic() { + sig.inputs().map_bound(|inputs| inputs.get(i).copied()).transpose() + } else { + Some(sig.input(i)) + } + }, + Self::Closure(_, sig) => Some(sig.input(0).map_bound(|ty| ty.tuple_fields()[i])), + Self::Trait(inputs, _) => Some(inputs.map_bound(|ty| ty.tuple_fields()[i])), + } + } + + /// Gets the argument type at the given offset. For closures this will also get the type as + /// written. This will return `None` when the index is out of bounds only for variadic + /// functions, otherwise this will panic. + pub fn input_with_hir(self, i: usize) -> Option<(Option<&'tcx hir::Ty<'tcx>>, Binder<'tcx, Ty<'tcx>>)> { + match self { + Self::Sig(sig) => { + if sig.c_variadic() { + sig.inputs() + .map_bound(|inputs| inputs.get(i).copied()) + .transpose() + .map(|arg| (None, arg)) + } else { + Some((None, sig.input(i))) + } + }, + Self::Closure(decl, sig) => Some(( + decl.and_then(|decl| decl.inputs.get(i)), + sig.input(0).map_bound(|ty| ty.tuple_fields()[i]), + )), + Self::Trait(inputs, _) => Some((None, inputs.map_bound(|ty| ty.tuple_fields()[i]))), } } @@ -518,7 +549,7 @@ impl<'tcx> ExprFnSig<'tcx> { /// specified. pub fn output(self) -> Option<Binder<'tcx, Ty<'tcx>>> { match self { - Self::Sig(sig) | Self::Closure(sig) => Some(sig.output()), + Self::Sig(sig) | Self::Closure(_, sig) => Some(sig.output()), Self::Trait(_, output) => output, } } @@ -529,74 +560,123 @@ pub fn expr_sig<'tcx>(cx: &LateContext<'tcx>, expr: &Expr<'_>) -> Option<ExprFnS if let Res::Def(DefKind::Fn | DefKind::Ctor(_, CtorKind::Fn) | DefKind::AssocFn, id) = path_res(cx, expr) { Some(ExprFnSig::Sig(cx.tcx.fn_sig(id))) } else { - let ty = cx.typeck_results().expr_ty_adjusted(expr).peel_refs(); - match *ty.kind() { - ty::Closure(_, subs) => Some(ExprFnSig::Closure(subs.as_closure().sig())), - ty::FnDef(id, subs) => Some(ExprFnSig::Sig(cx.tcx.bound_fn_sig(id).subst(cx.tcx, subs))), - ty::FnPtr(sig) => Some(ExprFnSig::Sig(sig)), - ty::Dynamic(bounds, _) => { - let lang_items = cx.tcx.lang_items(); - match bounds.principal() { - Some(bound) - if Some(bound.def_id()) == lang_items.fn_trait() - || Some(bound.def_id()) == lang_items.fn_once_trait() - || Some(bound.def_id()) == lang_items.fn_mut_trait() => - { - let output = bounds - .projection_bounds() - .find(|p| lang_items.fn_once_output().map_or(false, |id| id == p.item_def_id())) - .map(|p| p.map_bound(|p| p.term.ty().expect("return type was a const"))); - Some(ExprFnSig::Trait(bound.map_bound(|b| b.substs.type_at(0)), output)) - }, - _ => None, + ty_sig(cx, cx.typeck_results().expr_ty_adjusted(expr).peel_refs()) + } +} + +fn ty_sig<'tcx>(cx: &LateContext<'tcx>, ty: Ty<'tcx>) -> Option<ExprFnSig<'tcx>> { + match *ty.kind() { + ty::Closure(id, subs) => { + let decl = id + .as_local() + .and_then(|id| cx.tcx.hir().fn_decl_by_hir_id(cx.tcx.hir().local_def_id_to_hir_id(id))); + Some(ExprFnSig::Closure(decl, subs.as_closure().sig())) + }, + ty::FnDef(id, subs) => Some(ExprFnSig::Sig(cx.tcx.bound_fn_sig(id).subst(cx.tcx, subs))), + ty::FnPtr(sig) => Some(ExprFnSig::Sig(sig)), + ty::Dynamic(bounds, _) => { + let lang_items = cx.tcx.lang_items(); + match bounds.principal() { + Some(bound) + if Some(bound.def_id()) == lang_items.fn_trait() + || Some(bound.def_id()) == lang_items.fn_once_trait() + || Some(bound.def_id()) == lang_items.fn_mut_trait() => + { + let output = bounds + .projection_bounds() + .find(|p| lang_items.fn_once_output().map_or(false, |id| id == p.item_def_id())) + .map(|p| p.map_bound(|p| p.term.ty().unwrap())); + Some(ExprFnSig::Trait(bound.map_bound(|b| b.substs.type_at(0)), output)) + }, + _ => None, + } + }, + ty::Projection(proj) => match cx.tcx.try_normalize_erasing_regions(cx.param_env, ty) { + Ok(normalized_ty) if normalized_ty != ty => ty_sig(cx, normalized_ty), + _ => sig_for_projection(cx, proj).or_else(|| sig_from_bounds(cx, ty)), + }, + ty::Param(_) => sig_from_bounds(cx, ty), + _ => None, + } +} + +fn sig_from_bounds<'tcx>(cx: &LateContext<'tcx>, ty: Ty<'tcx>) -> Option<ExprFnSig<'tcx>> { + let mut inputs = None; + let mut output = None; + let lang_items = cx.tcx.lang_items(); + + for (pred, _) in all_predicates_of(cx.tcx, cx.typeck_results().hir_owner.to_def_id()) { + match pred.kind().skip_binder() { + PredicateKind::Trait(p) + if (lang_items.fn_trait() == Some(p.def_id()) + || lang_items.fn_mut_trait() == Some(p.def_id()) + || lang_items.fn_once_trait() == Some(p.def_id())) + && p.self_ty() == ty => + { + if inputs.is_some() { + // Multiple different fn trait impls. Is this even allowed? + return None; } + inputs = Some(pred.kind().rebind(p.trait_ref.substs.type_at(1))); }, - ty::Param(_) | ty::Projection(..) => { - let mut inputs = None; - let mut output = None; - let lang_items = cx.tcx.lang_items(); - - for (pred, _) in all_predicates_of(cx.tcx, cx.typeck_results().hir_owner.to_def_id()) { - let mut is_input = false; - if let Some(ty) = pred - .kind() - .map_bound(|pred| match pred { - PredicateKind::Trait(p) - if (lang_items.fn_trait() == Some(p.def_id()) - || lang_items.fn_mut_trait() == Some(p.def_id()) - || lang_items.fn_once_trait() == Some(p.def_id())) - && p.self_ty() == ty => - { - is_input = true; - Some(p.trait_ref.substs.type_at(1)) - }, - PredicateKind::Projection(p) - if Some(p.projection_ty.item_def_id) == lang_items.fn_once_output() - && p.projection_ty.self_ty() == ty => - { - is_input = false; - p.term.ty() - }, - _ => None, - }) - .transpose() - { - if is_input && inputs.is_none() { - inputs = Some(ty); - } else if !is_input && output.is_none() { - output = Some(ty); - } else { - // Multiple different fn trait impls. Is this even allowed? - return None; - } - } + PredicateKind::Projection(p) + if Some(p.projection_ty.item_def_id) == lang_items.fn_once_output() + && p.projection_ty.self_ty() == ty => + { + if output.is_some() { + // Multiple different fn trait impls. Is this even allowed? + return None; } + output = Some(pred.kind().rebind(p.term.ty().unwrap())); + }, + _ => (), + } + } + + inputs.map(|ty| ExprFnSig::Trait(ty, output)) +} + +fn sig_for_projection<'tcx>(cx: &LateContext<'tcx>, ty: ProjectionTy<'tcx>) -> Option<ExprFnSig<'tcx>> { + let mut inputs = None; + let mut output = None; + let lang_items = cx.tcx.lang_items(); - inputs.map(|ty| ExprFnSig::Trait(ty, output)) + for pred in cx + .tcx + .bound_explicit_item_bounds(ty.item_def_id) + .transpose_iter() + .map(|x| x.map_bound(|(p, _)| p)) + { + match pred.0.kind().skip_binder() { + PredicateKind::Trait(p) + if (lang_items.fn_trait() == Some(p.def_id()) + || lang_items.fn_mut_trait() == Some(p.def_id()) + || lang_items.fn_once_trait() == Some(p.def_id())) => + { + if inputs.is_some() { + // Multiple different fn trait impls. Is this even allowed? + return None; + } + inputs = Some( + pred.map_bound(|pred| pred.kind().rebind(p.trait_ref.substs.type_at(1))) + .subst(cx.tcx, ty.substs), + ); }, - _ => None, + PredicateKind::Projection(p) if Some(p.projection_ty.item_def_id) == lang_items.fn_once_output() => { + if output.is_some() { + // Multiple different fn trait impls. Is this even allowed? + return None; + } + output = Some( + pred.map_bound(|pred| pred.kind().rebind(p.term.ty().unwrap())) + .subst(cx.tcx, ty.substs), + ); + }, + _ => (), } } + + inputs.map(|ty| ExprFnSig::Trait(ty, output)) } #[derive(Clone, Copy)] @@ -667,3 +747,45 @@ pub fn is_c_void(cx: &LateContext<'_>, ty: Ty<'_>) -> bool { false } } + +pub fn for_each_top_level_late_bound_region<B>( + ty: Ty<'_>, + f: impl FnMut(BoundRegion) -> ControlFlow<B>, +) -> ControlFlow<B> { + struct V<F> { + index: u32, + f: F, + } + impl<'tcx, B, F: FnMut(BoundRegion) -> ControlFlow<B>> TypeVisitor<'tcx> for V<F> { + type BreakTy = B; + fn visit_region(&mut self, r: Region<'tcx>) -> ControlFlow<Self::BreakTy> { + if let RegionKind::ReLateBound(idx, bound) = r.kind() && idx.as_u32() == self.index { + (self.f)(bound) + } else { + ControlFlow::Continue(()) + } + } + fn visit_binder<T: TypeVisitable<'tcx>>(&mut self, t: &Binder<'tcx, T>) -> ControlFlow<Self::BreakTy> { + self.index += 1; + let res = t.super_visit_with(self); + self.index -= 1; + res + } + } + ty.visit_with(&mut V { index: 0, f }) +} + +/// Gets the struct or enum variant from the given `Res` +pub fn variant_of_res<'tcx>(cx: &LateContext<'tcx>, res: Res) -> Option<&'tcx VariantDef> { + match res { + Res::Def(DefKind::Struct, id) => Some(cx.tcx.adt_def(id).non_enum_variant()), + Res::Def(DefKind::Variant, id) => Some(cx.tcx.adt_def(cx.tcx.parent(id)).variant_with_id(id)), + Res::Def(DefKind::Ctor(CtorOf::Struct, _), id) => Some(cx.tcx.adt_def(cx.tcx.parent(id)).non_enum_variant()), + Res::Def(DefKind::Ctor(CtorOf::Variant, _), id) => { + let var_id = cx.tcx.parent(id); + Some(cx.tcx.adt_def(cx.tcx.parent(var_id)).variant_with_id(var_id)) + }, + Res::SelfCtor(id) => Some(cx.tcx.type_of(id).ty_adt_def().unwrap().non_enum_variant()), + _ => None, + } +} diff --git a/src/tools/clippy/clippy_utils/src/visitors.rs b/src/tools/clippy/clippy_utils/src/visitors.rs index b6c8f1d516e..68cfa8c1aa8 100644 --- a/src/tools/clippy/clippy_utils/src/visitors.rs +++ b/src/tools/clippy/clippy_utils/src/visitors.rs @@ -1,16 +1,18 @@ +use crate::ty::needs_ordered_drop; use crate::{get_enclosing_block, path_to_local_id}; use core::ops::ControlFlow; use rustc_hir as hir; -use rustc_hir::def::{DefKind, Res}; +use rustc_hir::def::{CtorKind, DefKind, Res}; use rustc_hir::intravisit::{self, walk_block, walk_expr, Visitor}; use rustc_hir::{ - Arm, Block, BlockCheckMode, Body, BodyId, Expr, ExprKind, HirId, ItemId, ItemKind, Stmt, UnOp, UnsafeSource, - Unsafety, + Arm, Block, BlockCheckMode, Body, BodyId, Expr, ExprKind, HirId, ItemId, ItemKind, Let, QPath, Stmt, UnOp, + UnsafeSource, Unsafety, }; use rustc_lint::LateContext; use rustc_middle::hir::map::Map; use rustc_middle::hir::nested_filter; -use rustc_middle::ty; +use rustc_middle::ty::adjustment::Adjust; +use rustc_middle::ty::{self, Ty, TypeckResults}; /// Convenience method for creating a `Visitor` with just `visit_expr` overridden and nested /// bodies (i.e. closures) are visited. @@ -494,3 +496,124 @@ pub fn for_each_local_use_after_expr<'tcx, B>( ControlFlow::Continue(()) } } + +// Calls the given function for every unconsumed temporary created by the expression. Note the +// function is only guaranteed to be called for types which need to be dropped, but it may be called +// for other types. +pub fn for_each_unconsumed_temporary<'tcx, B>( + cx: &LateContext<'tcx>, + e: &'tcx Expr<'tcx>, + mut f: impl FnMut(Ty<'tcx>) -> ControlFlow<B>, +) -> ControlFlow<B> { + // Todo: Handle partially consumed values. + fn helper<'tcx, B>( + typeck: &'tcx TypeckResults<'tcx>, + consume: bool, + e: &'tcx Expr<'tcx>, + f: &mut impl FnMut(Ty<'tcx>) -> ControlFlow<B>, + ) -> ControlFlow<B> { + if !consume + || matches!( + typeck.expr_adjustments(e), + [adjust, ..] if matches!(adjust.kind, Adjust::Borrow(_) | Adjust::Deref(_)) + ) + { + match e.kind { + ExprKind::Path(QPath::Resolved(None, p)) + if matches!(p.res, Res::Def(DefKind::Ctor(_, CtorKind::Const), _)) => + { + f(typeck.expr_ty(e))?; + }, + ExprKind::Path(_) + | ExprKind::Unary(UnOp::Deref, _) + | ExprKind::Index(..) + | ExprKind::Field(..) + | ExprKind::AddrOf(..) => (), + _ => f(typeck.expr_ty(e))?, + } + } + match e.kind { + ExprKind::AddrOf(_, _, e) + | ExprKind::Field(e, _) + | ExprKind::Unary(UnOp::Deref, e) + | ExprKind::Match(e, ..) + | ExprKind::Let(&Let { init: e, .. }) => { + helper(typeck, false, e, f)?; + }, + ExprKind::Block(&Block { expr: Some(e), .. }, _) + | ExprKind::Box(e) + | ExprKind::Cast(e, _) + | ExprKind::Unary(_, e) => { + helper(typeck, true, e, f)?; + }, + ExprKind::Call(callee, args) => { + helper(typeck, true, callee, f)?; + for arg in args { + helper(typeck, true, arg, f)?; + } + }, + ExprKind::MethodCall(_, args, _) | ExprKind::Tup(args) | ExprKind::Array(args) => { + for arg in args { + helper(typeck, true, arg, f)?; + } + }, + ExprKind::Index(borrowed, consumed) + | ExprKind::Assign(borrowed, consumed, _) + | ExprKind::AssignOp(_, borrowed, consumed) => { + helper(typeck, false, borrowed, f)?; + helper(typeck, true, consumed, f)?; + }, + ExprKind::Binary(_, lhs, rhs) => { + helper(typeck, true, lhs, f)?; + helper(typeck, true, rhs, f)?; + }, + ExprKind::Struct(_, fields, default) => { + for field in fields { + helper(typeck, true, field.expr, f)?; + } + if let Some(default) = default { + helper(typeck, false, default, f)?; + } + }, + ExprKind::If(cond, then, else_expr) => { + helper(typeck, true, cond, f)?; + helper(typeck, true, then, f)?; + if let Some(else_expr) = else_expr { + helper(typeck, true, else_expr, f)?; + } + }, + ExprKind::Type(e, _) => { + helper(typeck, consume, e, f)?; + }, + + // Either drops temporaries, jumps out of the current expression, or has no sub expression. + ExprKind::DropTemps(_) + | ExprKind::Ret(_) + | ExprKind::Break(..) + | ExprKind::Yield(..) + | ExprKind::Block(..) + | ExprKind::Loop(..) + | ExprKind::Repeat(..) + | ExprKind::Lit(_) + | ExprKind::ConstBlock(_) + | ExprKind::Closure { .. } + | ExprKind::Path(_) + | ExprKind::Continue(_) + | ExprKind::InlineAsm(_) + | ExprKind::Err => (), + } + ControlFlow::Continue(()) + } + helper(cx.typeck_results(), true, e, &mut f) +} + +pub fn any_temporaries_need_ordered_drop<'tcx>(cx: &LateContext<'tcx>, e: &'tcx Expr<'tcx>) -> bool { + for_each_unconsumed_temporary(cx, e, |ty| { + if needs_ordered_drop(cx, ty) { + ControlFlow::Break(()) + } else { + ControlFlow::Continue(()) + } + }) + .is_break() +} diff --git a/src/tools/clippy/rust-toolchain b/src/tools/clippy/rust-toolchain index 6ad56aacf8c..6cc6d5036b3 100644 --- a/src/tools/clippy/rust-toolchain +++ b/src/tools/clippy/rust-toolchain @@ -1,3 +1,3 @@ [toolchain] -channel = "nightly-2022-06-16" +channel = "nightly-2022-06-30" components = ["cargo", "llvm-tools-preview", "rust-src", "rust-std", "rustc", "rustc-dev", "rustfmt"] diff --git a/src/tools/clippy/src/driver.rs b/src/tools/clippy/src/driver.rs index 67467f89b47..96d542cfe10 100644 --- a/src/tools/clippy/src/driver.rs +++ b/src/tools/clippy/src/driver.rs @@ -60,6 +60,7 @@ fn test_arg_value() { assert_eq!(arg_value(args, "--bar", |p| p == "foo"), None); assert_eq!(arg_value(args, "--foobar", |p| p == "foo"), None); assert_eq!(arg_value(args, "--foobar", |p| p == "123"), Some("123")); + assert_eq!(arg_value(args, "--foobar", |p| p.contains("12")), Some("123")); assert_eq!(arg_value(args, "--foo", |_| true), None); } @@ -152,7 +153,8 @@ You can use tool lints to allow or deny lints from your code, eg.: const BUG_REPORT_URL: &str = "https://github.com/rust-lang/rust-clippy/issues/new"; -static ICE_HOOK: LazyLock<Box<dyn Fn(&panic::PanicInfo<'_>) + Sync + Send + 'static>> = LazyLock::new(|| { +type PanicCallback = dyn Fn(&panic::PanicInfo<'_>) + Sync + Send + 'static; +static ICE_HOOK: LazyLock<Box<PanicCallback>> = LazyLock::new(|| { let hook = panic::take_hook(); panic::set_hook(Box::new(|info| report_clippy_ice(info, BUG_REPORT_URL))); hook @@ -334,15 +336,13 @@ pub fn main() { // - IF Clippy is run on the main crate, not on deps (`!cap_lints_allow`) THEN // - IF `--no-deps` is not set (`!no_deps`) OR // - IF `--no-deps` is set and Clippy is run on the specified primary package - let cap_lints_allow = arg_value(&orig_args, "--cap-lints", |val| val == "allow").is_some(); + let cap_lints_allow = arg_value(&orig_args, "--cap-lints", |val| val == "allow").is_some() + && arg_value(&orig_args, "--force-warn", |val| val.contains("clippy::")).is_none(); let in_primary_package = env::var("CARGO_PRIMARY_PACKAGE").is_ok(); let clippy_enabled = !cap_lints_allow && (!no_deps || in_primary_package); if clippy_enabled { args.extend(clippy_args); - } - - if clippy_enabled { rustc_driver::RunCompiler::new(&args, &mut ClippyCallbacks { clippy_args_var }).run() } else { rustc_driver::RunCompiler::new(&args, &mut RustcCallbacks { clippy_args_var }).run() diff --git a/src/tools/clippy/tests/compile-test.rs b/src/tools/clippy/tests/compile-test.rs index 061cda7e01e..bf7a39edf4c 100644 --- a/src/tools/clippy/tests/compile-test.rs +++ b/src/tools/clippy/tests/compile-test.rs @@ -23,6 +23,7 @@ const RUN_INTERNAL_TESTS: bool = cfg!(feature = "internal"); /// All crates used in UI tests are listed here static TEST_DEPENDENCIES: &[&str] = &[ + "clippy_lints", "clippy_utils", "derive_new", "futures", @@ -41,6 +42,8 @@ static TEST_DEPENDENCIES: &[&str] = &[ // Test dependencies may need an `extern crate` here to ensure that they show up // in the depinfo file (otherwise cargo thinks they are unused) #[allow(unused_extern_crates)] +extern crate clippy_lints; +#[allow(unused_extern_crates)] extern crate clippy_utils; #[allow(unused_extern_crates)] extern crate derive_new; @@ -124,7 +127,7 @@ fn base_config(test_dir: &str) -> compiletest::Config { let mut config = compiletest::Config { edition: Some("2021".into()), mode: TestMode::Ui, - ..compiletest::Config::default() + ..Default::default() }; if let Ok(filters) = env::var("TESTNAME") { @@ -280,6 +283,24 @@ fn run_ui_cargo() { } env::set_current_dir(&src_path)?; + + let cargo_toml_path = case.path().join("Cargo.toml"); + let cargo_content = fs::read(&cargo_toml_path)?; + let cargo_parsed: toml::Value = toml::from_str( + std::str::from_utf8(&cargo_content).expect("`Cargo.toml` is not a valid utf-8 file!"), + ) + .expect("Can't parse `Cargo.toml`"); + + let _g = VarGuard::set("CARGO_MANIFEST_DIR", case.path()); + let _h = VarGuard::set( + "CARGO_PKG_RUST_VERSION", + cargo_parsed + .get("package") + .and_then(|p| p.get("rust-version")) + .and_then(toml::Value::as_str) + .unwrap_or(""), + ); + for file in fs::read_dir(&src_path)? { let file = file?; if file.file_type()?.is_dir() { diff --git a/src/tools/clippy/tests/ui-cargo/cargo_rust_version/fail_both_diff/Cargo.toml b/src/tools/clippy/tests/ui-cargo/cargo_rust_version/fail_both_diff/Cargo.toml new file mode 100644 index 00000000000..73ec29c5803 --- /dev/null +++ b/src/tools/clippy/tests/ui-cargo/cargo_rust_version/fail_both_diff/Cargo.toml @@ -0,0 +1,8 @@ +[package] +name = "fail-both-diff" +version = "0.1.0" +rust-version = "1.56" + +# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html + +[dependencies] diff --git a/src/tools/clippy/tests/ui-cargo/cargo_rust_version/fail_both_diff/clippy.toml b/src/tools/clippy/tests/ui-cargo/cargo_rust_version/fail_both_diff/clippy.toml new file mode 100644 index 00000000000..abe19b3a007 --- /dev/null +++ b/src/tools/clippy/tests/ui-cargo/cargo_rust_version/fail_both_diff/clippy.toml @@ -0,0 +1 @@ +msrv = "1.59" diff --git a/src/tools/clippy/tests/ui-cargo/cargo_rust_version/fail_both_diff/src/main.rs b/src/tools/clippy/tests/ui-cargo/cargo_rust_version/fail_both_diff/src/main.rs new file mode 100644 index 00000000000..5b91d550867 --- /dev/null +++ b/src/tools/clippy/tests/ui-cargo/cargo_rust_version/fail_both_diff/src/main.rs @@ -0,0 +1,11 @@ +#![deny(clippy::use_self)] + +pub struct Foo; + +impl Foo { + pub fn bar() -> Foo { + Foo + } +} + +fn main() {} diff --git a/src/tools/clippy/tests/ui-cargo/cargo_rust_version/fail_both_diff/src/main.stderr b/src/tools/clippy/tests/ui-cargo/cargo_rust_version/fail_both_diff/src/main.stderr new file mode 100644 index 00000000000..9a7d802dc6d --- /dev/null +++ b/src/tools/clippy/tests/ui-cargo/cargo_rust_version/fail_both_diff/src/main.stderr @@ -0,0 +1,16 @@ +warning: the MSRV in `clippy.toml` and `Cargo.toml` differ; using `1.59.0` from `clippy.toml` + +error: unnecessary structure name repetition + --> $DIR/main.rs:6:21 + | +LL | pub fn bar() -> Foo { + | ^^^ help: use the applicable keyword: `Self` + | +note: the lint level is defined here + --> $DIR/main.rs:1:9 + | +LL | #![deny(clippy::use_self)] + | ^^^^^^^^^^^^^^^^ + +error: aborting due to previous error; 1 warning emitted + diff --git a/src/tools/clippy/tests/ui-cargo/cargo_rust_version/fail_both_same/Cargo.toml b/src/tools/clippy/tests/ui-cargo/cargo_rust_version/fail_both_same/Cargo.toml new file mode 100644 index 00000000000..2d6d547e4fe --- /dev/null +++ b/src/tools/clippy/tests/ui-cargo/cargo_rust_version/fail_both_same/Cargo.toml @@ -0,0 +1,8 @@ +[package] +name = "fail-both-same" +version = "0.1.0" +rust-version = "1.57.0" + +# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html + +[dependencies] diff --git a/src/tools/clippy/tests/ui-cargo/cargo_rust_version/fail_both_same/clippy.toml b/src/tools/clippy/tests/ui-cargo/cargo_rust_version/fail_both_same/clippy.toml new file mode 100644 index 00000000000..5cccb362c14 --- /dev/null +++ b/src/tools/clippy/tests/ui-cargo/cargo_rust_version/fail_both_same/clippy.toml @@ -0,0 +1 @@ +msrv = "1.57" diff --git a/src/tools/clippy/tests/ui-cargo/cargo_rust_version/fail_both_same/src/main.rs b/src/tools/clippy/tests/ui-cargo/cargo_rust_version/fail_both_same/src/main.rs new file mode 100644 index 00000000000..5b91d550867 --- /dev/null +++ b/src/tools/clippy/tests/ui-cargo/cargo_rust_version/fail_both_same/src/main.rs @@ -0,0 +1,11 @@ +#![deny(clippy::use_self)] + +pub struct Foo; + +impl Foo { + pub fn bar() -> Foo { + Foo + } +} + +fn main() {} diff --git a/src/tools/clippy/tests/ui-cargo/cargo_rust_version/fail_both_same/src/main.stderr b/src/tools/clippy/tests/ui-cargo/cargo_rust_version/fail_both_same/src/main.stderr new file mode 100644 index 00000000000..a280e1bacdf --- /dev/null +++ b/src/tools/clippy/tests/ui-cargo/cargo_rust_version/fail_both_same/src/main.stderr @@ -0,0 +1,14 @@ +error: unnecessary structure name repetition + --> $DIR/main.rs:6:21 + | +LL | pub fn bar() -> Foo { + | ^^^ help: use the applicable keyword: `Self` + | +note: the lint level is defined here + --> $DIR/main.rs:1:9 + | +LL | #![deny(clippy::use_self)] + | ^^^^^^^^^^^^^^^^ + +error: aborting due to previous error + diff --git a/src/tools/clippy/tests/ui-cargo/cargo_rust_version/fail_cargo/Cargo.toml b/src/tools/clippy/tests/ui-cargo/cargo_rust_version/fail_cargo/Cargo.toml new file mode 100644 index 00000000000..36a53bd829d --- /dev/null +++ b/src/tools/clippy/tests/ui-cargo/cargo_rust_version/fail_cargo/Cargo.toml @@ -0,0 +1,8 @@ +[package] +name = "fail-cargo" +version = "0.1.0" +rust-version = "1.56.1" + +# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html + +[dependencies] diff --git a/src/tools/clippy/tests/ui-cargo/cargo_rust_version/fail_cargo/src/main.rs b/src/tools/clippy/tests/ui-cargo/cargo_rust_version/fail_cargo/src/main.rs new file mode 100644 index 00000000000..5b91d550867 --- /dev/null +++ b/src/tools/clippy/tests/ui-cargo/cargo_rust_version/fail_cargo/src/main.rs @@ -0,0 +1,11 @@ +#![deny(clippy::use_self)] + +pub struct Foo; + +impl Foo { + pub fn bar() -> Foo { + Foo + } +} + +fn main() {} diff --git a/src/tools/clippy/tests/ui-cargo/cargo_rust_version/fail_cargo/src/main.stderr b/src/tools/clippy/tests/ui-cargo/cargo_rust_version/fail_cargo/src/main.stderr new file mode 100644 index 00000000000..a280e1bacdf --- /dev/null +++ b/src/tools/clippy/tests/ui-cargo/cargo_rust_version/fail_cargo/src/main.stderr @@ -0,0 +1,14 @@ +error: unnecessary structure name repetition + --> $DIR/main.rs:6:21 + | +LL | pub fn bar() -> Foo { + | ^^^ help: use the applicable keyword: `Self` + | +note: the lint level is defined here + --> $DIR/main.rs:1:9 + | +LL | #![deny(clippy::use_self)] + | ^^^^^^^^^^^^^^^^ + +error: aborting due to previous error + diff --git a/src/tools/clippy/tests/ui-cargo/cargo_rust_version/fail_clippy/Cargo.toml b/src/tools/clippy/tests/ui-cargo/cargo_rust_version/fail_clippy/Cargo.toml new file mode 100644 index 00000000000..9f644a1a39a --- /dev/null +++ b/src/tools/clippy/tests/ui-cargo/cargo_rust_version/fail_clippy/Cargo.toml @@ -0,0 +1,7 @@ +[package] +name = "fail-clippy" +version = "0.1.0" + +# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html + +[dependencies] diff --git a/src/tools/clippy/tests/ui-cargo/cargo_rust_version/fail_clippy/clippy.toml b/src/tools/clippy/tests/ui-cargo/cargo_rust_version/fail_clippy/clippy.toml new file mode 100644 index 00000000000..ddbdbc1fa25 --- /dev/null +++ b/src/tools/clippy/tests/ui-cargo/cargo_rust_version/fail_clippy/clippy.toml @@ -0,0 +1 @@ +msrv = "1.58" diff --git a/src/tools/clippy/tests/ui-cargo/cargo_rust_version/fail_clippy/src/main.rs b/src/tools/clippy/tests/ui-cargo/cargo_rust_version/fail_clippy/src/main.rs new file mode 100644 index 00000000000..5b91d550867 --- /dev/null +++ b/src/tools/clippy/tests/ui-cargo/cargo_rust_version/fail_clippy/src/main.rs @@ -0,0 +1,11 @@ +#![deny(clippy::use_self)] + +pub struct Foo; + +impl Foo { + pub fn bar() -> Foo { + Foo + } +} + +fn main() {} diff --git a/src/tools/clippy/tests/ui-cargo/cargo_rust_version/fail_clippy/src/main.stderr b/src/tools/clippy/tests/ui-cargo/cargo_rust_version/fail_clippy/src/main.stderr new file mode 100644 index 00000000000..a280e1bacdf --- /dev/null +++ b/src/tools/clippy/tests/ui-cargo/cargo_rust_version/fail_clippy/src/main.stderr @@ -0,0 +1,14 @@ +error: unnecessary structure name repetition + --> $DIR/main.rs:6:21 + | +LL | pub fn bar() -> Foo { + | ^^^ help: use the applicable keyword: `Self` + | +note: the lint level is defined here + --> $DIR/main.rs:1:9 + | +LL | #![deny(clippy::use_self)] + | ^^^^^^^^^^^^^^^^ + +error: aborting due to previous error + diff --git a/src/tools/clippy/tests/ui-cargo/cargo_rust_version/fail_file_attr/Cargo.toml b/src/tools/clippy/tests/ui-cargo/cargo_rust_version/fail_file_attr/Cargo.toml new file mode 100644 index 00000000000..5380e993b29 --- /dev/null +++ b/src/tools/clippy/tests/ui-cargo/cargo_rust_version/fail_file_attr/Cargo.toml @@ -0,0 +1,8 @@ +[package] +name = "fail-file-attr" +version = "0.1.0" +rust-version = "1.13" + +# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html + +[dependencies] diff --git a/src/tools/clippy/tests/ui-cargo/cargo_rust_version/fail_file_attr/clippy.toml b/src/tools/clippy/tests/ui-cargo/cargo_rust_version/fail_file_attr/clippy.toml new file mode 100644 index 00000000000..ea5d806594b --- /dev/null +++ b/src/tools/clippy/tests/ui-cargo/cargo_rust_version/fail_file_attr/clippy.toml @@ -0,0 +1 @@ +msrv = "1.13.0" diff --git a/src/tools/clippy/tests/ui-cargo/cargo_rust_version/fail_file_attr/src/main.rs b/src/tools/clippy/tests/ui-cargo/cargo_rust_version/fail_file_attr/src/main.rs new file mode 100644 index 00000000000..bcbffa82a54 --- /dev/null +++ b/src/tools/clippy/tests/ui-cargo/cargo_rust_version/fail_file_attr/src/main.rs @@ -0,0 +1,16 @@ +// FIXME: this should produce a warning, because the attribute says 1.58 and the cargo.toml file +// says 1.13 + +#![feature(custom_inner_attributes)] +#![clippy::msrv = "1.58.0"] +#![deny(clippy::use_self)] + +pub struct Foo; + +impl Foo { + pub fn bar() -> Foo { + Foo + } +} + +fn main() {} diff --git a/src/tools/clippy/tests/ui-cargo/cargo_rust_version/fail_file_attr/src/main.stderr b/src/tools/clippy/tests/ui-cargo/cargo_rust_version/fail_file_attr/src/main.stderr new file mode 100644 index 00000000000..88f6e00922b --- /dev/null +++ b/src/tools/clippy/tests/ui-cargo/cargo_rust_version/fail_file_attr/src/main.stderr @@ -0,0 +1,14 @@ +error: unnecessary structure name repetition + --> $DIR/main.rs:11:21 + | +LL | pub fn bar() -> Foo { + | ^^^ help: use the applicable keyword: `Self` + | +note: the lint level is defined here + --> $DIR/main.rs:6:9 + | +LL | #![deny(clippy::use_self)] + | ^^^^^^^^^^^^^^^^ + +error: aborting due to previous error + diff --git a/src/tools/clippy/tests/ui-cargo/cargo_rust_version/pass_both_same/Cargo.toml b/src/tools/clippy/tests/ui-cargo/cargo_rust_version/pass_both_same/Cargo.toml new file mode 100644 index 00000000000..1f9bd8f9a84 --- /dev/null +++ b/src/tools/clippy/tests/ui-cargo/cargo_rust_version/pass_both_same/Cargo.toml @@ -0,0 +1,8 @@ +[package] +name = "fail-both-same" +version = "0.1.0" +rust-version = "1.13.0" + +# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html + +[dependencies] diff --git a/src/tools/clippy/tests/ui-cargo/cargo_rust_version/pass_both_same/clippy.toml b/src/tools/clippy/tests/ui-cargo/cargo_rust_version/pass_both_same/clippy.toml new file mode 100644 index 00000000000..5e8e48b636b --- /dev/null +++ b/src/tools/clippy/tests/ui-cargo/cargo_rust_version/pass_both_same/clippy.toml @@ -0,0 +1 @@ +msrv = "1.13" diff --git a/src/tools/clippy/tests/ui-cargo/cargo_rust_version/pass_both_same/src/main.rs b/src/tools/clippy/tests/ui-cargo/cargo_rust_version/pass_both_same/src/main.rs new file mode 100644 index 00000000000..5b91d550867 --- /dev/null +++ b/src/tools/clippy/tests/ui-cargo/cargo_rust_version/pass_both_same/src/main.rs @@ -0,0 +1,11 @@ +#![deny(clippy::use_self)] + +pub struct Foo; + +impl Foo { + pub fn bar() -> Foo { + Foo + } +} + +fn main() {} diff --git a/src/tools/clippy/tests/ui-cargo/cargo_rust_version/pass_cargo/Cargo.toml b/src/tools/clippy/tests/ui-cargo/cargo_rust_version/pass_cargo/Cargo.toml new file mode 100644 index 00000000000..77538027c0f --- /dev/null +++ b/src/tools/clippy/tests/ui-cargo/cargo_rust_version/pass_cargo/Cargo.toml @@ -0,0 +1,8 @@ +[package] +name = "fail-cargo" +version = "0.1.0" +rust-version = "1.13.0" + +# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html + +[dependencies] diff --git a/src/tools/clippy/tests/ui-cargo/cargo_rust_version/pass_cargo/src/main.rs b/src/tools/clippy/tests/ui-cargo/cargo_rust_version/pass_cargo/src/main.rs new file mode 100644 index 00000000000..5b91d550867 --- /dev/null +++ b/src/tools/clippy/tests/ui-cargo/cargo_rust_version/pass_cargo/src/main.rs @@ -0,0 +1,11 @@ +#![deny(clippy::use_self)] + +pub struct Foo; + +impl Foo { + pub fn bar() -> Foo { + Foo + } +} + +fn main() {} diff --git a/src/tools/clippy/tests/ui-cargo/cargo_rust_version/pass_clippy/Cargo.toml b/src/tools/clippy/tests/ui-cargo/cargo_rust_version/pass_clippy/Cargo.toml new file mode 100644 index 00000000000..9f644a1a39a --- /dev/null +++ b/src/tools/clippy/tests/ui-cargo/cargo_rust_version/pass_clippy/Cargo.toml @@ -0,0 +1,7 @@ +[package] +name = "fail-clippy" +version = "0.1.0" + +# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html + +[dependencies] diff --git a/src/tools/clippy/tests/ui-cargo/cargo_rust_version/pass_clippy/clippy.toml b/src/tools/clippy/tests/ui-cargo/cargo_rust_version/pass_clippy/clippy.toml new file mode 100644 index 00000000000..5e8e48b636b --- /dev/null +++ b/src/tools/clippy/tests/ui-cargo/cargo_rust_version/pass_clippy/clippy.toml @@ -0,0 +1 @@ +msrv = "1.13" diff --git a/src/tools/clippy/tests/ui-cargo/cargo_rust_version/pass_clippy/src/main.rs b/src/tools/clippy/tests/ui-cargo/cargo_rust_version/pass_clippy/src/main.rs new file mode 100644 index 00000000000..5b91d550867 --- /dev/null +++ b/src/tools/clippy/tests/ui-cargo/cargo_rust_version/pass_clippy/src/main.rs @@ -0,0 +1,11 @@ +#![deny(clippy::use_self)] + +pub struct Foo; + +impl Foo { + pub fn bar() -> Foo { + Foo + } +} + +fn main() {} diff --git a/src/tools/clippy/tests/ui-cargo/cargo_rust_version/pass_file_attr/Cargo.toml b/src/tools/clippy/tests/ui-cargo/cargo_rust_version/pass_file_attr/Cargo.toml new file mode 100644 index 00000000000..f0387cd90b8 --- /dev/null +++ b/src/tools/clippy/tests/ui-cargo/cargo_rust_version/pass_file_attr/Cargo.toml @@ -0,0 +1,8 @@ +[package] +name = "fail-file-attr" +version = "0.1.0" +rust-version = "1.59" + +# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html + +[dependencies] diff --git a/src/tools/clippy/tests/ui-cargo/cargo_rust_version/pass_file_attr/src/main.rs b/src/tools/clippy/tests/ui-cargo/cargo_rust_version/pass_file_attr/src/main.rs new file mode 100644 index 00000000000..27fe4771d2d --- /dev/null +++ b/src/tools/clippy/tests/ui-cargo/cargo_rust_version/pass_file_attr/src/main.rs @@ -0,0 +1,13 @@ +#![feature(custom_inner_attributes)] +#![clippy::msrv = "1.13.0"] +#![deny(clippy::use_self)] + +pub struct Foo; + +impl Foo { + pub fn bar() -> Foo { + Foo + } +} + +fn main() {} diff --git a/src/tools/clippy/tests/ui-cargo/cargo_rust_version/warn_both_diff/Cargo.toml b/src/tools/clippy/tests/ui-cargo/cargo_rust_version/warn_both_diff/Cargo.toml new file mode 100644 index 00000000000..a19d5b33fe5 --- /dev/null +++ b/src/tools/clippy/tests/ui-cargo/cargo_rust_version/warn_both_diff/Cargo.toml @@ -0,0 +1,8 @@ +[package] +name = "warn-both-diff" +version = "0.1.0" +rust-version = "1.56.0" + +# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html + +[dependencies] diff --git a/src/tools/clippy/tests/ui-cargo/cargo_rust_version/warn_both_diff/clippy.toml b/src/tools/clippy/tests/ui-cargo/cargo_rust_version/warn_both_diff/clippy.toml new file mode 100644 index 00000000000..5e8e48b636b --- /dev/null +++ b/src/tools/clippy/tests/ui-cargo/cargo_rust_version/warn_both_diff/clippy.toml @@ -0,0 +1 @@ +msrv = "1.13" diff --git a/src/tools/clippy/tests/ui-cargo/cargo_rust_version/warn_both_diff/src/main.rs b/src/tools/clippy/tests/ui-cargo/cargo_rust_version/warn_both_diff/src/main.rs new file mode 100644 index 00000000000..5b91d550867 --- /dev/null +++ b/src/tools/clippy/tests/ui-cargo/cargo_rust_version/warn_both_diff/src/main.rs @@ -0,0 +1,11 @@ +#![deny(clippy::use_self)] + +pub struct Foo; + +impl Foo { + pub fn bar() -> Foo { + Foo + } +} + +fn main() {} diff --git a/src/tools/clippy/tests/ui-cargo/cargo_rust_version/warn_both_diff/src/main.stderr b/src/tools/clippy/tests/ui-cargo/cargo_rust_version/warn_both_diff/src/main.stderr new file mode 100644 index 00000000000..eeae5b7b275 --- /dev/null +++ b/src/tools/clippy/tests/ui-cargo/cargo_rust_version/warn_both_diff/src/main.stderr @@ -0,0 +1,4 @@ +warning: the MSRV in `clippy.toml` and `Cargo.toml` differ; using `1.13.0` from `clippy.toml` + +warning: 1 warning emitted + diff --git a/src/tools/clippy/tests/ui-cargo/multiple_config_files/warn/src/main.stderr b/src/tools/clippy/tests/ui-cargo/multiple_config_files/warn/src/main.stderr index 2abb4e3e06e..98697e001f9 100644 --- a/src/tools/clippy/tests/ui-cargo/multiple_config_files/warn/src/main.stderr +++ b/src/tools/clippy/tests/ui-cargo/multiple_config_files/warn/src/main.stderr @@ -1,2 +1,2 @@ -Using config file `$SRC_DIR/tests/ui-cargo/multiple_config_files/warn/.clippy.toml` -Warning: `$SRC_DIR/tests/ui-cargo/multiple_config_files/warn/clippy.toml` will be ignored. +Using config file `$SRC_DIR/.clippy.toml` +Warning: `$SRC_DIR/clippy.toml` will be ignored. diff --git a/src/tools/clippy/tests/ui-internal/collapsible_span_lint_calls.fixed b/src/tools/clippy/tests/ui-internal/collapsible_span_lint_calls.fixed index a5a6f20ddd5..9f299d7dec7 100644 --- a/src/tools/clippy/tests/ui-internal/collapsible_span_lint_calls.fixed +++ b/src/tools/clippy/tests/ui-internal/collapsible_span_lint_calls.fixed @@ -45,7 +45,12 @@ impl EarlyLintPass for Pass { if predicate { db.note(note_msg); } - }) + }); + + // Issue #8798 + span_lint_and_then(cx, TEST_LINT, expr.span, lint_msg, |db| { + db.help(help_msg).help(help_msg); + }); } } diff --git a/src/tools/clippy/tests/ui-internal/collapsible_span_lint_calls.rs b/src/tools/clippy/tests/ui-internal/collapsible_span_lint_calls.rs index 6d783aa0786..2b113f555e4 100644 --- a/src/tools/clippy/tests/ui-internal/collapsible_span_lint_calls.rs +++ b/src/tools/clippy/tests/ui-internal/collapsible_span_lint_calls.rs @@ -55,7 +55,12 @@ impl EarlyLintPass for Pass { if predicate { db.note(note_msg); } - }) + }); + + // Issue #8798 + span_lint_and_then(cx, TEST_LINT, expr.span, lint_msg, |db| { + db.help(help_msg).help(help_msg); + }); } } diff --git a/src/tools/clippy/tests/ui-internal/default_deprecation_reason.rs b/src/tools/clippy/tests/ui-internal/default_deprecation_reason.rs new file mode 100644 index 00000000000..c8961d5e1f0 --- /dev/null +++ b/src/tools/clippy/tests/ui-internal/default_deprecation_reason.rs @@ -0,0 +1,30 @@ +#![deny(clippy::internal)] +#![feature(rustc_private)] + +#[macro_use] +extern crate clippy_lints; +use clippy_lints::deprecated_lints::ClippyDeprecatedLint; + +declare_deprecated_lint! { + /// ### What it does + /// Nothing. This lint has been deprecated. + /// + /// ### Deprecation reason + /// TODO + #[clippy::version = "1.63.0"] + pub COOL_LINT_DEFAULT, + "default deprecation note" +} + +declare_deprecated_lint! { + /// ### What it does + /// Nothing. This lint has been deprecated. + /// + /// ### Deprecation reason + /// This lint has been replaced by `cooler_lint` + #[clippy::version = "1.63.0"] + pub COOL_LINT, + "this lint has been replaced by `cooler_lint`" +} + +fn main() {} diff --git a/src/tools/clippy/tests/ui-internal/default_deprecation_reason.stderr b/src/tools/clippy/tests/ui-internal/default_deprecation_reason.stderr new file mode 100644 index 00000000000..ca26b649f98 --- /dev/null +++ b/src/tools/clippy/tests/ui-internal/default_deprecation_reason.stderr @@ -0,0 +1,22 @@ +error: the lint `COOL_LINT_DEFAULT` has the default deprecation reason + --> $DIR/default_deprecation_reason.rs:8:1 + | +LL | / declare_deprecated_lint! { +LL | | /// ### What it does +LL | | /// Nothing. This lint has been deprecated. +LL | | /// +... | +LL | | "default deprecation note" +LL | | } + | |_^ + | +note: the lint level is defined here + --> $DIR/default_deprecation_reason.rs:1:9 + | +LL | #![deny(clippy::internal)] + | ^^^^^^^^^^^^^^^^ + = note: `#[deny(clippy::default_deprecation_reason)]` implied by `#[deny(clippy::internal)]` + = note: this error originates in the macro `declare_deprecated_lint` (in Nightly builds, run with -Z macro-backtrace for more info) + +error: aborting due to previous error + diff --git a/src/tools/clippy/tests/ui/auxiliary/macro_rules.rs b/src/tools/clippy/tests/ui/auxiliary/macro_rules.rs index 9f283337c7e..5bd2c2799f0 100644 --- a/src/tools/clippy/tests/ui/auxiliary/macro_rules.rs +++ b/src/tools/clippy/tests/ui/auxiliary/macro_rules.rs @@ -127,3 +127,11 @@ macro_rules! ptr_as_ptr_cast { $ptr as *const i32 }; } + +#[macro_export] +macro_rules! manual_rem_euclid { + () => { + let value: i32 = 5; + let _: i32 = ((value % 4) + 4) % 4; + }; +} diff --git a/src/tools/clippy/tests/ui/auxiliary/proc_macro_derive.rs b/src/tools/clippy/tests/ui/auxiliary/proc_macro_derive.rs index ed7b17651e6..a89a06308d0 100644 --- a/src/tools/clippy/tests/ui/auxiliary/proc_macro_derive.rs +++ b/src/tools/clippy/tests/ui/auxiliary/proc_macro_derive.rs @@ -72,3 +72,17 @@ pub fn mini_macro(_: TokenStream) -> TokenStream { } ) } + +#[proc_macro_derive(ExtraLifetimeDerive)] +#[allow(unused)] +pub fn extra_lifetime(_input: TokenStream) -> TokenStream { + quote!( + pub struct ExtraLifetime; + + impl<'b> ExtraLifetime { + pub fn something<'c>() -> Self { + Self + } + } + ) +} diff --git a/src/tools/clippy/tests/ui/escape_analysis.rs b/src/tools/clippy/tests/ui/boxed_local.rs index 13e2b6c7a2e..4639f00a8d8 100644 --- a/src/tools/clippy/tests/ui/escape_analysis.rs +++ b/src/tools/clippy/tests/ui/boxed_local.rs @@ -1,4 +1,5 @@ #![feature(box_syntax)] +#![feature(lint_reasons)] #![allow( clippy::borrowed_box, clippy::needless_pass_by_value, @@ -202,3 +203,7 @@ mod issue4804 { fn foo(x: Box<u32>) {} } } + +fn check_expect(#[expect(clippy::boxed_local)] x: Box<A>) { + x.foo(); +} diff --git a/src/tools/clippy/tests/ui/escape_analysis.stderr b/src/tools/clippy/tests/ui/boxed_local.stderr index 4a82b4419f9..9036529f39c 100644 --- a/src/tools/clippy/tests/ui/escape_analysis.stderr +++ b/src/tools/clippy/tests/ui/boxed_local.stderr @@ -1,5 +1,5 @@ error: local variable doesn't need to be boxed here - --> $DIR/escape_analysis.rs:40:13 + --> $DIR/boxed_local.rs:41:13 | LL | fn warn_arg(x: Box<A>) { | ^ @@ -7,19 +7,19 @@ LL | fn warn_arg(x: Box<A>) { = note: `-D clippy::boxed-local` implied by `-D warnings` error: local variable doesn't need to be boxed here - --> $DIR/escape_analysis.rs:131:12 + --> $DIR/boxed_local.rs:132:12 | LL | pub fn new(_needs_name: Box<PeekableSeekable<&()>>) -> () {} | ^^^^^^^^^^^ error: local variable doesn't need to be boxed here - --> $DIR/escape_analysis.rs:195:44 + --> $DIR/boxed_local.rs:196:44 | LL | fn default_impl_x(self: Box<Self>, x: Box<u32>) -> u32 { | ^ error: local variable doesn't need to be boxed here - --> $DIR/escape_analysis.rs:202:16 + --> $DIR/boxed_local.rs:203:16 | LL | fn foo(x: Box<u32>) {} | ^ diff --git a/src/tools/clippy/tests/ui/checked_unwrap/simple_conditionals.rs b/src/tools/clippy/tests/ui/checked_unwrap/simple_conditionals.rs index ee3fdfabe9d..82dce81979f 100644 --- a/src/tools/clippy/tests/ui/checked_unwrap/simple_conditionals.rs +++ b/src/tools/clippy/tests/ui/checked_unwrap/simple_conditionals.rs @@ -1,3 +1,4 @@ +#![feature(lint_reasons)] #![deny(clippy::panicking_unwrap, clippy::unnecessary_unwrap)] #![allow(clippy::if_same_then_else, clippy::branches_sharing_code)] @@ -84,3 +85,18 @@ fn main() { assert!(x.is_ok(), "{:?}", x.unwrap_err()); // ok, it's a common test pattern } + +fn check_expect() { + let x = Some(()); + if x.is_some() { + #[expect(clippy::unnecessary_unwrap)] + x.unwrap(); // unnecessary + #[expect(clippy::unnecessary_unwrap)] + x.expect("an error message"); // unnecessary + } else { + #[expect(clippy::panicking_unwrap)] + x.unwrap(); // will panic + #[expect(clippy::panicking_unwrap)] + x.expect("an error message"); // will panic + } +} diff --git a/src/tools/clippy/tests/ui/checked_unwrap/simple_conditionals.stderr b/src/tools/clippy/tests/ui/checked_unwrap/simple_conditionals.stderr index 34131592802..ef688274222 100644 --- a/src/tools/clippy/tests/ui/checked_unwrap/simple_conditionals.stderr +++ b/src/tools/clippy/tests/ui/checked_unwrap/simple_conditionals.stderr @@ -1,5 +1,5 @@ error: called `unwrap` on `x` after checking its variant with `is_some` - --> $DIR/simple_conditionals.rs:39:9 + --> $DIR/simple_conditionals.rs:40:9 | LL | if x.is_some() { | -------------- help: try: `if let Some(..) = x` @@ -7,13 +7,13 @@ LL | x.unwrap(); // unnecessary | ^^^^^^^^^^ | note: the lint level is defined here - --> $DIR/simple_conditionals.rs:1:35 + --> $DIR/simple_conditionals.rs:2:35 | LL | #![deny(clippy::panicking_unwrap, clippy::unnecessary_unwrap)] | ^^^^^^^^^^^^^^^^^^^^^^^^^^ error: called `expect` on `x` after checking its variant with `is_some` - --> $DIR/simple_conditionals.rs:40:9 + --> $DIR/simple_conditionals.rs:41:9 | LL | if x.is_some() { | -------------- help: try: `if let Some(..) = x` @@ -22,7 +22,7 @@ LL | x.expect("an error message"); // unnecessary | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ error: this call to `unwrap()` will always panic - --> $DIR/simple_conditionals.rs:42:9 + --> $DIR/simple_conditionals.rs:43:9 | LL | if x.is_some() { | ----------- because of this check @@ -31,13 +31,13 @@ LL | x.unwrap(); // will panic | ^^^^^^^^^^ | note: the lint level is defined here - --> $DIR/simple_conditionals.rs:1:9 + --> $DIR/simple_conditionals.rs:2:9 | LL | #![deny(clippy::panicking_unwrap, clippy::unnecessary_unwrap)] | ^^^^^^^^^^^^^^^^^^^^^^^^ error: this call to `expect()` will always panic - --> $DIR/simple_conditionals.rs:43:9 + --> $DIR/simple_conditionals.rs:44:9 | LL | if x.is_some() { | ----------- because of this check @@ -46,7 +46,7 @@ LL | x.expect("an error message"); // will panic | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ error: this call to `unwrap()` will always panic - --> $DIR/simple_conditionals.rs:46:9 + --> $DIR/simple_conditionals.rs:47:9 | LL | if x.is_none() { | ----------- because of this check @@ -54,7 +54,7 @@ LL | x.unwrap(); // will panic | ^^^^^^^^^^ error: called `unwrap` on `x` after checking its variant with `is_none` - --> $DIR/simple_conditionals.rs:48:9 + --> $DIR/simple_conditionals.rs:49:9 | LL | if x.is_none() { | -------------- help: try: `if let Some(..) = x` @@ -63,7 +63,7 @@ LL | x.unwrap(); // unnecessary | ^^^^^^^^^^ error: called `unwrap` on `x` after checking its variant with `is_some` - --> $DIR/simple_conditionals.rs:7:13 + --> $DIR/simple_conditionals.rs:8:13 | LL | if $a.is_some() { | --------------- help: try: `if let Some(..) = x` @@ -76,7 +76,7 @@ LL | m!(x); = note: this error originates in the macro `m` (in Nightly builds, run with -Z macro-backtrace for more info) error: called `unwrap` on `x` after checking its variant with `is_ok` - --> $DIR/simple_conditionals.rs:56:9 + --> $DIR/simple_conditionals.rs:57:9 | LL | if x.is_ok() { | ------------ help: try: `if let Ok(..) = x` @@ -84,7 +84,7 @@ LL | x.unwrap(); // unnecessary | ^^^^^^^^^^ error: called `expect` on `x` after checking its variant with `is_ok` - --> $DIR/simple_conditionals.rs:57:9 + --> $DIR/simple_conditionals.rs:58:9 | LL | if x.is_ok() { | ------------ help: try: `if let Ok(..) = x` @@ -93,7 +93,7 @@ LL | x.expect("an error message"); // unnecessary | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ error: this call to `unwrap_err()` will always panic - --> $DIR/simple_conditionals.rs:58:9 + --> $DIR/simple_conditionals.rs:59:9 | LL | if x.is_ok() { | --------- because of this check @@ -102,7 +102,7 @@ LL | x.unwrap_err(); // will panic | ^^^^^^^^^^^^^^ error: this call to `unwrap()` will always panic - --> $DIR/simple_conditionals.rs:60:9 + --> $DIR/simple_conditionals.rs:61:9 | LL | if x.is_ok() { | --------- because of this check @@ -111,7 +111,7 @@ LL | x.unwrap(); // will panic | ^^^^^^^^^^ error: this call to `expect()` will always panic - --> $DIR/simple_conditionals.rs:61:9 + --> $DIR/simple_conditionals.rs:62:9 | LL | if x.is_ok() { | --------- because of this check @@ -120,7 +120,7 @@ LL | x.expect("an error message"); // will panic | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ error: called `unwrap_err` on `x` after checking its variant with `is_ok` - --> $DIR/simple_conditionals.rs:62:9 + --> $DIR/simple_conditionals.rs:63:9 | LL | if x.is_ok() { | ------------ help: try: `if let Err(..) = x` @@ -129,7 +129,7 @@ LL | x.unwrap_err(); // unnecessary | ^^^^^^^^^^^^^^ error: this call to `unwrap()` will always panic - --> $DIR/simple_conditionals.rs:65:9 + --> $DIR/simple_conditionals.rs:66:9 | LL | if x.is_err() { | ---------- because of this check @@ -137,7 +137,7 @@ LL | x.unwrap(); // will panic | ^^^^^^^^^^ error: called `unwrap_err` on `x` after checking its variant with `is_err` - --> $DIR/simple_conditionals.rs:66:9 + --> $DIR/simple_conditionals.rs:67:9 | LL | if x.is_err() { | ------------- help: try: `if let Err(..) = x` @@ -146,7 +146,7 @@ LL | x.unwrap_err(); // unnecessary | ^^^^^^^^^^^^^^ error: called `unwrap` on `x` after checking its variant with `is_err` - --> $DIR/simple_conditionals.rs:68:9 + --> $DIR/simple_conditionals.rs:69:9 | LL | if x.is_err() { | ------------- help: try: `if let Ok(..) = x` @@ -155,7 +155,7 @@ LL | x.unwrap(); // unnecessary | ^^^^^^^^^^ error: this call to `unwrap_err()` will always panic - --> $DIR/simple_conditionals.rs:69:9 + --> $DIR/simple_conditionals.rs:70:9 | LL | if x.is_err() { | ---------- because of this check diff --git a/src/tools/clippy/tests/ui/crashes/ice-6252.stderr b/src/tools/clippy/tests/ui/crashes/ice-6252.stderr index d930d486fde..a6a767483ed 100644 --- a/src/tools/clippy/tests/ui/crashes/ice-6252.stderr +++ b/src/tools/clippy/tests/ui/crashes/ice-6252.stderr @@ -25,7 +25,7 @@ error[E0046]: not all trait items implemented, missing: `VAL` --> $DIR/ice-6252.rs:10:1 | LL | const VAL: T; - | ------------- `VAL` from trait + | ------------ `VAL` from trait ... LL | impl<N, M> TypeVal<usize> for Multiply<N, M> where N: TypeVal<VAL> {} | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ missing `VAL` in implementation diff --git a/src/tools/clippy/tests/ui/declare_interior_mutable_const/others.rs b/src/tools/clippy/tests/ui/declare_interior_mutable_const/others.rs index 48c5e9537d6..62af545db50 100644 --- a/src/tools/clippy/tests/ui/declare_interior_mutable_const/others.rs +++ b/src/tools/clippy/tests/ui/declare_interior_mutable_const/others.rs @@ -31,4 +31,9 @@ const NO_ANN: &dyn Display = &70; static STATIC_TUPLE: (AtomicUsize, String) = (ATOMIC, STRING); //^ there should be no lints on this line +// issue #8493 +thread_local! { + static THREAD_LOCAL: Cell<i32> = const { Cell::new(0) }; +} + fn main() {} diff --git a/src/tools/clippy/tests/ui/default_instead_of_iter_empty.fixed b/src/tools/clippy/tests/ui/default_instead_of_iter_empty.fixed new file mode 100644 index 00000000000..f1abfdcd6ce --- /dev/null +++ b/src/tools/clippy/tests/ui/default_instead_of_iter_empty.fixed @@ -0,0 +1,21 @@ +// run-rustfix +#![warn(clippy::default_instead_of_iter_empty)] +#![allow(dead_code)] +use std::collections::HashMap; + +#[derive(Default)] +struct Iter { + iter: std::iter::Empty<usize>, +} + +fn main() { + // Do lint. + let _ = std::iter::empty::<usize>(); + let _ = std::iter::empty::<HashMap<usize, usize>>(); + let _foo: std::iter::Empty<usize> = std::iter::empty(); + + // Do not lint. + let _ = Vec::<usize>::default(); + let _ = String::default(); + let _ = Iter::default(); +} diff --git a/src/tools/clippy/tests/ui/default_instead_of_iter_empty.rs b/src/tools/clippy/tests/ui/default_instead_of_iter_empty.rs new file mode 100644 index 00000000000..2630519c46d --- /dev/null +++ b/src/tools/clippy/tests/ui/default_instead_of_iter_empty.rs @@ -0,0 +1,21 @@ +// run-rustfix +#![warn(clippy::default_instead_of_iter_empty)] +#![allow(dead_code)] +use std::collections::HashMap; + +#[derive(Default)] +struct Iter { + iter: std::iter::Empty<usize>, +} + +fn main() { + // Do lint. + let _ = std::iter::Empty::<usize>::default(); + let _ = std::iter::Empty::<HashMap<usize, usize>>::default(); + let _foo: std::iter::Empty<usize> = std::iter::Empty::default(); + + // Do not lint. + let _ = Vec::<usize>::default(); + let _ = String::default(); + let _ = Iter::default(); +} diff --git a/src/tools/clippy/tests/ui/default_instead_of_iter_empty.stderr b/src/tools/clippy/tests/ui/default_instead_of_iter_empty.stderr new file mode 100644 index 00000000000..460fc84def8 --- /dev/null +++ b/src/tools/clippy/tests/ui/default_instead_of_iter_empty.stderr @@ -0,0 +1,22 @@ +error: `std::iter::empty()` is the more idiomatic way + --> $DIR/default_instead_of_iter_empty.rs:13:13 + | +LL | let _ = std::iter::Empty::<usize>::default(); + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `std::iter::empty::<usize>()` + | + = note: `-D clippy::default-instead-of-iter-empty` implied by `-D warnings` + +error: `std::iter::empty()` is the more idiomatic way + --> $DIR/default_instead_of_iter_empty.rs:14:13 + | +LL | let _ = std::iter::Empty::<HashMap<usize, usize>>::default(); + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `std::iter::empty::<HashMap<usize, usize>>()` + +error: `std::iter::empty()` is the more idiomatic way + --> $DIR/default_instead_of_iter_empty.rs:15:41 + | +LL | let _foo: std::iter::Empty<usize> = std::iter::Empty::default(); + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `std::iter::empty()` + +error: aborting due to 3 previous errors + diff --git a/src/tools/clippy/tests/ui/derive_hash_xor_eq.stderr b/src/tools/clippy/tests/ui/derive_hash_xor_eq.stderr index e5184bd1407..2a4abb0c519 100644 --- a/src/tools/clippy/tests/ui/derive_hash_xor_eq.stderr +++ b/src/tools/clippy/tests/ui/derive_hash_xor_eq.stderr @@ -8,12 +8,8 @@ LL | #[derive(Hash)] note: `PartialEq` implemented here --> $DIR/derive_hash_xor_eq.rs:15:1 | -LL | / impl PartialEq for Bar { -LL | | fn eq(&self, _: &Bar) -> bool { -LL | | true -LL | | } -LL | | } - | |_^ +LL | impl PartialEq for Bar { + | ^^^^^^^^^^^^^^^^^^^^^^ = note: this error originates in the derive macro `Hash` (in Nightly builds, run with -Z macro-backtrace for more info) error: you are deriving `Hash` but have implemented `PartialEq` explicitly @@ -25,12 +21,8 @@ LL | #[derive(Hash)] note: `PartialEq` implemented here --> $DIR/derive_hash_xor_eq.rs:24:1 | -LL | / impl PartialEq<Baz> for Baz { -LL | | fn eq(&self, _: &Baz) -> bool { -LL | | true -LL | | } -LL | | } - | |_^ +LL | impl PartialEq<Baz> for Baz { + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^ = note: this error originates in the derive macro `Hash` (in Nightly builds, run with -Z macro-backtrace for more info) error: you are implementing `Hash` explicitly but have derived `PartialEq` diff --git a/src/tools/clippy/tests/ui/derive_ord_xor_partial_ord.stderr b/src/tools/clippy/tests/ui/derive_ord_xor_partial_ord.stderr index 32896c99dad..baf8341aba9 100644 --- a/src/tools/clippy/tests/ui/derive_ord_xor_partial_ord.stderr +++ b/src/tools/clippy/tests/ui/derive_ord_xor_partial_ord.stderr @@ -8,12 +8,8 @@ LL | #[derive(Ord, PartialEq, Eq)] note: `PartialOrd` implemented here --> $DIR/derive_ord_xor_partial_ord.rs:24:1 | -LL | / impl PartialOrd for DeriveOrd { -LL | | fn partial_cmp(&self, other: &Self) -> Option<Ordering> { -LL | | Some(other.cmp(self)) -LL | | } -LL | | } - | |_^ +LL | impl PartialOrd for DeriveOrd { + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ = note: this error originates in the derive macro `Ord` (in Nightly builds, run with -Z macro-backtrace for more info) error: you are deriving `Ord` but have implemented `PartialOrd` explicitly @@ -25,12 +21,8 @@ LL | #[derive(Ord, PartialEq, Eq)] note: `PartialOrd` implemented here --> $DIR/derive_ord_xor_partial_ord.rs:33:1 | -LL | / impl PartialOrd<DeriveOrdWithExplicitTypeVariable> for DeriveOrdWithExplicitTypeVariable { -LL | | fn partial_cmp(&self, other: &Self) -> Option<Ordering> { -LL | | Some(other.cmp(self)) -LL | | } -LL | | } - | |_^ +LL | impl PartialOrd<DeriveOrdWithExplicitTypeVariable> for DeriveOrdWithExplicitTypeVariable { + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ = note: this error originates in the derive macro `Ord` (in Nightly builds, run with -Z macro-backtrace for more info) error: you are implementing `Ord` explicitly but have derived `PartialOrd` diff --git a/src/tools/clippy/tests/ui/enum_variants.rs b/src/tools/clippy/tests/ui/enum_variants.rs index b2bf7c4e360..efed12ee2ef 100644 --- a/src/tools/clippy/tests/ui/enum_variants.rs +++ b/src/tools/clippy/tests/ui/enum_variants.rs @@ -158,4 +158,25 @@ enum Phase { PostLookup, } +mod issue9018 { + enum DoLint { + _TypeCreate, + _TypeRead, + _TypeUpdate, + _TypeDestroy, + } + + enum DoLintToo { + _CreateType, + _UpdateType, + _DeleteType, + } + + enum DoNotLint { + _Foo, + _Bar, + _Baz, + } +} + fn main() {} diff --git a/src/tools/clippy/tests/ui/enum_variants.stderr b/src/tools/clippy/tests/ui/enum_variants.stderr index 8a3265086e8..7342aff80f0 100644 --- a/src/tools/clippy/tests/ui/enum_variants.stderr +++ b/src/tools/clippy/tests/ui/enum_variants.stderr @@ -120,5 +120,30 @@ LL | | } | = help: remove the postfixes and use full paths to the variants instead of glob imports -error: aborting due to 12 previous errors +error: all variants have the same prefix: `_Type` + --> $DIR/enum_variants.rs:162:5 + | +LL | / enum DoLint { +LL | | _TypeCreate, +LL | | _TypeRead, +LL | | _TypeUpdate, +LL | | _TypeDestroy, +LL | | } + | |_____^ + | + = help: remove the prefixes and use full paths to the variants instead of glob imports + +error: all variants have the same postfix: `Type` + --> $DIR/enum_variants.rs:169:5 + | +LL | / enum DoLintToo { +LL | | _CreateType, +LL | | _UpdateType, +LL | | _DeleteType, +LL | | } + | |_____^ + | + = help: remove the postfixes and use full paths to the variants instead of glob imports + +error: aborting due to 14 previous errors diff --git a/src/tools/clippy/tests/ui/explicit_auto_deref.fixed b/src/tools/clippy/tests/ui/explicit_auto_deref.fixed new file mode 100644 index 00000000000..d4ff1b1566d --- /dev/null +++ b/src/tools/clippy/tests/ui/explicit_auto_deref.fixed @@ -0,0 +1,214 @@ +// run-rustfix + +#![warn(clippy::explicit_auto_deref)] +#![allow( + dead_code, + unused_braces, + clippy::borrowed_box, + clippy::needless_borrow, + clippy::needless_return, + clippy::ptr_arg, + clippy::redundant_field_names, + clippy::too_many_arguments, + clippy::borrow_deref_ref, + clippy::let_unit_value +)] + +trait CallableStr { + type T: Fn(&str); + fn callable_str(&self) -> Self::T; +} +impl CallableStr for () { + type T = fn(&str); + fn callable_str(&self) -> Self::T { + fn f(_: &str) {} + f + } +} +impl CallableStr for i32 { + type T = <() as CallableStr>::T; + fn callable_str(&self) -> Self::T { + ().callable_str() + } +} + +trait CallableT<U: ?Sized> { + type T: Fn(&U); + fn callable_t(&self) -> Self::T; +} +impl<U: ?Sized> CallableT<U> for () { + type T = fn(&U); + fn callable_t(&self) -> Self::T { + fn f<U: ?Sized>(_: &U) {} + f::<U> + } +} +impl<U: ?Sized> CallableT<U> for i32 { + type T = <() as CallableT<U>>::T; + fn callable_t(&self) -> Self::T { + ().callable_t() + } +} + +fn f_str(_: &str) {} +fn f_string(_: &String) {} +fn f_t<T>(_: T) {} +fn f_ref_t<T: ?Sized>(_: &T) {} + +fn f_str_t<T>(_: &str, _: T) {} + +fn f_box_t<T>(_: &Box<T>) {} + +extern "C" { + fn var(_: u32, ...); +} + +fn main() { + let s = String::new(); + + let _: &str = &s; + let _ = &*s; // Don't lint. Inferred type would change. + let _: &_ = &*s; // Don't lint. Inferred type would change. + + f_str(&s); + f_t(&*s); // Don't lint. Inferred type would change. + f_ref_t(&*s); // Don't lint. Inferred type would change. + + f_str_t(&s, &*s); // Don't lint second param. + + let b = Box::new(Box::new(Box::new(5))); + let _: &Box<i32> = &b; + let _: &Box<_> = &**b; // Don't lint. Inferred type would change. + + f_box_t(&**b); // Don't lint. Inferred type would change. + + let c = |_x: &str| (); + c(&s); + + let c = |_x| (); + c(&*s); // Don't lint. Inferred type would change. + + fn _f(x: &String) -> &str { + x + } + + fn _f1(x: &String) -> &str { + { x } + } + + fn _f2(x: &String) -> &str { + { x } + } + + fn _f3(x: &Box<Box<Box<i32>>>) -> &Box<i32> { + x + } + + fn _f4( + x: String, + f1: impl Fn(&str), + f2: &dyn Fn(&str), + f3: fn(&str), + f4: impl CallableStr, + f5: <() as CallableStr>::T, + f6: <i32 as CallableStr>::T, + f7: &dyn CallableStr<T = fn(&str)>, + f8: impl CallableT<str>, + f9: <() as CallableT<str>>::T, + f10: <i32 as CallableT<str>>::T, + f11: &dyn CallableT<str, T = fn(&str)>, + ) { + f1(&x); + f2(&x); + f3(&x); + f4.callable_str()(&x); + f5(&x); + f6(&x); + f7.callable_str()(&x); + f8.callable_t()(&x); + f9(&x); + f10(&x); + f11.callable_t()(&x); + } + + struct S1<'a>(&'a str); + let _ = S1(&s); + + struct S2<'a> { + s: &'a str, + } + let _ = S2 { s: &s }; + + struct S3<'a, T: ?Sized>(&'a T); + let _ = S3(&*s); // Don't lint. Inferred type would change. + + struct S4<'a, T: ?Sized> { + s: &'a T, + } + let _ = S4 { s: &*s }; // Don't lint. Inferred type would change. + + enum E1<'a> { + S1(&'a str), + S2 { s: &'a str }, + } + impl<'a> E1<'a> { + fn m1(s: &'a String) { + let _ = Self::S1(s); + let _ = Self::S2 { s: s }; + } + } + let _ = E1::S1(&s); + let _ = E1::S2 { s: &s }; + + enum E2<'a, T: ?Sized> { + S1(&'a T), + S2 { s: &'a T }, + } + let _ = E2::S1(&*s); // Don't lint. Inferred type would change. + let _ = E2::S2 { s: &*s }; // Don't lint. Inferred type would change. + + let ref_s = &s; + let _: &String = &*ref_s; // Don't lint reborrow. + f_string(&*ref_s); // Don't lint reborrow. + + struct S5 { + foo: u32, + } + let b = Box::new(Box::new(S5 { foo: 5 })); + let _ = b.foo; + let _ = b.foo; + let _ = b.foo; + + struct S6 { + foo: S5, + } + impl core::ops::Deref for S6 { + type Target = S5; + fn deref(&self) -> &Self::Target { + &self.foo + } + } + let s6 = S6 { foo: S5 { foo: 5 } }; + let _ = (*s6).foo; // Don't lint. `S6` also has a field named `foo` + + let ref_str = &"foo"; + let _ = f_str(ref_str); + let ref_ref_str = &ref_str; + let _ = f_str(ref_ref_str); + + fn _f5(x: &u32) -> u32 { + if true { + *x + } else { + return *x; + } + } + + f_str(&&ref_str); // `needless_borrow` will suggest removing both references + f_str(&ref_str); // `needless_borrow` will suggest removing only one reference + + let x = &&40; + unsafe { + var(0, &**x); + } +} diff --git a/src/tools/clippy/tests/ui/explicit_auto_deref.rs b/src/tools/clippy/tests/ui/explicit_auto_deref.rs new file mode 100644 index 00000000000..99294a7947b --- /dev/null +++ b/src/tools/clippy/tests/ui/explicit_auto_deref.rs @@ -0,0 +1,214 @@ +// run-rustfix + +#![warn(clippy::explicit_auto_deref)] +#![allow( + dead_code, + unused_braces, + clippy::borrowed_box, + clippy::needless_borrow, + clippy::needless_return, + clippy::ptr_arg, + clippy::redundant_field_names, + clippy::too_many_arguments, + clippy::borrow_deref_ref, + clippy::let_unit_value +)] + +trait CallableStr { + type T: Fn(&str); + fn callable_str(&self) -> Self::T; +} +impl CallableStr for () { + type T = fn(&str); + fn callable_str(&self) -> Self::T { + fn f(_: &str) {} + f + } +} +impl CallableStr for i32 { + type T = <() as CallableStr>::T; + fn callable_str(&self) -> Self::T { + ().callable_str() + } +} + +trait CallableT<U: ?Sized> { + type T: Fn(&U); + fn callable_t(&self) -> Self::T; +} +impl<U: ?Sized> CallableT<U> for () { + type T = fn(&U); + fn callable_t(&self) -> Self::T { + fn f<U: ?Sized>(_: &U) {} + f::<U> + } +} +impl<U: ?Sized> CallableT<U> for i32 { + type T = <() as CallableT<U>>::T; + fn callable_t(&self) -> Self::T { + ().callable_t() + } +} + +fn f_str(_: &str) {} +fn f_string(_: &String) {} +fn f_t<T>(_: T) {} +fn f_ref_t<T: ?Sized>(_: &T) {} + +fn f_str_t<T>(_: &str, _: T) {} + +fn f_box_t<T>(_: &Box<T>) {} + +extern "C" { + fn var(_: u32, ...); +} + +fn main() { + let s = String::new(); + + let _: &str = &*s; + let _ = &*s; // Don't lint. Inferred type would change. + let _: &_ = &*s; // Don't lint. Inferred type would change. + + f_str(&*s); + f_t(&*s); // Don't lint. Inferred type would change. + f_ref_t(&*s); // Don't lint. Inferred type would change. + + f_str_t(&*s, &*s); // Don't lint second param. + + let b = Box::new(Box::new(Box::new(5))); + let _: &Box<i32> = &**b; + let _: &Box<_> = &**b; // Don't lint. Inferred type would change. + + f_box_t(&**b); // Don't lint. Inferred type would change. + + let c = |_x: &str| (); + c(&*s); + + let c = |_x| (); + c(&*s); // Don't lint. Inferred type would change. + + fn _f(x: &String) -> &str { + &**x + } + + fn _f1(x: &String) -> &str { + { &**x } + } + + fn _f2(x: &String) -> &str { + &**{ x } + } + + fn _f3(x: &Box<Box<Box<i32>>>) -> &Box<i32> { + &***x + } + + fn _f4( + x: String, + f1: impl Fn(&str), + f2: &dyn Fn(&str), + f3: fn(&str), + f4: impl CallableStr, + f5: <() as CallableStr>::T, + f6: <i32 as CallableStr>::T, + f7: &dyn CallableStr<T = fn(&str)>, + f8: impl CallableT<str>, + f9: <() as CallableT<str>>::T, + f10: <i32 as CallableT<str>>::T, + f11: &dyn CallableT<str, T = fn(&str)>, + ) { + f1(&*x); + f2(&*x); + f3(&*x); + f4.callable_str()(&*x); + f5(&*x); + f6(&*x); + f7.callable_str()(&*x); + f8.callable_t()(&*x); + f9(&*x); + f10(&*x); + f11.callable_t()(&*x); + } + + struct S1<'a>(&'a str); + let _ = S1(&*s); + + struct S2<'a> { + s: &'a str, + } + let _ = S2 { s: &*s }; + + struct S3<'a, T: ?Sized>(&'a T); + let _ = S3(&*s); // Don't lint. Inferred type would change. + + struct S4<'a, T: ?Sized> { + s: &'a T, + } + let _ = S4 { s: &*s }; // Don't lint. Inferred type would change. + + enum E1<'a> { + S1(&'a str), + S2 { s: &'a str }, + } + impl<'a> E1<'a> { + fn m1(s: &'a String) { + let _ = Self::S1(&**s); + let _ = Self::S2 { s: &**s }; + } + } + let _ = E1::S1(&*s); + let _ = E1::S2 { s: &*s }; + + enum E2<'a, T: ?Sized> { + S1(&'a T), + S2 { s: &'a T }, + } + let _ = E2::S1(&*s); // Don't lint. Inferred type would change. + let _ = E2::S2 { s: &*s }; // Don't lint. Inferred type would change. + + let ref_s = &s; + let _: &String = &*ref_s; // Don't lint reborrow. + f_string(&*ref_s); // Don't lint reborrow. + + struct S5 { + foo: u32, + } + let b = Box::new(Box::new(S5 { foo: 5 })); + let _ = b.foo; + let _ = (*b).foo; + let _ = (**b).foo; + + struct S6 { + foo: S5, + } + impl core::ops::Deref for S6 { + type Target = S5; + fn deref(&self) -> &Self::Target { + &self.foo + } + } + let s6 = S6 { foo: S5 { foo: 5 } }; + let _ = (*s6).foo; // Don't lint. `S6` also has a field named `foo` + + let ref_str = &"foo"; + let _ = f_str(*ref_str); + let ref_ref_str = &ref_str; + let _ = f_str(**ref_ref_str); + + fn _f5(x: &u32) -> u32 { + if true { + *x + } else { + return *x; + } + } + + f_str(&&*ref_str); // `needless_borrow` will suggest removing both references + f_str(&&**ref_str); // `needless_borrow` will suggest removing only one reference + + let x = &&40; + unsafe { + var(0, &**x); + } +} diff --git a/src/tools/clippy/tests/ui/explicit_auto_deref.stderr b/src/tools/clippy/tests/ui/explicit_auto_deref.stderr new file mode 100644 index 00000000000..55f956e37ae --- /dev/null +++ b/src/tools/clippy/tests/ui/explicit_auto_deref.stderr @@ -0,0 +1,196 @@ +error: deref which would be done by auto-deref + --> $DIR/explicit_auto_deref.rs:69:20 + | +LL | let _: &str = &*s; + | ^^ help: try this: `s` + | + = note: `-D clippy::explicit-auto-deref` implied by `-D warnings` + +error: deref which would be done by auto-deref + --> $DIR/explicit_auto_deref.rs:73:12 + | +LL | f_str(&*s); + | ^^ help: try this: `s` + +error: deref which would be done by auto-deref + --> $DIR/explicit_auto_deref.rs:77:14 + | +LL | f_str_t(&*s, &*s); // Don't lint second param. + | ^^ help: try this: `s` + +error: deref which would be done by auto-deref + --> $DIR/explicit_auto_deref.rs:80:25 + | +LL | let _: &Box<i32> = &**b; + | ^^^ help: try this: `b` + +error: deref which would be done by auto-deref + --> $DIR/explicit_auto_deref.rs:86:8 + | +LL | c(&*s); + | ^^ help: try this: `s` + +error: deref which would be done by auto-deref + --> $DIR/explicit_auto_deref.rs:92:9 + | +LL | &**x + | ^^^^ help: try this: `x` + +error: deref which would be done by auto-deref + --> $DIR/explicit_auto_deref.rs:96:11 + | +LL | { &**x } + | ^^^^ help: try this: `x` + +error: deref which would be done by auto-deref + --> $DIR/explicit_auto_deref.rs:100:9 + | +LL | &**{ x } + | ^^^^^^^^ help: try this: `{ x }` + +error: deref which would be done by auto-deref + --> $DIR/explicit_auto_deref.rs:104:9 + | +LL | &***x + | ^^^^^ help: try this: `x` + +error: deref which would be done by auto-deref + --> $DIR/explicit_auto_deref.rs:121:13 + | +LL | f1(&*x); + | ^^ help: try this: `x` + +error: deref which would be done by auto-deref + --> $DIR/explicit_auto_deref.rs:122:13 + | +LL | f2(&*x); + | ^^ help: try this: `x` + +error: deref which would be done by auto-deref + --> $DIR/explicit_auto_deref.rs:123:13 + | +LL | f3(&*x); + | ^^ help: try this: `x` + +error: deref which would be done by auto-deref + --> $DIR/explicit_auto_deref.rs:124:28 + | +LL | f4.callable_str()(&*x); + | ^^ help: try this: `x` + +error: deref which would be done by auto-deref + --> $DIR/explicit_auto_deref.rs:125:13 + | +LL | f5(&*x); + | ^^ help: try this: `x` + +error: deref which would be done by auto-deref + --> $DIR/explicit_auto_deref.rs:126:13 + | +LL | f6(&*x); + | ^^ help: try this: `x` + +error: deref which would be done by auto-deref + --> $DIR/explicit_auto_deref.rs:127:28 + | +LL | f7.callable_str()(&*x); + | ^^ help: try this: `x` + +error: deref which would be done by auto-deref + --> $DIR/explicit_auto_deref.rs:128:26 + | +LL | f8.callable_t()(&*x); + | ^^ help: try this: `x` + +error: deref which would be done by auto-deref + --> $DIR/explicit_auto_deref.rs:129:13 + | +LL | f9(&*x); + | ^^ help: try this: `x` + +error: deref which would be done by auto-deref + --> $DIR/explicit_auto_deref.rs:130:14 + | +LL | f10(&*x); + | ^^ help: try this: `x` + +error: deref which would be done by auto-deref + --> $DIR/explicit_auto_deref.rs:131:27 + | +LL | f11.callable_t()(&*x); + | ^^ help: try this: `x` + +error: deref which would be done by auto-deref + --> $DIR/explicit_auto_deref.rs:135:17 + | +LL | let _ = S1(&*s); + | ^^ help: try this: `s` + +error: deref which would be done by auto-deref + --> $DIR/explicit_auto_deref.rs:140:22 + | +LL | let _ = S2 { s: &*s }; + | ^^ help: try this: `s` + +error: deref which would be done by auto-deref + --> $DIR/explicit_auto_deref.rs:156:30 + | +LL | let _ = Self::S1(&**s); + | ^^^^ help: try this: `s` + +error: deref which would be done by auto-deref + --> $DIR/explicit_auto_deref.rs:157:35 + | +LL | let _ = Self::S2 { s: &**s }; + | ^^^^ help: try this: `s` + +error: deref which would be done by auto-deref + --> $DIR/explicit_auto_deref.rs:160:21 + | +LL | let _ = E1::S1(&*s); + | ^^ help: try this: `s` + +error: deref which would be done by auto-deref + --> $DIR/explicit_auto_deref.rs:161:26 + | +LL | let _ = E1::S2 { s: &*s }; + | ^^ help: try this: `s` + +error: deref which would be done by auto-deref + --> $DIR/explicit_auto_deref.rs:179:13 + | +LL | let _ = (*b).foo; + | ^^^^ help: try this: `b` + +error: deref which would be done by auto-deref + --> $DIR/explicit_auto_deref.rs:180:13 + | +LL | let _ = (**b).foo; + | ^^^^^ help: try this: `b` + +error: deref which would be done by auto-deref + --> $DIR/explicit_auto_deref.rs:195:19 + | +LL | let _ = f_str(*ref_str); + | ^^^^^^^^ help: try this: `ref_str` + +error: deref which would be done by auto-deref + --> $DIR/explicit_auto_deref.rs:197:19 + | +LL | let _ = f_str(**ref_ref_str); + | ^^^^^^^^^^^^^ help: try this: `ref_ref_str` + +error: deref which would be done by auto-deref + --> $DIR/explicit_auto_deref.rs:207:13 + | +LL | f_str(&&*ref_str); // `needless_borrow` will suggest removing both references + | ^^^^^^^^ help: try this: `ref_str` + +error: deref which would be done by auto-deref + --> $DIR/explicit_auto_deref.rs:208:12 + | +LL | f_str(&&**ref_str); // `needless_borrow` will suggest removing only one reference + | ^^^^^^^^^^ help: try this: `ref_str` + +error: aborting due to 32 previous errors + diff --git a/src/tools/clippy/tests/ui/explicit_deref_methods.fixed b/src/tools/clippy/tests/ui/explicit_deref_methods.fixed index 92f27e68549..523cae183ee 100644 --- a/src/tools/clippy/tests/ui/explicit_deref_methods.fixed +++ b/src/tools/clippy/tests/ui/explicit_deref_methods.fixed @@ -4,7 +4,8 @@ unused_variables, clippy::clone_double_ref, clippy::needless_borrow, - clippy::borrow_deref_ref + clippy::borrow_deref_ref, + clippy::explicit_auto_deref )] #![warn(clippy::explicit_deref_methods)] diff --git a/src/tools/clippy/tests/ui/explicit_deref_methods.rs b/src/tools/clippy/tests/ui/explicit_deref_methods.rs index d118607f992..0bbc1ae57cd 100644 --- a/src/tools/clippy/tests/ui/explicit_deref_methods.rs +++ b/src/tools/clippy/tests/ui/explicit_deref_methods.rs @@ -4,7 +4,8 @@ unused_variables, clippy::clone_double_ref, clippy::needless_borrow, - clippy::borrow_deref_ref + clippy::borrow_deref_ref, + clippy::explicit_auto_deref )] #![warn(clippy::explicit_deref_methods)] diff --git a/src/tools/clippy/tests/ui/explicit_deref_methods.stderr b/src/tools/clippy/tests/ui/explicit_deref_methods.stderr index 8e8b358972b..4b10ed1377b 100644 --- a/src/tools/clippy/tests/ui/explicit_deref_methods.stderr +++ b/src/tools/clippy/tests/ui/explicit_deref_methods.stderr @@ -1,5 +1,5 @@ error: explicit `deref` method call - --> $DIR/explicit_deref_methods.rs:35:19 + --> $DIR/explicit_deref_methods.rs:36:19 | LL | let b: &str = a.deref(); | ^^^^^^^^^ help: try this: `&*a` @@ -7,67 +7,67 @@ LL | let b: &str = a.deref(); = note: `-D clippy::explicit-deref-methods` implied by `-D warnings` error: explicit `deref_mut` method call - --> $DIR/explicit_deref_methods.rs:37:23 + --> $DIR/explicit_deref_methods.rs:38:23 | LL | let b: &mut str = a.deref_mut(); | ^^^^^^^^^^^^^ help: try this: `&mut **a` error: explicit `deref` method call - --> $DIR/explicit_deref_methods.rs:40:39 + --> $DIR/explicit_deref_methods.rs:41:39 | LL | let b: String = format!("{}, {}", a.deref(), a.deref()); | ^^^^^^^^^ help: try this: `&*a` error: explicit `deref` method call - --> $DIR/explicit_deref_methods.rs:40:50 + --> $DIR/explicit_deref_methods.rs:41:50 | LL | let b: String = format!("{}, {}", a.deref(), a.deref()); | ^^^^^^^^^ help: try this: `&*a` error: explicit `deref` method call - --> $DIR/explicit_deref_methods.rs:42:20 + --> $DIR/explicit_deref_methods.rs:43:20 | LL | println!("{}", a.deref()); | ^^^^^^^^^ help: try this: `&*a` error: explicit `deref` method call - --> $DIR/explicit_deref_methods.rs:45:11 + --> $DIR/explicit_deref_methods.rs:46:11 | LL | match a.deref() { | ^^^^^^^^^ help: try this: `&*a` error: explicit `deref` method call - --> $DIR/explicit_deref_methods.rs:49:28 + --> $DIR/explicit_deref_methods.rs:50:28 | LL | let b: String = concat(a.deref()); | ^^^^^^^^^ help: try this: `&*a` error: explicit `deref` method call - --> $DIR/explicit_deref_methods.rs:51:13 + --> $DIR/explicit_deref_methods.rs:52:13 | LL | let b = just_return(a).deref(); | ^^^^^^^^^^^^^^^^^^^^^^ help: try this: `just_return(a)` error: explicit `deref` method call - --> $DIR/explicit_deref_methods.rs:53:28 + --> $DIR/explicit_deref_methods.rs:54:28 | LL | let b: String = concat(just_return(a).deref()); | ^^^^^^^^^^^^^^^^^^^^^^ help: try this: `just_return(a)` error: explicit `deref` method call - --> $DIR/explicit_deref_methods.rs:55:19 + --> $DIR/explicit_deref_methods.rs:56:19 | LL | let b: &str = a.deref().deref(); | ^^^^^^^^^^^^^^^^^ help: try this: `&**a` error: explicit `deref` method call - --> $DIR/explicit_deref_methods.rs:58:13 + --> $DIR/explicit_deref_methods.rs:59:13 | LL | let b = opt_a.unwrap().deref(); | ^^^^^^^^^^^^^^^^^^^^^^ help: try this: `&*opt_a.unwrap()` error: explicit `deref` method call - --> $DIR/explicit_deref_methods.rs:84:31 + --> $DIR/explicit_deref_methods.rs:85:31 | LL | let b: &str = expr_deref!(a.deref()); | ^^^^^^^^^ help: try this: `&*a` diff --git a/src/tools/clippy/tests/ui/extra_unused_lifetimes.rs b/src/tools/clippy/tests/ui/extra_unused_lifetimes.rs index f76127a7105..d6631e01290 100644 --- a/src/tools/clippy/tests/ui/extra_unused_lifetimes.rs +++ b/src/tools/clippy/tests/ui/extra_unused_lifetimes.rs @@ -1,3 +1,5 @@ +// aux-build:proc_macro_derive.rs + #![allow( unused, dead_code, @@ -7,6 +9,9 @@ )] #![warn(clippy::extra_unused_lifetimes)] +#[macro_use] +extern crate proc_macro_derive; + fn empty() {} fn used_lt<'a>(x: &'a u8) {} @@ -114,4 +119,11 @@ mod second_case { } } +// Should not lint +#[derive(ExtraLifetimeDerive)] +struct Human<'a> { + pub bones: i32, + pub name: &'a str, +} + fn main() {} diff --git a/src/tools/clippy/tests/ui/extra_unused_lifetimes.stderr b/src/tools/clippy/tests/ui/extra_unused_lifetimes.stderr index fcc12d4ce14..26ebc3976df 100644 --- a/src/tools/clippy/tests/ui/extra_unused_lifetimes.stderr +++ b/src/tools/clippy/tests/ui/extra_unused_lifetimes.stderr @@ -1,5 +1,5 @@ error: this lifetime isn't used in the function definition - --> $DIR/extra_unused_lifetimes.rs:14:14 + --> $DIR/extra_unused_lifetimes.rs:19:14 | LL | fn unused_lt<'a>(x: u8) {} | ^^ @@ -7,31 +7,31 @@ LL | fn unused_lt<'a>(x: u8) {} = note: `-D clippy::extra-unused-lifetimes` implied by `-D warnings` error: this lifetime isn't used in the function definition - --> $DIR/extra_unused_lifetimes.rs:41:10 + --> $DIR/extra_unused_lifetimes.rs:46:10 | LL | fn x<'a>(&self) {} | ^^ error: this lifetime isn't used in the function definition - --> $DIR/extra_unused_lifetimes.rs:67:22 + --> $DIR/extra_unused_lifetimes.rs:72:22 | LL | fn unused_lt<'a>(x: u8) {} | ^^ error: this lifetime isn't used in the impl - --> $DIR/extra_unused_lifetimes.rs:78:10 + --> $DIR/extra_unused_lifetimes.rs:83:10 | LL | impl<'a> std::ops::AddAssign<&Scalar> for &mut Scalar { | ^^ error: this lifetime isn't used in the impl - --> $DIR/extra_unused_lifetimes.rs:84:10 + --> $DIR/extra_unused_lifetimes.rs:89:10 | LL | impl<'b> Scalar { | ^^ error: this lifetime isn't used in the function definition - --> $DIR/extra_unused_lifetimes.rs:85:26 + --> $DIR/extra_unused_lifetimes.rs:90:26 | LL | pub fn something<'c>() -> Self { | ^^ diff --git a/src/tools/clippy/tests/ui/if_same_then_else.rs b/src/tools/clippy/tests/ui/if_same_then_else.rs index ef956745500..2598c2ab426 100644 --- a/src/tools/clippy/tests/ui/if_same_then_else.rs +++ b/src/tools/clippy/tests/ui/if_same_then_else.rs @@ -6,7 +6,9 @@ clippy::no_effect, clippy::unused_unit, clippy::zero_divided_by_zero, - clippy::branches_sharing_code + clippy::branches_sharing_code, + dead_code, + unreachable_code )] struct Foo { @@ -155,4 +157,61 @@ mod issue_5698 { } } +mod issue_8836 { + fn do_not_lint() { + if true { + todo!() + } else { + todo!() + } + if true { + todo!(); + } else { + todo!(); + } + if true { + unimplemented!() + } else { + unimplemented!() + } + if true { + unimplemented!(); + } else { + unimplemented!(); + } + + if true { + println!("FOO"); + todo!(); + } else { + println!("FOO"); + todo!(); + } + + if true { + println!("FOO"); + unimplemented!(); + } else { + println!("FOO"); + unimplemented!(); + } + + if true { + println!("FOO"); + todo!() + } else { + println!("FOO"); + todo!() + } + + if true { + println!("FOO"); + unimplemented!() + } else { + println!("FOO"); + unimplemented!() + } + } +} + fn main() {} diff --git a/src/tools/clippy/tests/ui/if_same_then_else.stderr b/src/tools/clippy/tests/ui/if_same_then_else.stderr index 2f38052fc20..2cdf442486a 100644 --- a/src/tools/clippy/tests/ui/if_same_then_else.stderr +++ b/src/tools/clippy/tests/ui/if_same_then_else.stderr @@ -1,5 +1,5 @@ error: this `if` has identical blocks - --> $DIR/if_same_then_else.rs:21:13 + --> $DIR/if_same_then_else.rs:23:13 | LL | if true { | _____________^ @@ -13,7 +13,7 @@ LL | | } else { | = note: `-D clippy::if-same-then-else` implied by `-D warnings` note: same as this - --> $DIR/if_same_then_else.rs:29:12 + --> $DIR/if_same_then_else.rs:31:12 | LL | } else { | ____________^ @@ -26,7 +26,7 @@ LL | | } | |_____^ error: this `if` has identical blocks - --> $DIR/if_same_then_else.rs:65:21 + --> $DIR/if_same_then_else.rs:67:21 | LL | let _ = if true { | _____________________^ @@ -35,7 +35,7 @@ LL | | } else { | |_____^ | note: same as this - --> $DIR/if_same_then_else.rs:67:12 + --> $DIR/if_same_then_else.rs:69:12 | LL | } else { | ____________^ @@ -45,7 +45,7 @@ LL | | }; | |_____^ error: this `if` has identical blocks - --> $DIR/if_same_then_else.rs:72:21 + --> $DIR/if_same_then_else.rs:74:21 | LL | let _ = if true { | _____________________^ @@ -54,7 +54,7 @@ LL | | } else { | |_____^ | note: same as this - --> $DIR/if_same_then_else.rs:74:12 + --> $DIR/if_same_then_else.rs:76:12 | LL | } else { | ____________^ @@ -64,7 +64,7 @@ LL | | }; | |_____^ error: this `if` has identical blocks - --> $DIR/if_same_then_else.rs:88:21 + --> $DIR/if_same_then_else.rs:90:21 | LL | let _ = if true { | _____________________^ @@ -73,7 +73,7 @@ LL | | } else { | |_____^ | note: same as this - --> $DIR/if_same_then_else.rs:90:12 + --> $DIR/if_same_then_else.rs:92:12 | LL | } else { | ____________^ @@ -83,7 +83,7 @@ LL | | }; | |_____^ error: this `if` has identical blocks - --> $DIR/if_same_then_else.rs:95:13 + --> $DIR/if_same_then_else.rs:97:13 | LL | if true { | _____________^ @@ -96,7 +96,7 @@ LL | | } else { | |_____^ | note: same as this - --> $DIR/if_same_then_else.rs:102:12 + --> $DIR/if_same_then_else.rs:104:12 | LL | } else { | ____________^ diff --git a/src/tools/clippy/tests/ui/implicit_return.fixed b/src/tools/clippy/tests/ui/implicit_return.fixed index a51f7bc6a29..5e55b8b6739 100644 --- a/src/tools/clippy/tests/ui/implicit_return.fixed +++ b/src/tools/clippy/tests/ui/implicit_return.fixed @@ -1,5 +1,5 @@ // run-rustfix - +#![feature(lint_reasons)] #![warn(clippy::implicit_return)] #![allow(clippy::needless_return, clippy::needless_bool, unused, clippy::never_loop)] @@ -128,3 +128,13 @@ async fn foo() -> bool { } fn main() {} + +fn check_expect() -> bool { + if true { + // no error! + return true; + } + + #[expect(clippy::implicit_return)] + true +} diff --git a/src/tools/clippy/tests/ui/implicit_return.rs b/src/tools/clippy/tests/ui/implicit_return.rs index 03f8ec49d51..76f0a980352 100644 --- a/src/tools/clippy/tests/ui/implicit_return.rs +++ b/src/tools/clippy/tests/ui/implicit_return.rs @@ -1,5 +1,5 @@ // run-rustfix - +#![feature(lint_reasons)] #![warn(clippy::implicit_return)] #![allow(clippy::needless_return, clippy::needless_bool, unused, clippy::never_loop)] @@ -128,3 +128,13 @@ async fn foo() -> bool { } fn main() {} + +fn check_expect() -> bool { + if true { + // no error! + return true; + } + + #[expect(clippy::implicit_return)] + true +} diff --git a/src/tools/clippy/tests/ui/let_underscore_lock.rs b/src/tools/clippy/tests/ui/let_underscore_lock.rs index 539d74d1d4c..7a7c4e92499 100644 --- a/src/tools/clippy/tests/ui/let_underscore_lock.rs +++ b/src/tools/clippy/tests/ui/let_underscore_lock.rs @@ -13,6 +13,10 @@ fn main() { let _ = rw.try_read(); let _ = rw.try_write(); + // These shouldn't throw an error. + let _ = m; + let _ = rw; + use parking_lot::{lock_api::RawMutex, Mutex, RwLock}; let p_m: Mutex<()> = Mutex::const_new(RawMutex::INIT, ()); @@ -24,4 +28,9 @@ fn main() { let p_rw = RwLock::new(0); let _ = p_rw.read(); let _ = p_rw.write(); + + // These shouldn't throw an error. + let _ = p_m; + let _ = p_m1; + let _ = p_rw; } diff --git a/src/tools/clippy/tests/ui/let_underscore_lock.stderr b/src/tools/clippy/tests/ui/let_underscore_lock.stderr index 3a2bc17bf7b..4365b48fabb 100644 --- a/src/tools/clippy/tests/ui/let_underscore_lock.stderr +++ b/src/tools/clippy/tests/ui/let_underscore_lock.stderr @@ -48,7 +48,7 @@ LL | let _ = rw.try_write(); = help: consider using an underscore-prefixed named binding or dropping explicitly with `std::mem::drop` error: non-binding let on a synchronization lock - --> $DIR/let_underscore_lock.rs:19:5 + --> $DIR/let_underscore_lock.rs:23:5 | LL | let _ = p_m.lock(); | ^^^^^^^^^^^^^^^^^^^ @@ -56,7 +56,7 @@ LL | let _ = p_m.lock(); = help: consider using an underscore-prefixed named binding or dropping explicitly with `std::mem::drop` error: non-binding let on a synchronization lock - --> $DIR/let_underscore_lock.rs:22:5 + --> $DIR/let_underscore_lock.rs:26:5 | LL | let _ = p_m1.lock(); | ^^^^^^^^^^^^^^^^^^^^ @@ -64,7 +64,7 @@ LL | let _ = p_m1.lock(); = help: consider using an underscore-prefixed named binding or dropping explicitly with `std::mem::drop` error: non-binding let on a synchronization lock - --> $DIR/let_underscore_lock.rs:25:5 + --> $DIR/let_underscore_lock.rs:29:5 | LL | let _ = p_rw.read(); | ^^^^^^^^^^^^^^^^^^^^ @@ -72,7 +72,7 @@ LL | let _ = p_rw.read(); = help: consider using an underscore-prefixed named binding or dropping explicitly with `std::mem::drop` error: non-binding let on a synchronization lock - --> $DIR/let_underscore_lock.rs:26:5 + --> $DIR/let_underscore_lock.rs:30:5 | LL | let _ = p_rw.write(); | ^^^^^^^^^^^^^^^^^^^^^ diff --git a/src/tools/clippy/tests/ui/logic_bug.rs b/src/tools/clippy/tests/ui/logic_bug.rs index 4eaa2dd98eb..dd6b1db5f70 100644 --- a/src/tools/clippy/tests/ui/logic_bug.rs +++ b/src/tools/clippy/tests/ui/logic_bug.rs @@ -1,3 +1,4 @@ +#![feature(lint_reasons)] #![allow(unused, clippy::diverging_sub_expression)] #![warn(clippy::logic_bug)] @@ -24,3 +25,10 @@ fn equality_stuff() { let _ = a > b && a <= b; let _ = a > b && a == b; } + +fn check_expect() { + let a: i32 = unimplemented!(); + let b: i32 = unimplemented!(); + #[expect(clippy::logic_bug)] + let _ = a < b && a >= b; +} diff --git a/src/tools/clippy/tests/ui/logic_bug.stderr b/src/tools/clippy/tests/ui/logic_bug.stderr index 8f55e1c8ad8..4021fbf4570 100644 --- a/src/tools/clippy/tests/ui/logic_bug.stderr +++ b/src/tools/clippy/tests/ui/logic_bug.stderr @@ -1,60 +1,60 @@ error: this boolean expression contains a logic bug - --> $DIR/logic_bug.rs:10:13 + --> $DIR/logic_bug.rs:11:13 | LL | let _ = a && b || a; | ^^^^^^^^^^^ help: it would look like the following: `a` | = note: `-D clippy::logic-bug` implied by `-D warnings` help: this expression can be optimized out by applying boolean operations to the outer expression - --> $DIR/logic_bug.rs:10:18 + --> $DIR/logic_bug.rs:11:18 | LL | let _ = a && b || a; | ^ error: this boolean expression contains a logic bug - --> $DIR/logic_bug.rs:12:13 + --> $DIR/logic_bug.rs:13:13 | LL | let _ = false && a; | ^^^^^^^^^^ help: it would look like the following: `false` | help: this expression can be optimized out by applying boolean operations to the outer expression - --> $DIR/logic_bug.rs:12:22 + --> $DIR/logic_bug.rs:13:22 | LL | let _ = false && a; | ^ error: this boolean expression contains a logic bug - --> $DIR/logic_bug.rs:22:13 + --> $DIR/logic_bug.rs:23:13 | LL | let _ = a == b && a != b; | ^^^^^^^^^^^^^^^^ help: it would look like the following: `false` | help: this expression can be optimized out by applying boolean operations to the outer expression - --> $DIR/logic_bug.rs:22:13 + --> $DIR/logic_bug.rs:23:13 | LL | let _ = a == b && a != b; | ^^^^^^ error: this boolean expression contains a logic bug - --> $DIR/logic_bug.rs:23:13 + --> $DIR/logic_bug.rs:24:13 | LL | let _ = a < b && a >= b; | ^^^^^^^^^^^^^^^ help: it would look like the following: `false` | help: this expression can be optimized out by applying boolean operations to the outer expression - --> $DIR/logic_bug.rs:23:13 + --> $DIR/logic_bug.rs:24:13 | LL | let _ = a < b && a >= b; | ^^^^^ error: this boolean expression contains a logic bug - --> $DIR/logic_bug.rs:24:13 + --> $DIR/logic_bug.rs:25:13 | LL | let _ = a > b && a <= b; | ^^^^^^^^^^^^^^^ help: it would look like the following: `false` | help: this expression can be optimized out by applying boolean operations to the outer expression - --> $DIR/logic_bug.rs:24:13 + --> $DIR/logic_bug.rs:25:13 | LL | let _ = a > b && a <= b; | ^^^^^ diff --git a/src/tools/clippy/tests/ui/macro_use_imports.fixed b/src/tools/clippy/tests/ui/macro_use_imports.fixed index a83c8ba0b64..e612480d264 100644 --- a/src/tools/clippy/tests/ui/macro_use_imports.fixed +++ b/src/tools/clippy/tests/ui/macro_use_imports.fixed @@ -4,6 +4,7 @@ // run-rustfix // ignore-32bit +#![feature(lint_reasons)] #![allow(unused_imports, unreachable_code, unused_variables, dead_code, unused_attributes)] #![allow(clippy::single_component_path_imports)] #![warn(clippy::macro_use_imports)] diff --git a/src/tools/clippy/tests/ui/macro_use_imports.rs b/src/tools/clippy/tests/ui/macro_use_imports.rs index e26a7545ea6..b34817cc3b2 100644 --- a/src/tools/clippy/tests/ui/macro_use_imports.rs +++ b/src/tools/clippy/tests/ui/macro_use_imports.rs @@ -4,6 +4,7 @@ // run-rustfix // ignore-32bit +#![feature(lint_reasons)] #![allow(unused_imports, unreachable_code, unused_variables, dead_code, unused_attributes)] #![allow(clippy::single_component_path_imports)] #![warn(clippy::macro_use_imports)] diff --git a/src/tools/clippy/tests/ui/macro_use_imports.stderr b/src/tools/clippy/tests/ui/macro_use_imports.stderr index 9028a636e7f..bf7b6edd0e3 100644 --- a/src/tools/clippy/tests/ui/macro_use_imports.stderr +++ b/src/tools/clippy/tests/ui/macro_use_imports.stderr @@ -1,28 +1,28 @@ error: `macro_use` attributes are no longer needed in the Rust 2018 edition - --> $DIR/macro_use_imports.rs:18:5 + --> $DIR/macro_use_imports.rs:23:5 | LL | #[macro_use] - | ^^^^^^^^^^^^ help: remove the attribute and import the macro directly, try: `use mac::{pub_macro, function_macro, ty_macro, inner_mod_macro, pub_in_private_macro};` + | ^^^^^^^^^^^^ help: remove the attribute and import the macro directly, try: `use mac::{inner::foofoo, inner::try_err};` | = note: `-D clippy::macro-use-imports` implied by `-D warnings` error: `macro_use` attributes are no longer needed in the Rust 2018 edition - --> $DIR/macro_use_imports.rs:20:5 + --> $DIR/macro_use_imports.rs:21:5 | LL | #[macro_use] | ^^^^^^^^^^^^ help: remove the attribute and import the macro directly, try: `use mini_mac::ClippyMiniMacroTest;` error: `macro_use` attributes are no longer needed in the Rust 2018 edition - --> $DIR/macro_use_imports.rs:22:5 + --> $DIR/macro_use_imports.rs:25:5 | LL | #[macro_use] - | ^^^^^^^^^^^^ help: remove the attribute and import the macro directly, try: `use mac::{inner::foofoo, inner::try_err};` + | ^^^^^^^^^^^^ help: remove the attribute and import the macro directly, try: `use mac::inner::nested::string_add;` error: `macro_use` attributes are no longer needed in the Rust 2018 edition - --> $DIR/macro_use_imports.rs:24:5 + --> $DIR/macro_use_imports.rs:19:5 | LL | #[macro_use] - | ^^^^^^^^^^^^ help: remove the attribute and import the macro directly, try: `use mac::inner::nested::string_add;` + | ^^^^^^^^^^^^ help: remove the attribute and import the macro directly, try: `use mac::{pub_macro, function_macro, ty_macro, inner_mod_macro, pub_in_private_macro};` error: aborting due to 4 previous errors diff --git a/src/tools/clippy/tests/ui/macro_use_imports_expect.rs b/src/tools/clippy/tests/ui/macro_use_imports_expect.rs new file mode 100644 index 00000000000..8a1b05da9ef --- /dev/null +++ b/src/tools/clippy/tests/ui/macro_use_imports_expect.rs @@ -0,0 +1,51 @@ +// aux-build:macro_rules.rs +// aux-build:macro_use_helper.rs +// aux-build:proc_macro_derive.rs +// ignore-32bit + +#![feature(lint_reasons)] +#![allow(unused_imports, unreachable_code, unused_variables, dead_code, unused_attributes)] +#![allow(clippy::single_component_path_imports)] +#![warn(clippy::macro_use_imports)] + +#[macro_use] +extern crate macro_use_helper as mac; + +#[macro_use] +extern crate proc_macro_derive as mini_mac; + +mod a { + #[expect(clippy::macro_use_imports)] + #[macro_use] + use mac; + #[expect(clippy::macro_use_imports)] + #[macro_use] + use mini_mac; + #[expect(clippy::macro_use_imports)] + #[macro_use] + use mac::inner; + #[expect(clippy::macro_use_imports)] + #[macro_use] + use mac::inner::nested; + + #[derive(ClippyMiniMacroTest)] + struct Test; + + fn test() { + pub_macro!(); + inner_mod_macro!(); + pub_in_private_macro!(_var); + function_macro!(); + let v: ty_macro!() = Vec::default(); + + inner::try_err!(); + inner::foofoo!(); + nested::string_add!(); + } +} + +// issue #7015, ICE due to calling `module_children` with local `DefId` +#[macro_use] +use a as b; + +fn main() {} diff --git a/src/tools/clippy/tests/ui/manual_find.rs b/src/tools/clippy/tests/ui/manual_find.rs new file mode 100644 index 00000000000..257fe045f78 --- /dev/null +++ b/src/tools/clippy/tests/ui/manual_find.rs @@ -0,0 +1,22 @@ +#![allow(unused)] +#![warn(clippy::manual_find)] + +fn vec_string(strings: Vec<String>) -> Option<String> { + for s in strings { + if s == String::new() { + return Some(s); + } + } + None +} + +fn tuple(arr: Vec<(String, i32)>) -> Option<String> { + for (s, _) in arr { + if s == String::new() { + return Some(s); + } + } + None +} + +fn main() {} diff --git a/src/tools/clippy/tests/ui/manual_find.stderr b/src/tools/clippy/tests/ui/manual_find.stderr new file mode 100644 index 00000000000..da0fd4aaef7 --- /dev/null +++ b/src/tools/clippy/tests/ui/manual_find.stderr @@ -0,0 +1,29 @@ +error: manual implementation of `Iterator::find` + --> $DIR/manual_find.rs:5:5 + | +LL | / for s in strings { +LL | | if s == String::new() { +LL | | return Some(s); +LL | | } +LL | | } +LL | | None + | |________^ help: replace with an iterator: `strings.into_iter().find(|s| s == String::new())` + | + = note: `-D clippy::manual-find` implied by `-D warnings` + = note: you may need to dereference some variables + +error: manual implementation of `Iterator::find` + --> $DIR/manual_find.rs:14:5 + | +LL | / for (s, _) in arr { +LL | | if s == String::new() { +LL | | return Some(s); +LL | | } +LL | | } +LL | | None + | |________^ help: replace with an iterator: `arr.into_iter().map(|(s, _)| s).find(|s| s == String::new())` + | + = note: you may need to dereference some variables + +error: aborting due to 2 previous errors + diff --git a/src/tools/clippy/tests/ui/manual_find_fixable.fixed b/src/tools/clippy/tests/ui/manual_find_fixable.fixed new file mode 100644 index 00000000000..36d1644c22b --- /dev/null +++ b/src/tools/clippy/tests/ui/manual_find_fixable.fixed @@ -0,0 +1,182 @@ +// run-rustfix + +#![allow(unused, clippy::needless_return)] +#![warn(clippy::manual_find)] + +use std::collections::HashMap; + +const ARRAY: &[u32; 5] = &[2, 7, 1, 9, 3]; + +fn lookup(n: u32) -> Option<u32> { + ARRAY.iter().find(|&&v| v == n).copied() +} + +fn with_pat(arr: Vec<(u32, u32)>) -> Option<u32> { + arr.into_iter().map(|(a, _)| a).find(|&a| a % 2 == 0) +} + +struct Data { + name: String, + is_true: bool, +} +fn with_struct(arr: Vec<Data>) -> Option<Data> { + arr.into_iter().find(|el| el.name.len() == 10) +} + +struct Tuple(usize, usize); +fn with_tuple_struct(arr: Vec<Tuple>) -> Option<usize> { + arr.into_iter().map(|Tuple(a, _)| a).find(|&a| a >= 3) +} + +struct A; +impl A { + fn should_keep(&self) -> bool { + true + } +} +fn with_method_call(arr: Vec<A>) -> Option<A> { + arr.into_iter().find(|el| el.should_keep()) +} + +fn with_closure(arr: Vec<u32>) -> Option<u32> { + let f = |el: u32| -> u32 { el + 10 }; + arr.into_iter().find(|&el| f(el) == 20) +} + +fn with_closure2(arr: HashMap<String, i32>) -> Option<i32> { + let f = |el: i32| -> bool { el == 10 }; + arr.values().find(|&&el| f(el)).copied() +} + +fn with_bool(arr: Vec<Data>) -> Option<Data> { + arr.into_iter().find(|el| el.is_true) +} + +fn with_side_effects(arr: Vec<u32>) -> Option<u32> { + for v in arr { + if v == 1 { + println!("side effect"); + return Some(v); + } + } + None +} + +fn with_else(arr: Vec<u32>) -> Option<u32> { + for el in arr { + if el % 2 == 0 { + return Some(el); + } else { + println!("{}", el); + } + } + None +} + +fn tuple_with_ref(v: [(u8, &u8); 3]) -> Option<u8> { + v.into_iter().map(|(_, &x)| x).find(|&x| x > 10) +} + +fn ref_to_tuple_with_ref(v: &[(u8, &u8)]) -> Option<u8> { + v.iter().map(|&(_, &x)| x).find(|&x| x > 10) +} + +fn explicit_ret(arr: Vec<i32>) -> Option<i32> { + arr.into_iter().find(|&x| x >= 5) +} + +fn plus_one(a: i32) -> Option<i32> { + Some(a + 1) +} +fn fn_instead_of_some(a: &[i32]) -> Option<i32> { + for &x in a { + if x == 1 { + return plus_one(x); + } + } + None +} + +fn for_in_condition(a: &[i32], b: bool) -> Option<i32> { + if b { + for &x in a { + if x == 1 { + return Some(x); + } + } + } + None +} + +fn intermediate_statements(a: &[i32]) -> Option<i32> { + for &x in a { + if x == 1 { + return Some(x); + } + } + + println!("side effect"); + + None +} + +fn mixed_binding_modes(arr: Vec<(i32, String)>) -> Option<i32> { + for (x, mut s) in arr { + if x == 1 && s.as_mut_str().len() == 2 { + return Some(x); + } + } + None +} + +fn as_closure() { + #[rustfmt::skip] + let f = |arr: Vec<i32>| -> Option<i32> { + arr.into_iter().find(|&x| x < 1) + }; +} + +fn in_block(a: &[i32]) -> Option<i32> { + let should_be_none = { + for &x in a { + if x == 1 { + return Some(x); + } + } + None + }; + + assert!(should_be_none.is_none()); + + should_be_none +} + +// Not handled yet +fn mut_binding(v: Vec<String>) -> Option<String> { + for mut s in v { + if s.as_mut_str().len() > 1 { + return Some(s); + } + } + None +} + +fn subpattern(v: Vec<[u32; 32]>) -> Option<[u32; 32]> { + for a @ [first, ..] in v { + if a[12] == first { + return Some(a); + } + } + None +} + +fn two_bindings(v: Vec<(u8, u8)>) -> Option<u8> { + for (a, n) in v { + if a == n { + return Some(a); + } + } + None +} + +fn main() {} diff --git a/src/tools/clippy/tests/ui/manual_find_fixable.rs b/src/tools/clippy/tests/ui/manual_find_fixable.rs new file mode 100644 index 00000000000..ed277ddaa72 --- /dev/null +++ b/src/tools/clippy/tests/ui/manual_find_fixable.rs @@ -0,0 +1,242 @@ +// run-rustfix + +#![allow(unused, clippy::needless_return)] +#![warn(clippy::manual_find)] + +use std::collections::HashMap; + +const ARRAY: &[u32; 5] = &[2, 7, 1, 9, 3]; + +fn lookup(n: u32) -> Option<u32> { + for &v in ARRAY { + if v == n { + return Some(v); + } + } + None +} + +fn with_pat(arr: Vec<(u32, u32)>) -> Option<u32> { + for (a, _) in arr { + if a % 2 == 0 { + return Some(a); + } + } + None +} + +struct Data { + name: String, + is_true: bool, +} +fn with_struct(arr: Vec<Data>) -> Option<Data> { + for el in arr { + if el.name.len() == 10 { + return Some(el); + } + } + None +} + +struct Tuple(usize, usize); +fn with_tuple_struct(arr: Vec<Tuple>) -> Option<usize> { + for Tuple(a, _) in arr { + if a >= 3 { + return Some(a); + } + } + None +} + +struct A; +impl A { + fn should_keep(&self) -> bool { + true + } +} +fn with_method_call(arr: Vec<A>) -> Option<A> { + for el in arr { + if el.should_keep() { + return Some(el); + } + } + None +} + +fn with_closure(arr: Vec<u32>) -> Option<u32> { + let f = |el: u32| -> u32 { el + 10 }; + for el in arr { + if f(el) == 20 { + return Some(el); + } + } + None +} + +fn with_closure2(arr: HashMap<String, i32>) -> Option<i32> { + let f = |el: i32| -> bool { el == 10 }; + for &el in arr.values() { + if f(el) { + return Some(el); + } + } + None +} + +fn with_bool(arr: Vec<Data>) -> Option<Data> { + for el in arr { + if el.is_true { + return Some(el); + } + } + None +} + +fn with_side_effects(arr: Vec<u32>) -> Option<u32> { + for v in arr { + if v == 1 { + println!("side effect"); + return Some(v); + } + } + None +} + +fn with_else(arr: Vec<u32>) -> Option<u32> { + for el in arr { + if el % 2 == 0 { + return Some(el); + } else { + println!("{}", el); + } + } + None +} + +fn tuple_with_ref(v: [(u8, &u8); 3]) -> Option<u8> { + for (_, &x) in v { + if x > 10 { + return Some(x); + } + } + None +} + +fn ref_to_tuple_with_ref(v: &[(u8, &u8)]) -> Option<u8> { + for &(_, &x) in v { + if x > 10 { + return Some(x); + } + } + None +} + +fn explicit_ret(arr: Vec<i32>) -> Option<i32> { + for x in arr { + if x >= 5 { + return Some(x); + } + } + return None; +} + +fn plus_one(a: i32) -> Option<i32> { + Some(a + 1) +} +fn fn_instead_of_some(a: &[i32]) -> Option<i32> { + for &x in a { + if x == 1 { + return plus_one(x); + } + } + None +} + +fn for_in_condition(a: &[i32], b: bool) -> Option<i32> { + if b { + for &x in a { + if x == 1 { + return Some(x); + } + } + } + None +} + +fn intermediate_statements(a: &[i32]) -> Option<i32> { + for &x in a { + if x == 1 { + return Some(x); + } + } + + println!("side effect"); + + None +} + +fn mixed_binding_modes(arr: Vec<(i32, String)>) -> Option<i32> { + for (x, mut s) in arr { + if x == 1 && s.as_mut_str().len() == 2 { + return Some(x); + } + } + None +} + +fn as_closure() { + #[rustfmt::skip] + let f = |arr: Vec<i32>| -> Option<i32> { + for x in arr { + if x < 1 { + return Some(x); + } + } + None + }; +} + +fn in_block(a: &[i32]) -> Option<i32> { + let should_be_none = { + for &x in a { + if x == 1 { + return Some(x); + } + } + None + }; + + assert!(should_be_none.is_none()); + + should_be_none +} + +// Not handled yet +fn mut_binding(v: Vec<String>) -> Option<String> { + for mut s in v { + if s.as_mut_str().len() > 1 { + return Some(s); + } + } + None +} + +fn subpattern(v: Vec<[u32; 32]>) -> Option<[u32; 32]> { + for a @ [first, ..] in v { + if a[12] == first { + return Some(a); + } + } + None +} + +fn two_bindings(v: Vec<(u8, u8)>) -> Option<u8> { + for (a, n) in v { + if a == n { + return Some(a); + } + } + None +} + +fn main() {} diff --git a/src/tools/clippy/tests/ui/manual_find_fixable.stderr b/src/tools/clippy/tests/ui/manual_find_fixable.stderr new file mode 100644 index 00000000000..dbc4ff69a74 --- /dev/null +++ b/src/tools/clippy/tests/ui/manual_find_fixable.stderr @@ -0,0 +1,142 @@ +error: manual implementation of `Iterator::find` + --> $DIR/manual_find_fixable.rs:11:5 + | +LL | / for &v in ARRAY { +LL | | if v == n { +LL | | return Some(v); +LL | | } +LL | | } +LL | | None + | |________^ help: replace with an iterator: `ARRAY.iter().find(|&&v| v == n).copied()` + | + = note: `-D clippy::manual-find` implied by `-D warnings` + +error: manual implementation of `Iterator::find` + --> $DIR/manual_find_fixable.rs:20:5 + | +LL | / for (a, _) in arr { +LL | | if a % 2 == 0 { +LL | | return Some(a); +LL | | } +LL | | } +LL | | None + | |________^ help: replace with an iterator: `arr.into_iter().map(|(a, _)| a).find(|&a| a % 2 == 0)` + +error: manual implementation of `Iterator::find` + --> $DIR/manual_find_fixable.rs:33:5 + | +LL | / for el in arr { +LL | | if el.name.len() == 10 { +LL | | return Some(el); +LL | | } +LL | | } +LL | | None + | |________^ help: replace with an iterator: `arr.into_iter().find(|el| el.name.len() == 10)` + | + = note: you may need to dereference some variables + +error: manual implementation of `Iterator::find` + --> $DIR/manual_find_fixable.rs:43:5 + | +LL | / for Tuple(a, _) in arr { +LL | | if a >= 3 { +LL | | return Some(a); +LL | | } +LL | | } +LL | | None + | |________^ help: replace with an iterator: `arr.into_iter().map(|Tuple(a, _)| a).find(|&a| a >= 3)` + +error: manual implementation of `Iterator::find` + --> $DIR/manual_find_fixable.rs:58:5 + | +LL | / for el in arr { +LL | | if el.should_keep() { +LL | | return Some(el); +LL | | } +LL | | } +LL | | None + | |________^ help: replace with an iterator: `arr.into_iter().find(|el| el.should_keep())` + | + = note: you may need to dereference some variables + +error: manual implementation of `Iterator::find` + --> $DIR/manual_find_fixable.rs:68:5 + | +LL | / for el in arr { +LL | | if f(el) == 20 { +LL | | return Some(el); +LL | | } +LL | | } +LL | | None + | |________^ help: replace with an iterator: `arr.into_iter().find(|&el| f(el) == 20)` + +error: manual implementation of `Iterator::find` + --> $DIR/manual_find_fixable.rs:78:5 + | +LL | / for &el in arr.values() { +LL | | if f(el) { +LL | | return Some(el); +LL | | } +LL | | } +LL | | None + | |________^ help: replace with an iterator: `arr.values().find(|&&el| f(el)).copied()` + +error: manual implementation of `Iterator::find` + --> $DIR/manual_find_fixable.rs:87:5 + | +LL | / for el in arr { +LL | | if el.is_true { +LL | | return Some(el); +LL | | } +LL | | } +LL | | None + | |________^ help: replace with an iterator: `arr.into_iter().find(|el| el.is_true)` + | + = note: you may need to dereference some variables + +error: manual implementation of `Iterator::find` + --> $DIR/manual_find_fixable.rs:117:5 + | +LL | / for (_, &x) in v { +LL | | if x > 10 { +LL | | return Some(x); +LL | | } +LL | | } +LL | | None + | |________^ help: replace with an iterator: `v.into_iter().map(|(_, &x)| x).find(|&x| x > 10)` + +error: manual implementation of `Iterator::find` + --> $DIR/manual_find_fixable.rs:126:5 + | +LL | / for &(_, &x) in v { +LL | | if x > 10 { +LL | | return Some(x); +LL | | } +LL | | } +LL | | None + | |________^ help: replace with an iterator: `v.iter().map(|&(_, &x)| x).find(|&x| x > 10)` + +error: manual implementation of `Iterator::find` + --> $DIR/manual_find_fixable.rs:135:5 + | +LL | / for x in arr { +LL | | if x >= 5 { +LL | | return Some(x); +LL | | } +LL | | } +LL | | return None; + | |________________^ help: replace with an iterator: `arr.into_iter().find(|&x| x >= 5)` + +error: manual implementation of `Iterator::find` + --> $DIR/manual_find_fixable.rs:190:9 + | +LL | / for x in arr { +LL | | if x < 1 { +LL | | return Some(x); +LL | | } +LL | | } +LL | | None + | |____________^ help: replace with an iterator: `arr.into_iter().find(|&x| x < 1)` + +error: aborting due to 12 previous errors + diff --git a/src/tools/clippy/tests/ui/manual_non_exhaustive_enum.rs b/src/tools/clippy/tests/ui/manual_non_exhaustive_enum.rs index f23c6d69b4c..03b2433f666 100644 --- a/src/tools/clippy/tests/ui/manual_non_exhaustive_enum.rs +++ b/src/tools/clippy/tests/ui/manual_non_exhaustive_enum.rs @@ -1,3 +1,4 @@ +#![feature(lint_reasons)] #![warn(clippy::manual_non_exhaustive)] #![allow(unused)] @@ -75,4 +76,12 @@ fn foo(x: &mut UsedHidden) { } } +#[expect(clippy::manual_non_exhaustive)] +enum ExpectLint { + A, + B, + #[doc(hidden)] + _C, +} + fn main() {} diff --git a/src/tools/clippy/tests/ui/manual_non_exhaustive_enum.stderr b/src/tools/clippy/tests/ui/manual_non_exhaustive_enum.stderr index 317a45d2cbd..144fe86df55 100644 --- a/src/tools/clippy/tests/ui/manual_non_exhaustive_enum.stderr +++ b/src/tools/clippy/tests/ui/manual_non_exhaustive_enum.stderr @@ -1,5 +1,5 @@ error: this seems like a manual implementation of the non-exhaustive pattern - --> $DIR/manual_non_exhaustive_enum.rs:4:1 + --> $DIR/manual_non_exhaustive_enum.rs:5:1 | LL | enum E { | ^----- @@ -15,13 +15,13 @@ LL | | } | = note: `-D clippy::manual-non-exhaustive` implied by `-D warnings` help: remove this variant - --> $DIR/manual_non_exhaustive_enum.rs:8:5 + --> $DIR/manual_non_exhaustive_enum.rs:9:5 | LL | _C, | ^^ error: this seems like a manual implementation of the non-exhaustive pattern - --> $DIR/manual_non_exhaustive_enum.rs:13:1 + --> $DIR/manual_non_exhaustive_enum.rs:14:1 | LL | / enum Ep { LL | | A, @@ -32,7 +32,7 @@ LL | | } | |_^ | help: remove this variant - --> $DIR/manual_non_exhaustive_enum.rs:17:5 + --> $DIR/manual_non_exhaustive_enum.rs:18:5 | LL | _C, | ^^ diff --git a/src/tools/clippy/tests/ui/manual_rem_euclid.fixed b/src/tools/clippy/tests/ui/manual_rem_euclid.fixed new file mode 100644 index 00000000000..5601c96c10b --- /dev/null +++ b/src/tools/clippy/tests/ui/manual_rem_euclid.fixed @@ -0,0 +1,55 @@ +// run-rustfix +// aux-build:macro_rules.rs + +#![warn(clippy::manual_rem_euclid)] + +#[macro_use] +extern crate macro_rules; + +macro_rules! internal_rem_euclid { + () => { + let value: i32 = 5; + let _: i32 = value.rem_euclid(4); + }; +} + +fn main() { + let value: i32 = 5; + + let _: i32 = value.rem_euclid(4); + let _: i32 = value.rem_euclid(4); + let _: i32 = value.rem_euclid(4); + let _: i32 = value.rem_euclid(4); + let _: i32 = 1 + value.rem_euclid(4); + + let _: i32 = (3 + value % 4) % 4; + let _: i32 = (-4 + value % -4) % -4; + let _: i32 = ((5 % 4) + 4) % 4; + + // Make sure the lint does not trigger if it would cause an error, like with an ambiguous + // integer type + let not_annotated = 24; + let _ = ((not_annotated % 4) + 4) % 4; + let inferred: _ = 24; + let _ = ((inferred % 4) + 4) % 4; + + // For lint to apply the constant must always be on the RHS of the previous value for % + let _: i32 = 4 % ((value % 4) + 4); + let _: i32 = ((4 % value) + 4) % 4; + + // Lint in internal macros + internal_rem_euclid!(); + + // Do not lint in external macros + manual_rem_euclid!(); +} + +// Should lint for params too +pub fn rem_euclid_4(num: i32) -> i32 { + num.rem_euclid(4) +} + +// Constant version came later, should still lint +pub const fn const_rem_euclid_4(num: i32) -> i32 { + num.rem_euclid(4) +} diff --git a/src/tools/clippy/tests/ui/manual_rem_euclid.rs b/src/tools/clippy/tests/ui/manual_rem_euclid.rs new file mode 100644 index 00000000000..52135be26b7 --- /dev/null +++ b/src/tools/clippy/tests/ui/manual_rem_euclid.rs @@ -0,0 +1,55 @@ +// run-rustfix +// aux-build:macro_rules.rs + +#![warn(clippy::manual_rem_euclid)] + +#[macro_use] +extern crate macro_rules; + +macro_rules! internal_rem_euclid { + () => { + let value: i32 = 5; + let _: i32 = ((value % 4) + 4) % 4; + }; +} + +fn main() { + let value: i32 = 5; + + let _: i32 = ((value % 4) + 4) % 4; + let _: i32 = (4 + (value % 4)) % 4; + let _: i32 = (value % 4 + 4) % 4; + let _: i32 = (4 + value % 4) % 4; + let _: i32 = 1 + (4 + value % 4) % 4; + + let _: i32 = (3 + value % 4) % 4; + let _: i32 = (-4 + value % -4) % -4; + let _: i32 = ((5 % 4) + 4) % 4; + + // Make sure the lint does not trigger if it would cause an error, like with an ambiguous + // integer type + let not_annotated = 24; + let _ = ((not_annotated % 4) + 4) % 4; + let inferred: _ = 24; + let _ = ((inferred % 4) + 4) % 4; + + // For lint to apply the constant must always be on the RHS of the previous value for % + let _: i32 = 4 % ((value % 4) + 4); + let _: i32 = ((4 % value) + 4) % 4; + + // Lint in internal macros + internal_rem_euclid!(); + + // Do not lint in external macros + manual_rem_euclid!(); +} + +// Should lint for params too +pub fn rem_euclid_4(num: i32) -> i32 { + ((num % 4) + 4) % 4 +} + +// Constant version came later, should still lint +pub const fn const_rem_euclid_4(num: i32) -> i32 { + ((num % 4) + 4) % 4 +} diff --git a/src/tools/clippy/tests/ui/manual_rem_euclid.stderr b/src/tools/clippy/tests/ui/manual_rem_euclid.stderr new file mode 100644 index 00000000000..a237fd0213c --- /dev/null +++ b/src/tools/clippy/tests/ui/manual_rem_euclid.stderr @@ -0,0 +1,57 @@ +error: manual `rem_euclid` implementation + --> $DIR/manual_rem_euclid.rs:19:18 + | +LL | let _: i32 = ((value % 4) + 4) % 4; + | ^^^^^^^^^^^^^^^^^^^^^ help: consider using: `value.rem_euclid(4)` + | + = note: `-D clippy::manual-rem-euclid` implied by `-D warnings` + +error: manual `rem_euclid` implementation + --> $DIR/manual_rem_euclid.rs:20:18 + | +LL | let _: i32 = (4 + (value % 4)) % 4; + | ^^^^^^^^^^^^^^^^^^^^^ help: consider using: `value.rem_euclid(4)` + +error: manual `rem_euclid` implementation + --> $DIR/manual_rem_euclid.rs:21:18 + | +LL | let _: i32 = (value % 4 + 4) % 4; + | ^^^^^^^^^^^^^^^^^^^ help: consider using: `value.rem_euclid(4)` + +error: manual `rem_euclid` implementation + --> $DIR/manual_rem_euclid.rs:22:18 + | +LL | let _: i32 = (4 + value % 4) % 4; + | ^^^^^^^^^^^^^^^^^^^ help: consider using: `value.rem_euclid(4)` + +error: manual `rem_euclid` implementation + --> $DIR/manual_rem_euclid.rs:23:22 + | +LL | let _: i32 = 1 + (4 + value % 4) % 4; + | ^^^^^^^^^^^^^^^^^^^ help: consider using: `value.rem_euclid(4)` + +error: manual `rem_euclid` implementation + --> $DIR/manual_rem_euclid.rs:12:22 + | +LL | let _: i32 = ((value % 4) + 4) % 4; + | ^^^^^^^^^^^^^^^^^^^^^ help: consider using: `value.rem_euclid(4)` +... +LL | internal_rem_euclid!(); + | ---------------------- in this macro invocation + | + = note: this error originates in the macro `internal_rem_euclid` (in Nightly builds, run with -Z macro-backtrace for more info) + +error: manual `rem_euclid` implementation + --> $DIR/manual_rem_euclid.rs:49:5 + | +LL | ((num % 4) + 4) % 4 + | ^^^^^^^^^^^^^^^^^^^ help: consider using: `num.rem_euclid(4)` + +error: manual `rem_euclid` implementation + --> $DIR/manual_rem_euclid.rs:54:5 + | +LL | ((num % 4) + 4) % 4 + | ^^^^^^^^^^^^^^^^^^^ help: consider using: `num.rem_euclid(4)` + +error: aborting due to 8 previous errors + diff --git a/src/tools/clippy/tests/ui/manual_retain.fixed b/src/tools/clippy/tests/ui/manual_retain.fixed new file mode 100644 index 00000000000..fba503a2066 --- /dev/null +++ b/src/tools/clippy/tests/ui/manual_retain.fixed @@ -0,0 +1,240 @@ +// run-rustfix +#![feature(custom_inner_attributes)] +#![warn(clippy::manual_retain)] +#![allow(unused)] +use std::collections::BTreeMap; +use std::collections::BTreeSet; +use std::collections::BinaryHeap; +use std::collections::HashMap; +use std::collections::HashSet; +use std::collections::VecDeque; + +fn main() { + binary_heap_retain(); + btree_set_retain(); + btree_map_retain(); + hash_set_retain(); + hash_map_retain(); + string_retain(); + vec_deque_retain(); + vec_retain(); + _msrv_153(); + _msrv_126(); + _msrv_118(); +} + +fn binary_heap_retain() { + // NOTE: Do not lint now, because binary_heap_retain is nighyly API. + // And we need to add a test case for msrv if we update this implmention. + // https://github.com/rust-lang/rust/issues/71503 + let mut heap = BinaryHeap::from([1, 2, 3]); + heap = heap.into_iter().filter(|x| x % 2 == 0).collect(); + heap = heap.iter().filter(|&x| x % 2 == 0).copied().collect(); + heap = heap.iter().filter(|&x| x % 2 == 0).cloned().collect(); + + // Do not lint, because type conversion is performed + heap = heap.into_iter().filter(|x| x % 2 == 0).collect::<BinaryHeap<i8>>(); + heap = heap.iter().filter(|&x| x % 2 == 0).copied().collect::<BinaryHeap<i8>>(); + heap = heap.iter().filter(|&x| x % 2 == 0).cloned().collect::<BinaryHeap<i8>>(); + + // Do not lint, because this expression is not assign. + let mut bar: BinaryHeap<i8> = heap.iter().filter(|&x| x % 2 == 0).copied().collect(); + let mut foobar: BinaryHeap<i8> = heap.into_iter().filter(|x| x % 2 == 0).collect(); + + // Do not lint, because it is an assignment to a different variable. + bar = foobar.iter().filter(|&x| x % 2 == 0).copied().collect(); + bar = foobar.into_iter().filter(|x| x % 2 == 0).collect(); +} + +fn btree_map_retain() { + let mut btree_map: BTreeMap<i8, i8> = (0..8).map(|x| (x, x * 10)).collect(); + // Do lint. + btree_map.retain(|k, _| k % 2 == 0); + btree_map.retain(|_, &mut v| v % 2 == 0); + btree_map.retain(|k, &mut v| (k % 2 == 0) && (v % 2 == 0)); + + // Do not lint. + btree_map = btree_map + .into_iter() + .filter(|(x, _)| x % 2 == 0) + .collect::<BTreeMap<i8, i8>>(); + + // Do not lint, because this expression is not assign. + let mut foobar: BTreeMap<i8, i8> = btree_map.into_iter().filter(|(k, _)| k % 2 == 0).collect(); + + // Do not lint, because it is an assignment to a different variable. + btree_map = foobar.into_iter().filter(|(k, _)| k % 2 == 0).collect(); +} + +fn btree_set_retain() { + let mut btree_set = BTreeSet::from([1, 2, 3, 4, 5, 6]); + + // Do lint. + btree_set.retain(|x| x % 2 == 0); + btree_set.retain(|x| x % 2 == 0); + btree_set.retain(|x| x % 2 == 0); + + // Do not lint, because type conversion is performed + btree_set = btree_set + .iter() + .filter(|&x| x % 2 == 0) + .copied() + .collect::<BTreeSet<i8>>(); + + btree_set = btree_set + .iter() + .filter(|&x| x % 2 == 0) + .cloned() + .collect::<BTreeSet<i8>>(); + + btree_set = btree_set.into_iter().filter(|x| x % 2 == 0).collect::<BTreeSet<i8>>(); + + // Do not lint, because this expression is not assign. + let mut foobar: BTreeSet<i8> = btree_set.iter().filter(|&x| x % 2 == 0).copied().collect(); + let mut bar: BTreeSet<i8> = btree_set.into_iter().filter(|x| x % 2 == 0).collect(); + + // Do not lint, because it is an assignment to a different variable. + bar = foobar.iter().filter(|&x| x % 2 == 0).copied().collect(); + bar = foobar.iter().filter(|&x| x % 2 == 0).cloned().collect(); + bar = foobar.into_iter().filter(|x| x % 2 == 0).collect(); +} + +fn hash_map_retain() { + let mut hash_map: HashMap<i8, i8> = (0..8).map(|x| (x, x * 10)).collect(); + // Do lint. + hash_map.retain(|k, _| k % 2 == 0); + hash_map.retain(|_, &mut v| v % 2 == 0); + hash_map.retain(|k, &mut v| (k % 2 == 0) && (v % 2 == 0)); + + // Do not lint. + hash_map = hash_map + .into_iter() + .filter(|(x, _)| x % 2 == 0) + .collect::<HashMap<i8, i8>>(); + + // Do not lint, because this expression is not assign. + let mut foobar: HashMap<i8, i8> = hash_map.into_iter().filter(|(k, _)| k % 2 == 0).collect(); + + // Do not lint, because it is an assignment to a different variable. + hash_map = foobar.into_iter().filter(|(k, _)| k % 2 == 0).collect(); +} + +fn hash_set_retain() { + let mut hash_set = HashSet::from([1, 2, 3, 4, 5, 6]); + // Do lint. + hash_set.retain(|x| x % 2 == 0); + hash_set.retain(|x| x % 2 == 0); + hash_set.retain(|x| x % 2 == 0); + + // Do not lint, because type conversion is performed + hash_set = hash_set.into_iter().filter(|x| x % 2 == 0).collect::<HashSet<i8>>(); + hash_set = hash_set + .iter() + .filter(|&x| x % 2 == 0) + .copied() + .collect::<HashSet<i8>>(); + + hash_set = hash_set + .iter() + .filter(|&x| x % 2 == 0) + .cloned() + .collect::<HashSet<i8>>(); + + // Do not lint, because this expression is not assign. + let mut bar: HashSet<i8> = hash_set.iter().filter(|&x| x % 2 == 0).copied().collect(); + let mut foobar: HashSet<i8> = hash_set.into_iter().filter(|x| x % 2 == 0).collect(); + + // Do not lint, because it is an assignment to a different variable. + bar = foobar.iter().filter(|&x| x % 2 == 0).copied().collect(); + bar = foobar.iter().filter(|&x| x % 2 == 0).cloned().collect(); + bar = foobar.into_iter().filter(|&x| x % 2 == 0).collect(); +} + +fn string_retain() { + let mut s = String::from("foobar"); + // Do lint. + s.retain(|c| c != 'o'); + + // Do not lint, because this expression is not assign. + let mut bar: String = s.chars().filter(|&c| c != 'o').to_owned().collect(); + + // Do not lint, because it is an assignment to a different variable. + s = bar.chars().filter(|&c| c != 'o').to_owned().collect(); +} + +fn vec_retain() { + let mut vec = vec![0, 1, 2]; + // Do lint. + vec.retain(|x| x % 2 == 0); + vec.retain(|x| x % 2 == 0); + vec.retain(|x| x % 2 == 0); + + // Do not lint, because type conversion is performed + vec = vec.into_iter().filter(|x| x % 2 == 0).collect::<Vec<i8>>(); + vec = vec.iter().filter(|&x| x % 2 == 0).copied().collect::<Vec<i8>>(); + vec = vec.iter().filter(|&x| x % 2 == 0).cloned().collect::<Vec<i8>>(); + + // Do not lint, because this expression is not assign. + let mut bar: Vec<i8> = vec.iter().filter(|&x| x % 2 == 0).copied().collect(); + let mut foobar: Vec<i8> = vec.into_iter().filter(|x| x % 2 == 0).collect(); + + // Do not lint, because it is an assignment to a different variable. + bar = foobar.iter().filter(|&x| x % 2 == 0).copied().collect(); + bar = foobar.iter().filter(|&x| x % 2 == 0).cloned().collect(); + bar = foobar.into_iter().filter(|x| x % 2 == 0).collect(); +} + +fn vec_deque_retain() { + let mut vec_deque = VecDeque::new(); + vec_deque.extend(1..5); + + // Do lint. + vec_deque.retain(|x| x % 2 == 0); + vec_deque.retain(|x| x % 2 == 0); + vec_deque.retain(|x| x % 2 == 0); + + // Do not lint, because type conversion is performed + vec_deque = vec_deque + .iter() + .filter(|&x| x % 2 == 0) + .copied() + .collect::<VecDeque<i8>>(); + vec_deque = vec_deque + .iter() + .filter(|&x| x % 2 == 0) + .cloned() + .collect::<VecDeque<i8>>(); + vec_deque = vec_deque.into_iter().filter(|x| x % 2 == 0).collect::<VecDeque<i8>>(); + + // Do not lint, because this expression is not assign. + let mut bar: VecDeque<i8> = vec_deque.iter().filter(|&x| x % 2 == 0).copied().collect(); + let mut foobar: VecDeque<i8> = vec_deque.into_iter().filter(|x| x % 2 == 0).collect(); + + // Do not lint, because it is an assignment to a different variable. + bar = foobar.iter().filter(|&x| x % 2 == 0).copied().collect(); + bar = foobar.iter().filter(|&x| x % 2 == 0).cloned().collect(); + bar = foobar.into_iter().filter(|x| x % 2 == 0).collect(); +} + +fn _msrv_153() { + #![clippy::msrv = "1.52"] + let mut btree_map: BTreeMap<i8, i8> = (0..8).map(|x| (x, x * 10)).collect(); + btree_map = btree_map.into_iter().filter(|(k, _)| k % 2 == 0).collect(); + + let mut btree_set = BTreeSet::from([1, 2, 3, 4, 5, 6]); + btree_set = btree_set.iter().filter(|&x| x % 2 == 0).copied().collect(); +} + +fn _msrv_126() { + #![clippy::msrv = "1.25"] + let mut s = String::from("foobar"); + s = s.chars().filter(|&c| c != 'o').to_owned().collect(); +} + +fn _msrv_118() { + #![clippy::msrv = "1.17"] + let mut hash_set = HashSet::from([1, 2, 3, 4, 5, 6]); + hash_set = hash_set.into_iter().filter(|x| x % 2 == 0).collect(); + let mut hash_map: HashMap<i8, i8> = (0..8).map(|x| (x, x * 10)).collect(); + hash_map = hash_map.into_iter().filter(|(k, _)| k % 2 == 0).collect(); +} diff --git a/src/tools/clippy/tests/ui/manual_retain.rs b/src/tools/clippy/tests/ui/manual_retain.rs new file mode 100644 index 00000000000..81a849fe768 --- /dev/null +++ b/src/tools/clippy/tests/ui/manual_retain.rs @@ -0,0 +1,246 @@ +// run-rustfix +#![feature(custom_inner_attributes)] +#![warn(clippy::manual_retain)] +#![allow(unused)] +use std::collections::BTreeMap; +use std::collections::BTreeSet; +use std::collections::BinaryHeap; +use std::collections::HashMap; +use std::collections::HashSet; +use std::collections::VecDeque; + +fn main() { + binary_heap_retain(); + btree_set_retain(); + btree_map_retain(); + hash_set_retain(); + hash_map_retain(); + string_retain(); + vec_deque_retain(); + vec_retain(); + _msrv_153(); + _msrv_126(); + _msrv_118(); +} + +fn binary_heap_retain() { + // NOTE: Do not lint now, because binary_heap_retain is nighyly API. + // And we need to add a test case for msrv if we update this implmention. + // https://github.com/rust-lang/rust/issues/71503 + let mut heap = BinaryHeap::from([1, 2, 3]); + heap = heap.into_iter().filter(|x| x % 2 == 0).collect(); + heap = heap.iter().filter(|&x| x % 2 == 0).copied().collect(); + heap = heap.iter().filter(|&x| x % 2 == 0).cloned().collect(); + + // Do not lint, because type conversion is performed + heap = heap.into_iter().filter(|x| x % 2 == 0).collect::<BinaryHeap<i8>>(); + heap = heap.iter().filter(|&x| x % 2 == 0).copied().collect::<BinaryHeap<i8>>(); + heap = heap.iter().filter(|&x| x % 2 == 0).cloned().collect::<BinaryHeap<i8>>(); + + // Do not lint, because this expression is not assign. + let mut bar: BinaryHeap<i8> = heap.iter().filter(|&x| x % 2 == 0).copied().collect(); + let mut foobar: BinaryHeap<i8> = heap.into_iter().filter(|x| x % 2 == 0).collect(); + + // Do not lint, because it is an assignment to a different variable. + bar = foobar.iter().filter(|&x| x % 2 == 0).copied().collect(); + bar = foobar.into_iter().filter(|x| x % 2 == 0).collect(); +} + +fn btree_map_retain() { + let mut btree_map: BTreeMap<i8, i8> = (0..8).map(|x| (x, x * 10)).collect(); + // Do lint. + btree_map = btree_map.into_iter().filter(|(k, _)| k % 2 == 0).collect(); + btree_map = btree_map.into_iter().filter(|(_, v)| v % 2 == 0).collect(); + btree_map = btree_map + .into_iter() + .filter(|(k, v)| (k % 2 == 0) && (v % 2 == 0)) + .collect(); + + // Do not lint. + btree_map = btree_map + .into_iter() + .filter(|(x, _)| x % 2 == 0) + .collect::<BTreeMap<i8, i8>>(); + + // Do not lint, because this expression is not assign. + let mut foobar: BTreeMap<i8, i8> = btree_map.into_iter().filter(|(k, _)| k % 2 == 0).collect(); + + // Do not lint, because it is an assignment to a different variable. + btree_map = foobar.into_iter().filter(|(k, _)| k % 2 == 0).collect(); +} + +fn btree_set_retain() { + let mut btree_set = BTreeSet::from([1, 2, 3, 4, 5, 6]); + + // Do lint. + btree_set = btree_set.iter().filter(|&x| x % 2 == 0).copied().collect(); + btree_set = btree_set.iter().filter(|&x| x % 2 == 0).cloned().collect(); + btree_set = btree_set.into_iter().filter(|x| x % 2 == 0).collect(); + + // Do not lint, because type conversion is performed + btree_set = btree_set + .iter() + .filter(|&x| x % 2 == 0) + .copied() + .collect::<BTreeSet<i8>>(); + + btree_set = btree_set + .iter() + .filter(|&x| x % 2 == 0) + .cloned() + .collect::<BTreeSet<i8>>(); + + btree_set = btree_set.into_iter().filter(|x| x % 2 == 0).collect::<BTreeSet<i8>>(); + + // Do not lint, because this expression is not assign. + let mut foobar: BTreeSet<i8> = btree_set.iter().filter(|&x| x % 2 == 0).copied().collect(); + let mut bar: BTreeSet<i8> = btree_set.into_iter().filter(|x| x % 2 == 0).collect(); + + // Do not lint, because it is an assignment to a different variable. + bar = foobar.iter().filter(|&x| x % 2 == 0).copied().collect(); + bar = foobar.iter().filter(|&x| x % 2 == 0).cloned().collect(); + bar = foobar.into_iter().filter(|x| x % 2 == 0).collect(); +} + +fn hash_map_retain() { + let mut hash_map: HashMap<i8, i8> = (0..8).map(|x| (x, x * 10)).collect(); + // Do lint. + hash_map = hash_map.into_iter().filter(|(k, _)| k % 2 == 0).collect(); + hash_map = hash_map.into_iter().filter(|(_, v)| v % 2 == 0).collect(); + hash_map = hash_map + .into_iter() + .filter(|(k, v)| (k % 2 == 0) && (v % 2 == 0)) + .collect(); + + // Do not lint. + hash_map = hash_map + .into_iter() + .filter(|(x, _)| x % 2 == 0) + .collect::<HashMap<i8, i8>>(); + + // Do not lint, because this expression is not assign. + let mut foobar: HashMap<i8, i8> = hash_map.into_iter().filter(|(k, _)| k % 2 == 0).collect(); + + // Do not lint, because it is an assignment to a different variable. + hash_map = foobar.into_iter().filter(|(k, _)| k % 2 == 0).collect(); +} + +fn hash_set_retain() { + let mut hash_set = HashSet::from([1, 2, 3, 4, 5, 6]); + // Do lint. + hash_set = hash_set.into_iter().filter(|x| x % 2 == 0).collect(); + hash_set = hash_set.iter().filter(|&x| x % 2 == 0).copied().collect(); + hash_set = hash_set.iter().filter(|&x| x % 2 == 0).cloned().collect(); + + // Do not lint, because type conversion is performed + hash_set = hash_set.into_iter().filter(|x| x % 2 == 0).collect::<HashSet<i8>>(); + hash_set = hash_set + .iter() + .filter(|&x| x % 2 == 0) + .copied() + .collect::<HashSet<i8>>(); + + hash_set = hash_set + .iter() + .filter(|&x| x % 2 == 0) + .cloned() + .collect::<HashSet<i8>>(); + + // Do not lint, because this expression is not assign. + let mut bar: HashSet<i8> = hash_set.iter().filter(|&x| x % 2 == 0).copied().collect(); + let mut foobar: HashSet<i8> = hash_set.into_iter().filter(|x| x % 2 == 0).collect(); + + // Do not lint, because it is an assignment to a different variable. + bar = foobar.iter().filter(|&x| x % 2 == 0).copied().collect(); + bar = foobar.iter().filter(|&x| x % 2 == 0).cloned().collect(); + bar = foobar.into_iter().filter(|&x| x % 2 == 0).collect(); +} + +fn string_retain() { + let mut s = String::from("foobar"); + // Do lint. + s = s.chars().filter(|&c| c != 'o').to_owned().collect(); + + // Do not lint, because this expression is not assign. + let mut bar: String = s.chars().filter(|&c| c != 'o').to_owned().collect(); + + // Do not lint, because it is an assignment to a different variable. + s = bar.chars().filter(|&c| c != 'o').to_owned().collect(); +} + +fn vec_retain() { + let mut vec = vec![0, 1, 2]; + // Do lint. + vec = vec.iter().filter(|&x| x % 2 == 0).copied().collect(); + vec = vec.iter().filter(|&x| x % 2 == 0).cloned().collect(); + vec = vec.into_iter().filter(|x| x % 2 == 0).collect(); + + // Do not lint, because type conversion is performed + vec = vec.into_iter().filter(|x| x % 2 == 0).collect::<Vec<i8>>(); + vec = vec.iter().filter(|&x| x % 2 == 0).copied().collect::<Vec<i8>>(); + vec = vec.iter().filter(|&x| x % 2 == 0).cloned().collect::<Vec<i8>>(); + + // Do not lint, because this expression is not assign. + let mut bar: Vec<i8> = vec.iter().filter(|&x| x % 2 == 0).copied().collect(); + let mut foobar: Vec<i8> = vec.into_iter().filter(|x| x % 2 == 0).collect(); + + // Do not lint, because it is an assignment to a different variable. + bar = foobar.iter().filter(|&x| x % 2 == 0).copied().collect(); + bar = foobar.iter().filter(|&x| x % 2 == 0).cloned().collect(); + bar = foobar.into_iter().filter(|x| x % 2 == 0).collect(); +} + +fn vec_deque_retain() { + let mut vec_deque = VecDeque::new(); + vec_deque.extend(1..5); + + // Do lint. + vec_deque = vec_deque.iter().filter(|&x| x % 2 == 0).copied().collect(); + vec_deque = vec_deque.iter().filter(|&x| x % 2 == 0).cloned().collect(); + vec_deque = vec_deque.into_iter().filter(|x| x % 2 == 0).collect(); + + // Do not lint, because type conversion is performed + vec_deque = vec_deque + .iter() + .filter(|&x| x % 2 == 0) + .copied() + .collect::<VecDeque<i8>>(); + vec_deque = vec_deque + .iter() + .filter(|&x| x % 2 == 0) + .cloned() + .collect::<VecDeque<i8>>(); + vec_deque = vec_deque.into_iter().filter(|x| x % 2 == 0).collect::<VecDeque<i8>>(); + + // Do not lint, because this expression is not assign. + let mut bar: VecDeque<i8> = vec_deque.iter().filter(|&x| x % 2 == 0).copied().collect(); + let mut foobar: VecDeque<i8> = vec_deque.into_iter().filter(|x| x % 2 == 0).collect(); + + // Do not lint, because it is an assignment to a different variable. + bar = foobar.iter().filter(|&x| x % 2 == 0).copied().collect(); + bar = foobar.iter().filter(|&x| x % 2 == 0).cloned().collect(); + bar = foobar.into_iter().filter(|x| x % 2 == 0).collect(); +} + +fn _msrv_153() { + #![clippy::msrv = "1.52"] + let mut btree_map: BTreeMap<i8, i8> = (0..8).map(|x| (x, x * 10)).collect(); + btree_map = btree_map.into_iter().filter(|(k, _)| k % 2 == 0).collect(); + + let mut btree_set = BTreeSet::from([1, 2, 3, 4, 5, 6]); + btree_set = btree_set.iter().filter(|&x| x % 2 == 0).copied().collect(); +} + +fn _msrv_126() { + #![clippy::msrv = "1.25"] + let mut s = String::from("foobar"); + s = s.chars().filter(|&c| c != 'o').to_owned().collect(); +} + +fn _msrv_118() { + #![clippy::msrv = "1.17"] + let mut hash_set = HashSet::from([1, 2, 3, 4, 5, 6]); + hash_set = hash_set.into_iter().filter(|x| x % 2 == 0).collect(); + let mut hash_map: HashMap<i8, i8> = (0..8).map(|x| (x, x * 10)).collect(); + hash_map = hash_map.into_iter().filter(|(k, _)| k % 2 == 0).collect(); +} diff --git a/src/tools/clippy/tests/ui/manual_retain.stderr b/src/tools/clippy/tests/ui/manual_retain.stderr new file mode 100644 index 00000000000..ec635919b48 --- /dev/null +++ b/src/tools/clippy/tests/ui/manual_retain.stderr @@ -0,0 +1,124 @@ +error: this expression can be written more simply using `.retain()` + --> $DIR/manual_retain.rs:52:5 + | +LL | btree_map = btree_map.into_iter().filter(|(k, _)| k % 2 == 0).collect(); + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: consider calling `.retain()` instead: `btree_map.retain(|k, _| k % 2 == 0)` + | + = note: `-D clippy::manual-retain` implied by `-D warnings` + +error: this expression can be written more simply using `.retain()` + --> $DIR/manual_retain.rs:53:5 + | +LL | btree_map = btree_map.into_iter().filter(|(_, v)| v % 2 == 0).collect(); + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: consider calling `.retain()` instead: `btree_map.retain(|_, &mut v| v % 2 == 0)` + +error: this expression can be written more simply using `.retain()` + --> $DIR/manual_retain.rs:54:5 + | +LL | / btree_map = btree_map +LL | | .into_iter() +LL | | .filter(|(k, v)| (k % 2 == 0) && (v % 2 == 0)) +LL | | .collect(); + | |__________________^ help: consider calling `.retain()` instead: `btree_map.retain(|k, &mut v| (k % 2 == 0) && (v % 2 == 0))` + +error: this expression can be written more simply using `.retain()` + --> $DIR/manual_retain.rs:76:5 + | +LL | btree_set = btree_set.iter().filter(|&x| x % 2 == 0).copied().collect(); + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: consider calling `.retain()` instead: `btree_set.retain(|x| x % 2 == 0)` + +error: this expression can be written more simply using `.retain()` + --> $DIR/manual_retain.rs:77:5 + | +LL | btree_set = btree_set.iter().filter(|&x| x % 2 == 0).cloned().collect(); + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: consider calling `.retain()` instead: `btree_set.retain(|x| x % 2 == 0)` + +error: this expression can be written more simply using `.retain()` + --> $DIR/manual_retain.rs:78:5 + | +LL | btree_set = btree_set.into_iter().filter(|x| x % 2 == 0).collect(); + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: consider calling `.retain()` instead: `btree_set.retain(|x| x % 2 == 0)` + +error: this expression can be written more simply using `.retain()` + --> $DIR/manual_retain.rs:108:5 + | +LL | hash_map = hash_map.into_iter().filter(|(k, _)| k % 2 == 0).collect(); + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: consider calling `.retain()` instead: `hash_map.retain(|k, _| k % 2 == 0)` + +error: this expression can be written more simply using `.retain()` + --> $DIR/manual_retain.rs:109:5 + | +LL | hash_map = hash_map.into_iter().filter(|(_, v)| v % 2 == 0).collect(); + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: consider calling `.retain()` instead: `hash_map.retain(|_, &mut v| v % 2 == 0)` + +error: this expression can be written more simply using `.retain()` + --> $DIR/manual_retain.rs:110:5 + | +LL | / hash_map = hash_map +LL | | .into_iter() +LL | | .filter(|(k, v)| (k % 2 == 0) && (v % 2 == 0)) +LL | | .collect(); + | |__________________^ help: consider calling `.retain()` instead: `hash_map.retain(|k, &mut v| (k % 2 == 0) && (v % 2 == 0))` + +error: this expression can be written more simply using `.retain()` + --> $DIR/manual_retain.rs:131:5 + | +LL | hash_set = hash_set.into_iter().filter(|x| x % 2 == 0).collect(); + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: consider calling `.retain()` instead: `hash_set.retain(|x| x % 2 == 0)` + +error: this expression can be written more simply using `.retain()` + --> $DIR/manual_retain.rs:132:5 + | +LL | hash_set = hash_set.iter().filter(|&x| x % 2 == 0).copied().collect(); + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: consider calling `.retain()` instead: `hash_set.retain(|x| x % 2 == 0)` + +error: this expression can be written more simply using `.retain()` + --> $DIR/manual_retain.rs:133:5 + | +LL | hash_set = hash_set.iter().filter(|&x| x % 2 == 0).cloned().collect(); + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: consider calling `.retain()` instead: `hash_set.retain(|x| x % 2 == 0)` + +error: this expression can be written more simply using `.retain()` + --> $DIR/manual_retain.rs:162:5 + | +LL | s = s.chars().filter(|&c| c != 'o').to_owned().collect(); + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: consider calling `.retain()` instead: `s.retain(|c| c != 'o')` + +error: this expression can be written more simply using `.retain()` + --> $DIR/manual_retain.rs:174:5 + | +LL | vec = vec.iter().filter(|&x| x % 2 == 0).copied().collect(); + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: consider calling `.retain()` instead: `vec.retain(|x| x % 2 == 0)` + +error: this expression can be written more simply using `.retain()` + --> $DIR/manual_retain.rs:175:5 + | +LL | vec = vec.iter().filter(|&x| x % 2 == 0).cloned().collect(); + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: consider calling `.retain()` instead: `vec.retain(|x| x % 2 == 0)` + +error: this expression can be written more simply using `.retain()` + --> $DIR/manual_retain.rs:176:5 + | +LL | vec = vec.into_iter().filter(|x| x % 2 == 0).collect(); + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: consider calling `.retain()` instead: `vec.retain(|x| x % 2 == 0)` + +error: this expression can be written more simply using `.retain()` + --> $DIR/manual_retain.rs:198:5 + | +LL | vec_deque = vec_deque.iter().filter(|&x| x % 2 == 0).copied().collect(); + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: consider calling `.retain()` instead: `vec_deque.retain(|x| x % 2 == 0)` + +error: this expression can be written more simply using `.retain()` + --> $DIR/manual_retain.rs:199:5 + | +LL | vec_deque = vec_deque.iter().filter(|&x| x % 2 == 0).cloned().collect(); + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: consider calling `.retain()` instead: `vec_deque.retain(|x| x % 2 == 0)` + +error: this expression can be written more simply using `.retain()` + --> $DIR/manual_retain.rs:200:5 + | +LL | vec_deque = vec_deque.into_iter().filter(|x| x % 2 == 0).collect(); + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: consider calling `.retain()` instead: `vec_deque.retain(|x| x % 2 == 0)` + +error: aborting due to 19 previous errors + diff --git a/src/tools/clippy/tests/ui/methods.rs b/src/tools/clippy/tests/ui/methods.rs index 9805097084d..1970c2eae53 100644 --- a/src/tools/clippy/tests/ui/methods.rs +++ b/src/tools/clippy/tests/ui/methods.rs @@ -15,6 +15,7 @@ clippy::use_self, clippy::useless_format, clippy::wrong_self_convention, + clippy::unused_async, clippy::unused_self, unused )] diff --git a/src/tools/clippy/tests/ui/methods.stderr b/src/tools/clippy/tests/ui/methods.stderr index 6be38b24fbd..b63672dd6fd 100644 --- a/src/tools/clippy/tests/ui/methods.stderr +++ b/src/tools/clippy/tests/ui/methods.stderr @@ -1,5 +1,5 @@ error: methods called `new` usually return `Self` - --> $DIR/methods.rs:103:5 + --> $DIR/methods.rs:104:5 | LL | / fn new() -> i32 { LL | | 0 @@ -9,7 +9,7 @@ LL | | } = note: `-D clippy::new-ret-no-self` implied by `-D warnings` error: called `filter(..).next()` on an `Iterator`. This is more succinctly expressed by calling `.find(..)` instead - --> $DIR/methods.rs:124:13 + --> $DIR/methods.rs:125:13 | LL | let _ = v.iter().filter(|&x| { | _____________^ diff --git a/src/tools/clippy/tests/ui/min_rust_version_attr.rs b/src/tools/clippy/tests/ui/min_rust_version_attr.rs index f83c3e0e281..44e407bd1ab 100644 --- a/src/tools/clippy/tests/ui/min_rust_version_attr.rs +++ b/src/tools/clippy/tests/ui/min_rust_version_attr.rs @@ -155,6 +155,11 @@ fn cast_abs_to_unsigned() { assert_eq!(10u32, x.abs() as u32); } +fn manual_rem_euclid() { + let x: i32 = 10; + let _: i32 = ((x % 4) + 4) % 4; +} + fn main() { filter_map_next(); checked_conversion(); @@ -174,6 +179,7 @@ fn main() { int_from_bool(); err_expect(); cast_abs_to_unsigned(); + manual_rem_euclid(); } mod just_under_msrv { @@ -211,3 +217,12 @@ mod just_above_msrv { } } } + +mod const_rem_euclid { + #![feature(custom_inner_attributes)] + #![clippy::msrv = "1.50.0"] + + pub const fn const_rem_euclid_4(num: i32) -> i32 { + ((num % 4) + 4) % 4 + } +} diff --git a/src/tools/clippy/tests/ui/min_rust_version_attr.stderr b/src/tools/clippy/tests/ui/min_rust_version_attr.stderr index de225eb740d..b1c23b539ff 100644 --- a/src/tools/clippy/tests/ui/min_rust_version_attr.stderr +++ b/src/tools/clippy/tests/ui/min_rust_version_attr.stderr @@ -1,12 +1,12 @@ error: stripping a prefix manually - --> $DIR/min_rust_version_attr.rs:198:24 + --> $DIR/min_rust_version_attr.rs:204:24 | LL | assert_eq!(s["hello, ".len()..].to_uppercase(), "WORLD!"); | ^^^^^^^^^^^^^^^^^^^^ | = note: `-D clippy::manual-strip` implied by `-D warnings` note: the prefix was tested here - --> $DIR/min_rust_version_attr.rs:197:9 + --> $DIR/min_rust_version_attr.rs:203:9 | LL | if s.starts_with("hello, ") { | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ @@ -17,13 +17,13 @@ LL ~ assert_eq!(<stripped>.to_uppercase(), "WORLD!"); | error: stripping a prefix manually - --> $DIR/min_rust_version_attr.rs:210:24 + --> $DIR/min_rust_version_attr.rs:216:24 | LL | assert_eq!(s["hello, ".len()..].to_uppercase(), "WORLD!"); | ^^^^^^^^^^^^^^^^^^^^ | note: the prefix was tested here - --> $DIR/min_rust_version_attr.rs:209:9 + --> $DIR/min_rust_version_attr.rs:215:9 | LL | if s.starts_with("hello, ") { | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ diff --git a/src/tools/clippy/tests/ui/needless_borrow.fixed b/src/tools/clippy/tests/ui/needless_borrow.fixed index e7a483c0582..cb005122436 100644 --- a/src/tools/clippy/tests/ui/needless_borrow.fixed +++ b/src/tools/clippy/tests/ui/needless_borrow.fixed @@ -62,7 +62,18 @@ fn main() { 0 => &mut x, _ => &mut *x, }; - + let y: &mut i32 = match 0 { + // Lint here. The type given above triggers auto-borrow. + 0 => x, + _ => &mut *x, + }; + fn ref_mut_i32(_: &mut i32) {} + ref_mut_i32(match 0 { + // Lint here. The type given above triggers auto-borrow. + 0 => x, + _ => &mut *x, + }); + // use 'x' after to make sure it's still usable in the fixed code. *x = 5; let s = String::new(); @@ -74,6 +85,36 @@ fn main() { let _ = x.0; let x = &x as *const (i32, i32); let _ = unsafe { (*x).0 }; + + // Issue #8367 + trait Foo { + fn foo(self); + } + impl Foo for &'_ () { + fn foo(self) {} + } + (&()).foo(); // Don't lint. `()` doesn't implement `Foo` + (&()).foo(); + + impl Foo for i32 { + fn foo(self) {} + } + impl Foo for &'_ i32 { + fn foo(self) {} + } + (&5).foo(); // Don't lint. `5` will call `<i32 as Foo>::foo` + (&5).foo(); + + trait FooRef { + fn foo_ref(&self); + } + impl FooRef for () { + fn foo_ref(&self) {} + } + impl FooRef for &'_ () { + fn foo_ref(&self) {} + } + (&&()).foo_ref(); // Don't lint. `&()` will call `<() as FooRef>::foo_ref` } #[allow(clippy::needless_borrowed_reference)] diff --git a/src/tools/clippy/tests/ui/needless_borrow.rs b/src/tools/clippy/tests/ui/needless_borrow.rs index 1d6bf46405a..d636a401003 100644 --- a/src/tools/clippy/tests/ui/needless_borrow.rs +++ b/src/tools/clippy/tests/ui/needless_borrow.rs @@ -62,7 +62,18 @@ fn main() { 0 => &mut x, _ => &mut *x, }; - + let y: &mut i32 = match 0 { + // Lint here. The type given above triggers auto-borrow. + 0 => &mut x, + _ => &mut *x, + }; + fn ref_mut_i32(_: &mut i32) {} + ref_mut_i32(match 0 { + // Lint here. The type given above triggers auto-borrow. + 0 => &mut x, + _ => &mut *x, + }); + // use 'x' after to make sure it's still usable in the fixed code. *x = 5; let s = String::new(); @@ -74,6 +85,36 @@ fn main() { let _ = (&x).0; let x = &x as *const (i32, i32); let _ = unsafe { (&*x).0 }; + + // Issue #8367 + trait Foo { + fn foo(self); + } + impl Foo for &'_ () { + fn foo(self) {} + } + (&()).foo(); // Don't lint. `()` doesn't implement `Foo` + (&&()).foo(); + + impl Foo for i32 { + fn foo(self) {} + } + impl Foo for &'_ i32 { + fn foo(self) {} + } + (&5).foo(); // Don't lint. `5` will call `<i32 as Foo>::foo` + (&&5).foo(); + + trait FooRef { + fn foo_ref(&self); + } + impl FooRef for () { + fn foo_ref(&self) {} + } + impl FooRef for &'_ () { + fn foo_ref(&self) {} + } + (&&()).foo_ref(); // Don't lint. `&()` will call `<() as FooRef>::foo_ref` } #[allow(clippy::needless_borrowed_reference)] diff --git a/src/tools/clippy/tests/ui/needless_borrow.stderr b/src/tools/clippy/tests/ui/needless_borrow.stderr index be59d8f546d..8a2e2b98959 100644 --- a/src/tools/clippy/tests/ui/needless_borrow.stderr +++ b/src/tools/clippy/tests/ui/needless_borrow.stderr @@ -84,17 +84,41 @@ error: this expression creates a reference which is immediately dereferenced by LL | let y: &mut i32 = &mut &mut x; | ^^^^^^^^^^^ help: change this to: `x` +error: this expression creates a reference which is immediately dereferenced by the compiler + --> $DIR/needless_borrow.rs:67:14 + | +LL | 0 => &mut x, + | ^^^^^^ help: change this to: `x` + +error: this expression creates a reference which is immediately dereferenced by the compiler + --> $DIR/needless_borrow.rs:73:14 + | +LL | 0 => &mut x, + | ^^^^^^ help: change this to: `x` + error: this expression borrows a value the compiler would automatically borrow - --> $DIR/needless_borrow.rs:74:13 + --> $DIR/needless_borrow.rs:85:13 | LL | let _ = (&x).0; | ^^^^ help: change this to: `x` error: this expression borrows a value the compiler would automatically borrow - --> $DIR/needless_borrow.rs:76:22 + --> $DIR/needless_borrow.rs:87:22 | LL | let _ = unsafe { (&*x).0 }; | ^^^^^ help: change this to: `(*x)` -error: aborting due to 16 previous errors +error: this expression creates a reference which is immediately dereferenced by the compiler + --> $DIR/needless_borrow.rs:97:5 + | +LL | (&&()).foo(); + | ^^^^^^ help: change this to: `(&())` + +error: this expression creates a reference which is immediately dereferenced by the compiler + --> $DIR/needless_borrow.rs:106:5 + | +LL | (&&5).foo(); + | ^^^^^ help: change this to: `(&5)` + +error: aborting due to 20 previous errors diff --git a/src/tools/clippy/tests/ui/needless_borrow_pat.rs b/src/tools/clippy/tests/ui/needless_borrow_pat.rs index 04b6283da3c..222e8e61799 100644 --- a/src/tools/clippy/tests/ui/needless_borrow_pat.rs +++ b/src/tools/clippy/tests/ui/needless_borrow_pat.rs @@ -1,7 +1,7 @@ // FIXME: run-rustfix waiting on multi-span suggestions #![warn(clippy::needless_borrow)] -#![allow(clippy::needless_borrowed_reference)] +#![allow(clippy::needless_borrowed_reference, clippy::explicit_auto_deref)] fn f1(_: &str) {} macro_rules! m1 { diff --git a/src/tools/clippy/tests/ui/needless_pass_by_value.stderr b/src/tools/clippy/tests/ui/needless_pass_by_value.stderr index d960c86a9f0..38f33c53f12 100644 --- a/src/tools/clippy/tests/ui/needless_pass_by_value.stderr +++ b/src/tools/clippy/tests/ui/needless_pass_by_value.stderr @@ -124,7 +124,7 @@ help: consider marking this type as `Copy` --> $DIR/needless_pass_by_value.rs:123:1 | LL | struct CopyWrapper(u32); - | ^^^^^^^^^^^^^^^^^^^^^^^^ + | ^^^^^^^^^^^^^^^^^^ error: this argument is passed by value, but not consumed in the function body --> $DIR/needless_pass_by_value.rs:131:29 @@ -136,7 +136,7 @@ help: consider marking this type as `Copy` --> $DIR/needless_pass_by_value.rs:123:1 | LL | struct CopyWrapper(u32); - | ^^^^^^^^^^^^^^^^^^^^^^^^ + | ^^^^^^^^^^^^^^^^^^ error: this argument is passed by value, but not consumed in the function body --> $DIR/needless_pass_by_value.rs:131:45 @@ -148,7 +148,7 @@ help: consider marking this type as `Copy` --> $DIR/needless_pass_by_value.rs:123:1 | LL | struct CopyWrapper(u32); - | ^^^^^^^^^^^^^^^^^^^^^^^^ + | ^^^^^^^^^^^^^^^^^^ error: this argument is passed by value, but not consumed in the function body --> $DIR/needless_pass_by_value.rs:131:61 @@ -160,7 +160,7 @@ help: consider marking this type as `Copy` --> $DIR/needless_pass_by_value.rs:123:1 | LL | struct CopyWrapper(u32); - | ^^^^^^^^^^^^^^^^^^^^^^^^ + | ^^^^^^^^^^^^^^^^^^ error: this argument is passed by value, but not consumed in the function body --> $DIR/needless_pass_by_value.rs:143:40 diff --git a/src/tools/clippy/tests/ui/needless_return.fixed b/src/tools/clippy/tests/ui/needless_return.fixed index 7c828430b78..0bc0d0011ef 100644 --- a/src/tools/clippy/tests/ui/needless_return.fixed +++ b/src/tools/clippy/tests/ui/needless_return.fixed @@ -1,5 +1,6 @@ // run-rustfix +#![feature(lint_reasons)] #![feature(let_else)] #![allow(unused)] #![allow( @@ -10,6 +11,8 @@ )] #![warn(clippy::needless_return)] +use std::cell::RefCell; + macro_rules! the_answer { () => { 42 @@ -86,17 +89,15 @@ fn test_nested_match(x: u32) { } } -fn read_line() -> String { - use std::io::BufRead; - let stdin = ::std::io::stdin(); - return stdin.lock().lines().next().unwrap().unwrap(); +fn temporary_outlives_local() -> String { + let x = RefCell::<String>::default(); + return x.borrow().clone(); } fn borrows_but_not_last(value: bool) -> String { if value { - use std::io::BufRead; - let stdin = ::std::io::stdin(); - let _a = stdin.lock().lines().next().unwrap().unwrap(); + let x = RefCell::<String>::default(); + let _a = x.borrow().clone(); String::from("test") } else { String::new() @@ -197,17 +198,15 @@ async fn async_test_void_match(x: u32) { } } -async fn async_read_line() -> String { - use std::io::BufRead; - let stdin = ::std::io::stdin(); - return stdin.lock().lines().next().unwrap().unwrap(); +async fn async_temporary_outlives_local() -> String { + let x = RefCell::<String>::default(); + return x.borrow().clone(); } async fn async_borrows_but_not_last(value: bool) -> String { if value { - use std::io::BufRead; - let stdin = ::std::io::stdin(); - let _a = stdin.lock().lines().next().unwrap().unwrap(); + let x = RefCell::<String>::default(); + let _a = x.borrow().clone(); String::from("test") } else { String::new() @@ -229,4 +228,13 @@ fn needless_return_macro() -> String { format!("Hello {}", "world!") } +fn check_expect() -> bool { + if true { + // no error! + return true; + } + #[expect(clippy::needless_return)] + return true; +} + fn main() {} diff --git a/src/tools/clippy/tests/ui/needless_return.rs b/src/tools/clippy/tests/ui/needless_return.rs index fe82af00e67..eb9f72e8e78 100644 --- a/src/tools/clippy/tests/ui/needless_return.rs +++ b/src/tools/clippy/tests/ui/needless_return.rs @@ -1,5 +1,6 @@ // run-rustfix +#![feature(lint_reasons)] #![feature(let_else)] #![allow(unused)] #![allow( @@ -10,6 +11,8 @@ )] #![warn(clippy::needless_return)] +use std::cell::RefCell; + macro_rules! the_answer { () => { 42 @@ -86,17 +89,15 @@ fn test_nested_match(x: u32) { } } -fn read_line() -> String { - use std::io::BufRead; - let stdin = ::std::io::stdin(); - return stdin.lock().lines().next().unwrap().unwrap(); +fn temporary_outlives_local() -> String { + let x = RefCell::<String>::default(); + return x.borrow().clone(); } fn borrows_but_not_last(value: bool) -> String { if value { - use std::io::BufRead; - let stdin = ::std::io::stdin(); - let _a = stdin.lock().lines().next().unwrap().unwrap(); + let x = RefCell::<String>::default(); + let _a = x.borrow().clone(); return String::from("test"); } else { return String::new(); @@ -197,17 +198,15 @@ async fn async_test_void_match(x: u32) { } } -async fn async_read_line() -> String { - use std::io::BufRead; - let stdin = ::std::io::stdin(); - return stdin.lock().lines().next().unwrap().unwrap(); +async fn async_temporary_outlives_local() -> String { + let x = RefCell::<String>::default(); + return x.borrow().clone(); } async fn async_borrows_but_not_last(value: bool) -> String { if value { - use std::io::BufRead; - let stdin = ::std::io::stdin(); - let _a = stdin.lock().lines().next().unwrap().unwrap(); + let x = RefCell::<String>::default(); + let _a = x.borrow().clone(); return String::from("test"); } else { return String::new(); @@ -229,4 +228,13 @@ fn needless_return_macro() -> String { return format!("Hello {}", "world!"); } +fn check_expect() -> bool { + if true { + // no error! + return true; + } + #[expect(clippy::needless_return)] + return true; +} + fn main() {} diff --git a/src/tools/clippy/tests/ui/needless_return.stderr b/src/tools/clippy/tests/ui/needless_return.stderr index 4c8be47b025..83ff0763869 100644 --- a/src/tools/clippy/tests/ui/needless_return.stderr +++ b/src/tools/clippy/tests/ui/needless_return.stderr @@ -1,5 +1,5 @@ error: unneeded `return` statement - --> $DIR/needless_return.rs:24:5 + --> $DIR/needless_return.rs:27:5 | LL | return true; | ^^^^^^^^^^^^ help: remove `return`: `true` @@ -7,217 +7,217 @@ LL | return true; = note: `-D clippy::needless-return` implied by `-D warnings` error: unneeded `return` statement - --> $DIR/needless_return.rs:28:5 + --> $DIR/needless_return.rs:31:5 | LL | return true; | ^^^^^^^^^^^^ help: remove `return`: `true` error: unneeded `return` statement - --> $DIR/needless_return.rs:33:9 + --> $DIR/needless_return.rs:36:9 | LL | return true; | ^^^^^^^^^^^^ help: remove `return`: `true` error: unneeded `return` statement - --> $DIR/needless_return.rs:35:9 + --> $DIR/needless_return.rs:38:9 | LL | return false; | ^^^^^^^^^^^^^ help: remove `return`: `false` error: unneeded `return` statement - --> $DIR/needless_return.rs:41:17 + --> $DIR/needless_return.rs:44:17 | LL | true => return false, | ^^^^^^^^^^^^ help: remove `return`: `false` error: unneeded `return` statement - --> $DIR/needless_return.rs:43:13 + --> $DIR/needless_return.rs:46:13 | LL | return true; | ^^^^^^^^^^^^ help: remove `return`: `true` error: unneeded `return` statement - --> $DIR/needless_return.rs:50:9 + --> $DIR/needless_return.rs:53:9 | LL | return true; | ^^^^^^^^^^^^ help: remove `return`: `true` error: unneeded `return` statement - --> $DIR/needless_return.rs:52:16 + --> $DIR/needless_return.rs:55:16 | LL | let _ = || return true; | ^^^^^^^^^^^ help: remove `return`: `true` error: unneeded `return` statement - --> $DIR/needless_return.rs:56:5 + --> $DIR/needless_return.rs:59:5 | LL | return the_answer!(); | ^^^^^^^^^^^^^^^^^^^^^ help: remove `return`: `the_answer!()` error: unneeded `return` statement - --> $DIR/needless_return.rs:60:5 + --> $DIR/needless_return.rs:63:5 | LL | return; | ^^^^^^^ help: remove `return` error: unneeded `return` statement - --> $DIR/needless_return.rs:65:9 + --> $DIR/needless_return.rs:68:9 | LL | return; | ^^^^^^^ help: remove `return` error: unneeded `return` statement - --> $DIR/needless_return.rs:67:9 + --> $DIR/needless_return.rs:70:9 | LL | return; | ^^^^^^^ help: remove `return` error: unneeded `return` statement - --> $DIR/needless_return.rs:74:14 + --> $DIR/needless_return.rs:77:14 | LL | _ => return, | ^^^^^^ help: replace `return` with a unit value: `()` error: unneeded `return` statement - --> $DIR/needless_return.rs:83:13 + --> $DIR/needless_return.rs:86:13 | LL | return; | ^^^^^^^ help: remove `return` error: unneeded `return` statement - --> $DIR/needless_return.rs:85:14 + --> $DIR/needless_return.rs:88:14 | LL | _ => return, | ^^^^^^ help: replace `return` with a unit value: `()` error: unneeded `return` statement - --> $DIR/needless_return.rs:100:9 + --> $DIR/needless_return.rs:101:9 | LL | return String::from("test"); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: remove `return`: `String::from("test")` error: unneeded `return` statement - --> $DIR/needless_return.rs:102:9 + --> $DIR/needless_return.rs:103:9 | LL | return String::new(); | ^^^^^^^^^^^^^^^^^^^^^ help: remove `return`: `String::new()` error: unneeded `return` statement - --> $DIR/needless_return.rs:124:32 + --> $DIR/needless_return.rs:125:32 | LL | bar.unwrap_or_else(|_| return) | ^^^^^^ help: replace `return` with an empty block: `{}` error: unneeded `return` statement - --> $DIR/needless_return.rs:129:13 + --> $DIR/needless_return.rs:130:13 | LL | return; | ^^^^^^^ help: remove `return` error: unneeded `return` statement - --> $DIR/needless_return.rs:131:20 + --> $DIR/needless_return.rs:132:20 | LL | let _ = || return; | ^^^^^^ help: replace `return` with an empty block: `{}` error: unneeded `return` statement - --> $DIR/needless_return.rs:137:32 + --> $DIR/needless_return.rs:138:32 | LL | res.unwrap_or_else(|_| return Foo) | ^^^^^^^^^^ help: remove `return`: `Foo` error: unneeded `return` statement - --> $DIR/needless_return.rs:146:5 + --> $DIR/needless_return.rs:147:5 | LL | return true; | ^^^^^^^^^^^^ help: remove `return`: `true` error: unneeded `return` statement - --> $DIR/needless_return.rs:150:5 + --> $DIR/needless_return.rs:151:5 | LL | return true; | ^^^^^^^^^^^^ help: remove `return`: `true` error: unneeded `return` statement - --> $DIR/needless_return.rs:155:9 + --> $DIR/needless_return.rs:156:9 | LL | return true; | ^^^^^^^^^^^^ help: remove `return`: `true` error: unneeded `return` statement - --> $DIR/needless_return.rs:157:9 + --> $DIR/needless_return.rs:158:9 | LL | return false; | ^^^^^^^^^^^^^ help: remove `return`: `false` error: unneeded `return` statement - --> $DIR/needless_return.rs:163:17 + --> $DIR/needless_return.rs:164:17 | LL | true => return false, | ^^^^^^^^^^^^ help: remove `return`: `false` error: unneeded `return` statement - --> $DIR/needless_return.rs:165:13 + --> $DIR/needless_return.rs:166:13 | LL | return true; | ^^^^^^^^^^^^ help: remove `return`: `true` error: unneeded `return` statement - --> $DIR/needless_return.rs:172:9 + --> $DIR/needless_return.rs:173:9 | LL | return true; | ^^^^^^^^^^^^ help: remove `return`: `true` error: unneeded `return` statement - --> $DIR/needless_return.rs:174:16 + --> $DIR/needless_return.rs:175:16 | LL | let _ = || return true; | ^^^^^^^^^^^ help: remove `return`: `true` error: unneeded `return` statement - --> $DIR/needless_return.rs:178:5 + --> $DIR/needless_return.rs:179:5 | LL | return the_answer!(); | ^^^^^^^^^^^^^^^^^^^^^ help: remove `return`: `the_answer!()` error: unneeded `return` statement - --> $DIR/needless_return.rs:182:5 + --> $DIR/needless_return.rs:183:5 | LL | return; | ^^^^^^^ help: remove `return` error: unneeded `return` statement - --> $DIR/needless_return.rs:187:9 + --> $DIR/needless_return.rs:188:9 | LL | return; | ^^^^^^^ help: remove `return` error: unneeded `return` statement - --> $DIR/needless_return.rs:189:9 + --> $DIR/needless_return.rs:190:9 | LL | return; | ^^^^^^^ help: remove `return` error: unneeded `return` statement - --> $DIR/needless_return.rs:196:14 + --> $DIR/needless_return.rs:197:14 | LL | _ => return, | ^^^^^^ help: replace `return` with a unit value: `()` error: unneeded `return` statement - --> $DIR/needless_return.rs:211:9 + --> $DIR/needless_return.rs:210:9 | LL | return String::from("test"); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: remove `return`: `String::from("test")` error: unneeded `return` statement - --> $DIR/needless_return.rs:213:9 + --> $DIR/needless_return.rs:212:9 | LL | return String::new(); | ^^^^^^^^^^^^^^^^^^^^^ help: remove `return`: `String::new()` error: unneeded `return` statement - --> $DIR/needless_return.rs:229:5 + --> $DIR/needless_return.rs:228:5 | LL | return format!("Hello {}", "world!"); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: remove `return`: `format!("Hello {}", "world!")` diff --git a/src/tools/clippy/tests/ui/neg_multiply.fixed b/src/tools/clippy/tests/ui/neg_multiply.fixed index 35af9d6ae31..58ab9e85678 100644 --- a/src/tools/clippy/tests/ui/neg_multiply.fixed +++ b/src/tools/clippy/tests/ui/neg_multiply.fixed @@ -38,6 +38,9 @@ fn main() { 0xcafe | -0xff00; + -(3_usize as i32); + -(3_usize as i32); + -1 * -1; // should be ok X * -1; // should be ok diff --git a/src/tools/clippy/tests/ui/neg_multiply.rs b/src/tools/clippy/tests/ui/neg_multiply.rs index 7dbdb0906ce..581290dc72e 100644 --- a/src/tools/clippy/tests/ui/neg_multiply.rs +++ b/src/tools/clippy/tests/ui/neg_multiply.rs @@ -38,6 +38,9 @@ fn main() { 0xcafe | 0xff00 * -1; + 3_usize as i32 * -1; + (3_usize as i32) * -1; + -1 * -1; // should be ok X * -1; // should be ok diff --git a/src/tools/clippy/tests/ui/neg_multiply.stderr b/src/tools/clippy/tests/ui/neg_multiply.stderr index dbf8fb36938..388ef29eb85 100644 --- a/src/tools/clippy/tests/ui/neg_multiply.stderr +++ b/src/tools/clippy/tests/ui/neg_multiply.stderr @@ -36,5 +36,17 @@ error: this multiplication by -1 can be written more succinctly LL | 0xcafe | 0xff00 * -1; | ^^^^^^^^^^^ help: consider using: `-0xff00` -error: aborting due to 6 previous errors +error: this multiplication by -1 can be written more succinctly + --> $DIR/neg_multiply.rs:41:5 + | +LL | 3_usize as i32 * -1; + | ^^^^^^^^^^^^^^^^^^^ help: consider using: `-(3_usize as i32)` + +error: this multiplication by -1 can be written more succinctly + --> $DIR/neg_multiply.rs:42:5 + | +LL | (3_usize as i32) * -1; + | ^^^^^^^^^^^^^^^^^^^^^ help: consider using: `-(3_usize as i32)` + +error: aborting due to 8 previous errors diff --git a/src/tools/clippy/tests/ui/nonminimal_bool.rs b/src/tools/clippy/tests/ui/nonminimal_bool.rs index fa5743c1155..24ae62bb058 100644 --- a/src/tools/clippy/tests/ui/nonminimal_bool.rs +++ b/src/tools/clippy/tests/ui/nonminimal_bool.rs @@ -1,3 +1,4 @@ +#![feature(lint_reasons)] #![allow(unused, clippy::diverging_sub_expression)] #![warn(clippy::nonminimal_bool)] @@ -50,3 +51,9 @@ fn issue4548() { if i != j && f(i, j) != 0 || i == j && f(i, j) != 1 {} } + +fn check_expect() { + let a: bool = unimplemented!(); + #[expect(clippy::nonminimal_bool)] + let _ = !!a; +} diff --git a/src/tools/clippy/tests/ui/nonminimal_bool.stderr b/src/tools/clippy/tests/ui/nonminimal_bool.stderr index bb93cbbd5e1..fc6a5ce1dc2 100644 --- a/src/tools/clippy/tests/ui/nonminimal_bool.stderr +++ b/src/tools/clippy/tests/ui/nonminimal_bool.stderr @@ -1,5 +1,5 @@ error: this boolean expression can be simplified - --> $DIR/nonminimal_bool.rs:10:13 + --> $DIR/nonminimal_bool.rs:11:13 | LL | let _ = !true; | ^^^^^ help: try: `false` @@ -7,43 +7,43 @@ LL | let _ = !true; = note: `-D clippy::nonminimal-bool` implied by `-D warnings` error: this boolean expression can be simplified - --> $DIR/nonminimal_bool.rs:11:13 + --> $DIR/nonminimal_bool.rs:12:13 | LL | let _ = !false; | ^^^^^^ help: try: `true` error: this boolean expression can be simplified - --> $DIR/nonminimal_bool.rs:12:13 + --> $DIR/nonminimal_bool.rs:13:13 | LL | let _ = !!a; | ^^^ help: try: `a` error: this boolean expression can be simplified - --> $DIR/nonminimal_bool.rs:13:13 + --> $DIR/nonminimal_bool.rs:14:13 | LL | let _ = false || a; | ^^^^^^^^^^ help: try: `a` error: this boolean expression can be simplified - --> $DIR/nonminimal_bool.rs:17:13 + --> $DIR/nonminimal_bool.rs:18:13 | LL | let _ = !(!a && b); | ^^^^^^^^^^ help: try: `a || !b` error: this boolean expression can be simplified - --> $DIR/nonminimal_bool.rs:18:13 + --> $DIR/nonminimal_bool.rs:19:13 | LL | let _ = !(!a || b); | ^^^^^^^^^^ help: try: `a && !b` error: this boolean expression can be simplified - --> $DIR/nonminimal_bool.rs:19:13 + --> $DIR/nonminimal_bool.rs:20:13 | LL | let _ = !a && !(b && c); | ^^^^^^^^^^^^^^^ help: try: `!(a || b && c)` error: this boolean expression can be simplified - --> $DIR/nonminimal_bool.rs:27:13 + --> $DIR/nonminimal_bool.rs:28:13 | LL | let _ = a == b && c == 5 && a == b; | ^^^^^^^^^^^^^^^^^^^^^^^^^^ @@ -56,7 +56,7 @@ LL | let _ = a == b && c == 5; | ~~~~~~~~~~~~~~~~ error: this boolean expression can be simplified - --> $DIR/nonminimal_bool.rs:28:13 + --> $DIR/nonminimal_bool.rs:29:13 | LL | let _ = a == b || c == 5 || a == b; | ^^^^^^^^^^^^^^^^^^^^^^^^^^ @@ -69,7 +69,7 @@ LL | let _ = a == b || c == 5; | ~~~~~~~~~~~~~~~~ error: this boolean expression can be simplified - --> $DIR/nonminimal_bool.rs:29:13 + --> $DIR/nonminimal_bool.rs:30:13 | LL | let _ = a == b && c == 5 && b == a; | ^^^^^^^^^^^^^^^^^^^^^^^^^^ @@ -82,7 +82,7 @@ LL | let _ = a == b && c == 5; | ~~~~~~~~~~~~~~~~ error: this boolean expression can be simplified - --> $DIR/nonminimal_bool.rs:30:13 + --> $DIR/nonminimal_bool.rs:31:13 | LL | let _ = a != b || !(a != b || c == d); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ @@ -95,7 +95,7 @@ LL | let _ = a != b || c != d; | ~~~~~~~~~~~~~~~~ error: this boolean expression can be simplified - --> $DIR/nonminimal_bool.rs:31:13 + --> $DIR/nonminimal_bool.rs:32:13 | LL | let _ = a != b && !(a != b && c == d); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ diff --git a/src/tools/clippy/tests/ui/ptr_arg.rs b/src/tools/clippy/tests/ui/ptr_arg.rs index 814bbc7af71..fd15001e540 100644 --- a/src/tools/clippy/tests/ui/ptr_arg.rs +++ b/src/tools/clippy/tests/ui/ptr_arg.rs @@ -1,3 +1,4 @@ +#![feature(lint_reasons)] #![allow(unused, clippy::many_single_char_names, clippy::redundant_clone)] #![warn(clippy::ptr_arg)] @@ -109,9 +110,12 @@ mod issue_5644 { #[allow(clippy::ptr_arg)] _s: &String, #[allow(clippy::ptr_arg)] _p: &PathBuf, #[allow(clippy::ptr_arg)] _c: &Cow<[i32]>, + #[expect(clippy::ptr_arg)] _expect: &Cow<[i32]>, ) { } + fn some_allowed(#[allow(clippy::ptr_arg)] _v: &Vec<u32>, _s: &String) {} + struct S; impl S { fn allowed( @@ -119,6 +123,7 @@ mod issue_5644 { #[allow(clippy::ptr_arg)] _s: &String, #[allow(clippy::ptr_arg)] _p: &PathBuf, #[allow(clippy::ptr_arg)] _c: &Cow<[i32]>, + #[expect(clippy::ptr_arg)] _expect: &Cow<[i32]>, ) { } } @@ -129,6 +134,7 @@ mod issue_5644 { #[allow(clippy::ptr_arg)] _s: &String, #[allow(clippy::ptr_arg)] _p: &PathBuf, #[allow(clippy::ptr_arg)] _c: &Cow<[i32]>, + #[expect(clippy::ptr_arg)] _expect: &Cow<[i32]>, ) { } } diff --git a/src/tools/clippy/tests/ui/ptr_arg.stderr b/src/tools/clippy/tests/ui/ptr_arg.stderr index 7ec4a566ff3..d64b5f454a5 100644 --- a/src/tools/clippy/tests/ui/ptr_arg.stderr +++ b/src/tools/clippy/tests/ui/ptr_arg.stderr @@ -1,5 +1,5 @@ error: writing `&Vec` instead of `&[_]` involves a new object where a slice will do - --> $DIR/ptr_arg.rs:7:14 + --> $DIR/ptr_arg.rs:8:14 | LL | fn do_vec(x: &Vec<i64>) { | ^^^^^^^^^ help: change this to: `&[i64]` @@ -7,43 +7,43 @@ LL | fn do_vec(x: &Vec<i64>) { = note: `-D clippy::ptr-arg` implied by `-D warnings` error: writing `&mut Vec` instead of `&mut [_]` involves a new object where a slice will do - --> $DIR/ptr_arg.rs:11:18 + --> $DIR/ptr_arg.rs:12:18 | LL | fn do_vec_mut(x: &mut Vec<i64>) { | ^^^^^^^^^^^^^ help: change this to: `&mut [i64]` error: writing `&String` instead of `&str` involves a new object where a slice will do - --> $DIR/ptr_arg.rs:15:14 + --> $DIR/ptr_arg.rs:16:14 | LL | fn do_str(x: &String) { | ^^^^^^^ help: change this to: `&str` error: writing `&mut String` instead of `&mut str` involves a new object where a slice will do - --> $DIR/ptr_arg.rs:19:18 + --> $DIR/ptr_arg.rs:20:18 | LL | fn do_str_mut(x: &mut String) { | ^^^^^^^^^^^ help: change this to: `&mut str` error: writing `&PathBuf` instead of `&Path` involves a new object where a slice will do - --> $DIR/ptr_arg.rs:23:15 + --> $DIR/ptr_arg.rs:24:15 | LL | fn do_path(x: &PathBuf) { | ^^^^^^^^ help: change this to: `&Path` error: writing `&mut PathBuf` instead of `&mut Path` involves a new object where a slice will do - --> $DIR/ptr_arg.rs:27:19 + --> $DIR/ptr_arg.rs:28:19 | LL | fn do_path_mut(x: &mut PathBuf) { | ^^^^^^^^^^^^ help: change this to: `&mut Path` error: writing `&Vec` instead of `&[_]` involves a new object where a slice will do - --> $DIR/ptr_arg.rs:35:18 + --> $DIR/ptr_arg.rs:36:18 | LL | fn do_vec(x: &Vec<i64>); | ^^^^^^^^^ help: change this to: `&[i64]` error: writing `&Vec` instead of `&[_]` involves a new object where a slice will do - --> $DIR/ptr_arg.rs:48:14 + --> $DIR/ptr_arg.rs:49:14 | LL | fn cloned(x: &Vec<u8>) -> Vec<u8> { | ^^^^^^^^ @@ -60,7 +60,7 @@ LL ~ x.to_owned() | error: writing `&String` instead of `&str` involves a new object where a slice will do - --> $DIR/ptr_arg.rs:57:18 + --> $DIR/ptr_arg.rs:58:18 | LL | fn str_cloned(x: &String) -> String { | ^^^^^^^ @@ -76,7 +76,7 @@ LL ~ x.to_owned() | error: writing `&PathBuf` instead of `&Path` involves a new object where a slice will do - --> $DIR/ptr_arg.rs:65:19 + --> $DIR/ptr_arg.rs:66:19 | LL | fn path_cloned(x: &PathBuf) -> PathBuf { | ^^^^^^^^ @@ -92,7 +92,7 @@ LL ~ x.to_path_buf() | error: writing `&String` instead of `&str` involves a new object where a slice will do - --> $DIR/ptr_arg.rs:73:44 + --> $DIR/ptr_arg.rs:74:44 | LL | fn false_positive_capacity(x: &Vec<u8>, y: &String) { | ^^^^^^^ @@ -106,13 +106,19 @@ LL ~ let c = y; | error: using a reference to `Cow` is not recommended - --> $DIR/ptr_arg.rs:87:25 + --> $DIR/ptr_arg.rs:88:25 | LL | fn test_cow_with_ref(c: &Cow<[i32]>) {} | ^^^^^^^^^^^ help: change this to: `&[i32]` +error: writing `&String` instead of `&str` involves a new object where a slice will do + --> $DIR/ptr_arg.rs:117:66 + | +LL | fn some_allowed(#[allow(clippy::ptr_arg)] _v: &Vec<u32>, _s: &String) {} + | ^^^^^^^ help: change this to: `&str` + error: writing `&Vec` instead of `&[_]` involves a new object where a slice will do - --> $DIR/ptr_arg.rs:140:21 + --> $DIR/ptr_arg.rs:146:21 | LL | fn foo_vec(vec: &Vec<u8>) { | ^^^^^^^^ @@ -125,7 +131,7 @@ LL ~ let _ = vec.to_owned().clone(); | error: writing `&PathBuf` instead of `&Path` involves a new object where a slice will do - --> $DIR/ptr_arg.rs:145:23 + --> $DIR/ptr_arg.rs:151:23 | LL | fn foo_path(path: &PathBuf) { | ^^^^^^^^ @@ -138,7 +144,7 @@ LL ~ let _ = path.to_path_buf().clone(); | error: writing `&PathBuf` instead of `&Path` involves a new object where a slice will do - --> $DIR/ptr_arg.rs:150:21 + --> $DIR/ptr_arg.rs:156:21 | LL | fn foo_str(str: &PathBuf) { | ^^^^^^^^ @@ -151,10 +157,10 @@ LL ~ let _ = str.to_path_buf().clone(); | error: writing `&mut Vec` instead of `&mut [_]` involves a new object where a slice will do - --> $DIR/ptr_arg.rs:156:29 + --> $DIR/ptr_arg.rs:162:29 | LL | fn mut_vec_slice_methods(v: &mut Vec<u32>) { | ^^^^^^^^^^^^^ help: change this to: `&mut [u32]` -error: aborting due to 16 previous errors +error: aborting due to 17 previous errors diff --git a/src/tools/clippy/tests/ui/redundant_clone.fixed b/src/tools/clippy/tests/ui/redundant_clone.fixed index 1525f6a93df..da52c0acf93 100644 --- a/src/tools/clippy/tests/ui/redundant_clone.fixed +++ b/src/tools/clippy/tests/ui/redundant_clone.fixed @@ -1,6 +1,7 @@ // run-rustfix // rustfix-only-machine-applicable +#![feature(lint_reasons)] #![allow(clippy::implicit_clone, clippy::drop_non_drop)] use std::ffi::OsString; use std::path::Path; @@ -29,6 +30,10 @@ fn main() { #[allow(clippy::redundant_clone)] let _s = String::new().to_string(); + // Check that lint level works + #[expect(clippy::redundant_clone)] + let _s = String::new().to_string(); + let tup = (String::from("foo"),); let _t = tup.0; diff --git a/src/tools/clippy/tests/ui/redundant_clone.rs b/src/tools/clippy/tests/ui/redundant_clone.rs index 2f82aefd928..5867d019dbb 100644 --- a/src/tools/clippy/tests/ui/redundant_clone.rs +++ b/src/tools/clippy/tests/ui/redundant_clone.rs @@ -1,6 +1,7 @@ // run-rustfix // rustfix-only-machine-applicable +#![feature(lint_reasons)] #![allow(clippy::implicit_clone, clippy::drop_non_drop)] use std::ffi::OsString; use std::path::Path; @@ -29,6 +30,10 @@ fn main() { #[allow(clippy::redundant_clone)] let _s = String::new().to_string(); + // Check that lint level works + #[expect(clippy::redundant_clone)] + let _s = String::new().to_string(); + let tup = (String::from("foo"),); let _t = tup.0.clone(); diff --git a/src/tools/clippy/tests/ui/redundant_clone.stderr b/src/tools/clippy/tests/ui/redundant_clone.stderr index 9f59017b261..aa1dd7cbb45 100644 --- a/src/tools/clippy/tests/ui/redundant_clone.stderr +++ b/src/tools/clippy/tests/ui/redundant_clone.stderr @@ -1,180 +1,180 @@ error: redundant clone - --> $DIR/redundant_clone.rs:9:42 + --> $DIR/redundant_clone.rs:10:42 | LL | let _s = ["lorem", "ipsum"].join(" ").to_string(); | ^^^^^^^^^^^^ help: remove this | = note: `-D clippy::redundant-clone` implied by `-D warnings` note: this value is dropped without further use - --> $DIR/redundant_clone.rs:9:14 + --> $DIR/redundant_clone.rs:10:14 | LL | let _s = ["lorem", "ipsum"].join(" ").to_string(); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ error: redundant clone - --> $DIR/redundant_clone.rs:12:15 + --> $DIR/redundant_clone.rs:13:15 | LL | let _s = s.clone(); | ^^^^^^^^ help: remove this | note: this value is dropped without further use - --> $DIR/redundant_clone.rs:12:14 + --> $DIR/redundant_clone.rs:13:14 | LL | let _s = s.clone(); | ^ error: redundant clone - --> $DIR/redundant_clone.rs:15:15 + --> $DIR/redundant_clone.rs:16:15 | LL | let _s = s.to_string(); | ^^^^^^^^^^^^ help: remove this | note: this value is dropped without further use - --> $DIR/redundant_clone.rs:15:14 + --> $DIR/redundant_clone.rs:16:14 | LL | let _s = s.to_string(); | ^ error: redundant clone - --> $DIR/redundant_clone.rs:18:15 + --> $DIR/redundant_clone.rs:19:15 | LL | let _s = s.to_owned(); | ^^^^^^^^^^^ help: remove this | note: this value is dropped without further use - --> $DIR/redundant_clone.rs:18:14 + --> $DIR/redundant_clone.rs:19:14 | LL | let _s = s.to_owned(); | ^ error: redundant clone - --> $DIR/redundant_clone.rs:20:42 + --> $DIR/redundant_clone.rs:21:42 | LL | let _s = Path::new("/a/b/").join("c").to_owned(); | ^^^^^^^^^^^ help: remove this | note: this value is dropped without further use - --> $DIR/redundant_clone.rs:20:14 + --> $DIR/redundant_clone.rs:21:14 | LL | let _s = Path::new("/a/b/").join("c").to_owned(); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ error: redundant clone - --> $DIR/redundant_clone.rs:22:42 + --> $DIR/redundant_clone.rs:23:42 | LL | let _s = Path::new("/a/b/").join("c").to_path_buf(); | ^^^^^^^^^^^^^^ help: remove this | note: this value is dropped without further use - --> $DIR/redundant_clone.rs:22:14 + --> $DIR/redundant_clone.rs:23:14 | LL | let _s = Path::new("/a/b/").join("c").to_path_buf(); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ error: redundant clone - --> $DIR/redundant_clone.rs:24:29 + --> $DIR/redundant_clone.rs:25:29 | LL | let _s = OsString::new().to_owned(); | ^^^^^^^^^^^ help: remove this | note: this value is dropped without further use - --> $DIR/redundant_clone.rs:24:14 + --> $DIR/redundant_clone.rs:25:14 | LL | let _s = OsString::new().to_owned(); | ^^^^^^^^^^^^^^^ error: redundant clone - --> $DIR/redundant_clone.rs:26:29 + --> $DIR/redundant_clone.rs:27:29 | LL | let _s = OsString::new().to_os_string(); | ^^^^^^^^^^^^^^^ help: remove this | note: this value is dropped without further use - --> $DIR/redundant_clone.rs:26:14 + --> $DIR/redundant_clone.rs:27:14 | LL | let _s = OsString::new().to_os_string(); | ^^^^^^^^^^^^^^^ error: redundant clone - --> $DIR/redundant_clone.rs:33:19 + --> $DIR/redundant_clone.rs:38:19 | LL | let _t = tup.0.clone(); | ^^^^^^^^ help: remove this | note: this value is dropped without further use - --> $DIR/redundant_clone.rs:33:14 + --> $DIR/redundant_clone.rs:38:14 | LL | let _t = tup.0.clone(); | ^^^^^ error: redundant clone - --> $DIR/redundant_clone.rs:65:25 + --> $DIR/redundant_clone.rs:70:25 | LL | if b { (a.clone(), a.clone()) } else { (Alpha, a) } | ^^^^^^^^ help: remove this | note: this value is dropped without further use - --> $DIR/redundant_clone.rs:65:24 + --> $DIR/redundant_clone.rs:70:24 | LL | if b { (a.clone(), a.clone()) } else { (Alpha, a) } | ^ error: redundant clone - --> $DIR/redundant_clone.rs:122:15 + --> $DIR/redundant_clone.rs:127:15 | LL | let _s = s.clone(); | ^^^^^^^^ help: remove this | note: this value is dropped without further use - --> $DIR/redundant_clone.rs:122:14 + --> $DIR/redundant_clone.rs:127:14 | LL | let _s = s.clone(); | ^ error: redundant clone - --> $DIR/redundant_clone.rs:123:15 + --> $DIR/redundant_clone.rs:128:15 | LL | let _t = t.clone(); | ^^^^^^^^ help: remove this | note: this value is dropped without further use - --> $DIR/redundant_clone.rs:123:14 + --> $DIR/redundant_clone.rs:128:14 | LL | let _t = t.clone(); | ^ error: redundant clone - --> $DIR/redundant_clone.rs:133:19 + --> $DIR/redundant_clone.rs:138:19 | LL | let _f = f.clone(); | ^^^^^^^^ help: remove this | note: this value is dropped without further use - --> $DIR/redundant_clone.rs:133:18 + --> $DIR/redundant_clone.rs:138:18 | LL | let _f = f.clone(); | ^ error: redundant clone - --> $DIR/redundant_clone.rs:145:14 + --> $DIR/redundant_clone.rs:150:14 | LL | let y = x.clone().join("matthias"); | ^^^^^^^^ help: remove this | note: cloned value is neither consumed nor mutated - --> $DIR/redundant_clone.rs:145:13 + --> $DIR/redundant_clone.rs:150:13 | LL | let y = x.clone().join("matthias"); | ^^^^^^^^^ error: redundant clone - --> $DIR/redundant_clone.rs:199:11 + --> $DIR/redundant_clone.rs:204:11 | LL | foo(&x.clone(), move || { | ^^^^^^^^ help: remove this | note: this value is dropped without further use - --> $DIR/redundant_clone.rs:199:10 + --> $DIR/redundant_clone.rs:204:10 | LL | foo(&x.clone(), move || { | ^ diff --git a/src/tools/clippy/tests/ui/ref_binding_to_reference.rs b/src/tools/clippy/tests/ui/ref_binding_to_reference.rs index 570ef406e4a..c8d0e56b197 100644 --- a/src/tools/clippy/tests/ui/ref_binding_to_reference.rs +++ b/src/tools/clippy/tests/ui/ref_binding_to_reference.rs @@ -2,7 +2,7 @@ #![feature(lint_reasons)] #![warn(clippy::ref_binding_to_reference)] -#![allow(clippy::needless_borrowed_reference)] +#![allow(clippy::needless_borrowed_reference, clippy::explicit_auto_deref)] fn f1(_: &str) {} macro_rules! m2 { diff --git a/src/tools/clippy/tests/ui/search_is_some_fixable_none.fixed b/src/tools/clippy/tests/ui/search_is_some_fixable_none.fixed index 6831fb2cf59..5190c5304c7 100644 --- a/src/tools/clippy/tests/ui/search_is_some_fixable_none.fixed +++ b/src/tools/clippy/tests/ui/search_is_some_fixable_none.fixed @@ -1,5 +1,5 @@ // run-rustfix -#![allow(dead_code)] +#![allow(dead_code, clippy::explicit_auto_deref)] #![warn(clippy::search_is_some)] fn main() { diff --git a/src/tools/clippy/tests/ui/search_is_some_fixable_none.rs b/src/tools/clippy/tests/ui/search_is_some_fixable_none.rs index 767518ab0c0..310d87333a9 100644 --- a/src/tools/clippy/tests/ui/search_is_some_fixable_none.rs +++ b/src/tools/clippy/tests/ui/search_is_some_fixable_none.rs @@ -1,5 +1,5 @@ // run-rustfix -#![allow(dead_code)] +#![allow(dead_code, clippy::explicit_auto_deref)] #![warn(clippy::search_is_some)] fn main() { diff --git a/src/tools/clippy/tests/ui/search_is_some_fixable_some.fixed b/src/tools/clippy/tests/ui/search_is_some_fixable_some.fixed index 7c940a2b069..5a2aee465d1 100644 --- a/src/tools/clippy/tests/ui/search_is_some_fixable_some.fixed +++ b/src/tools/clippy/tests/ui/search_is_some_fixable_some.fixed @@ -1,5 +1,5 @@ // run-rustfix -#![allow(dead_code)] +#![allow(dead_code, clippy::explicit_auto_deref)] #![warn(clippy::search_is_some)] fn main() { diff --git a/src/tools/clippy/tests/ui/search_is_some_fixable_some.rs b/src/tools/clippy/tests/ui/search_is_some_fixable_some.rs index 77fd52e4ce7..0e98ae18a21 100644 --- a/src/tools/clippy/tests/ui/search_is_some_fixable_some.rs +++ b/src/tools/clippy/tests/ui/search_is_some_fixable_some.rs @@ -1,5 +1,5 @@ // run-rustfix -#![allow(dead_code)] +#![allow(dead_code, clippy::explicit_auto_deref)] #![warn(clippy::search_is_some)] fn main() { diff --git a/src/tools/clippy/tests/ui/should_impl_trait/corner_cases.rs b/src/tools/clippy/tests/ui/should_impl_trait/corner_cases.rs index 1ccb0a1d167..50999c6f219 100644 --- a/src/tools/clippy/tests/ui/should_impl_trait/corner_cases.rs +++ b/src/tools/clippy/tests/ui/should_impl_trait/corner_cases.rs @@ -8,7 +8,8 @@ clippy::missing_safety_doc, clippy::wrong_self_convention, clippy::missing_panics_doc, - clippy::return_self_not_must_use + clippy::return_self_not_must_use, + clippy::unused_async )] use std::ops::Mul; diff --git a/src/tools/clippy/tests/ui/significant_drop_in_scrutinee.rs b/src/tools/clippy/tests/ui/significant_drop_in_scrutinee.rs index 4347610f393..185e5009b60 100644 --- a/src/tools/clippy/tests/ui/significant_drop_in_scrutinee.rs +++ b/src/tools/clippy/tests/ui/significant_drop_in_scrutinee.rs @@ -64,6 +64,19 @@ fn should_trigger_lint_with_mutex_guard_in_match_scrutinee() { }; } +fn should_not_trigger_lint_with_mutex_guard_in_match_scrutinee_when_lint_allowed() { + let mutex = Mutex::new(State {}); + + // Lint should not be triggered because it is "allowed" below. + #[allow(clippy::significant_drop_in_scrutinee)] + match mutex.lock().unwrap().foo() { + true => { + mutex.lock().unwrap().bar(); + }, + false => {}, + }; +} + fn should_not_trigger_lint_for_insignificant_drop() { // Should not trigger lint because there are no temporaries whose drops have a significant // side effect. @@ -591,4 +604,20 @@ fn should_trigger_lint_for_read_write_lock_for_loop() { } } +fn do_bar(mutex: &Mutex<State>) { + mutex.lock().unwrap().bar(); +} + +fn should_trigger_lint_without_significant_drop_in_arm() { + let mutex = Mutex::new(State {}); + + // Should trigger lint because the lifetime of the temporary MutexGuard is surprising because it + // is preserved until the end of the match, but there is no clear indication that this is the + // case. + match mutex.lock().unwrap().foo() { + true => do_bar(&mutex), + false => {}, + }; +} + fn main() {} diff --git a/src/tools/clippy/tests/ui/significant_drop_in_scrutinee.stderr b/src/tools/clippy/tests/ui/significant_drop_in_scrutinee.stderr index 5ce95204416..88ea6bce25b 100644 --- a/src/tools/clippy/tests/ui/significant_drop_in_scrutinee.stderr +++ b/src/tools/clippy/tests/ui/significant_drop_in_scrutinee.stderr @@ -1,174 +1,290 @@ -error: temporary with significant drop in match scrutinee +error: temporary with significant `Drop` in `match` scrutinee will live until the end of the `match` expression --> $DIR/significant_drop_in_scrutinee.rs:59:11 | LL | match mutex.lock().unwrap().foo() { | ^^^^^^^^^^^^^^^^^^^^^^^^^^^ +LL | true => { +LL | mutex.lock().unwrap().bar(); + | --------------------- another value with significant `Drop` created here +... +LL | }; + | - temporary lives until here | = note: `-D clippy::significant-drop-in-scrutinee` implied by `-D warnings` + = note: this might lead to deadlocks or other unexpected behavior help: try moving the temporary above the match | LL ~ let value = mutex.lock().unwrap().foo(); LL ~ match value { | -error: temporary with significant drop in match scrutinee - --> $DIR/significant_drop_in_scrutinee.rs:132:11 +error: temporary with significant `Drop` in `match` scrutinee will live until the end of the `match` expression + --> $DIR/significant_drop_in_scrutinee.rs:145:11 | LL | match s.lock_m().get_the_value() { | ^^^^^^^^^^^^^^^^^^^^^^^^^^ - | +... +LL | println!("{}", s.lock_m().get_the_value()); + | ---------- another value with significant `Drop` created here +... +LL | } + | - temporary lives until here + | + = note: this might lead to deadlocks or other unexpected behavior help: try moving the temporary above the match | LL ~ let value = s.lock_m().get_the_value(); LL ~ match value { | -error: temporary with significant drop in match scrutinee - --> $DIR/significant_drop_in_scrutinee.rs:153:11 +error: temporary with significant `Drop` in `match` scrutinee will live until the end of the `match` expression + --> $DIR/significant_drop_in_scrutinee.rs:166:11 | LL | match s.lock_m_m().get_the_value() { | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ - | +... +LL | println!("{}", s.lock_m().get_the_value()); + | ---------- another value with significant `Drop` created here +... +LL | } + | - temporary lives until here + | + = note: this might lead to deadlocks or other unexpected behavior help: try moving the temporary above the match | LL ~ let value = s.lock_m_m().get_the_value(); LL ~ match value { | -error: temporary with significant drop in match scrutinee - --> $DIR/significant_drop_in_scrutinee.rs:201:11 +error: temporary with significant `Drop` in `match` scrutinee will live until the end of the `match` expression + --> $DIR/significant_drop_in_scrutinee.rs:214:11 | LL | match counter.temp_increment().len() { | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ +... +LL | }; + | - temporary lives until here | + = note: this might lead to deadlocks or other unexpected behavior help: try moving the temporary above the match | LL ~ let value = counter.temp_increment().len(); LL ~ match value { | -error: temporary with significant drop in match scrutinee - --> $DIR/significant_drop_in_scrutinee.rs:224:16 +error: temporary with significant `Drop` in `match` scrutinee will live until the end of the `match` expression + --> $DIR/significant_drop_in_scrutinee.rs:237:16 | LL | match (mutex1.lock().unwrap().s.len(), true) { | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ - | +... +LL | mutex1.lock().unwrap().s.len(); + | ---------------------- another value with significant `Drop` created here +... +LL | }; + | - temporary lives until here + | + = note: this might lead to deadlocks or other unexpected behavior help: try moving the temporary above the match | LL ~ let value = mutex1.lock().unwrap().s.len(); LL ~ match (value, true) { | -error: temporary with significant drop in match scrutinee - --> $DIR/significant_drop_in_scrutinee.rs:233:22 +error: temporary with significant `Drop` in `match` scrutinee will live until the end of the `match` expression + --> $DIR/significant_drop_in_scrutinee.rs:246:22 | LL | match (true, mutex1.lock().unwrap().s.len(), true) { | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ - | +... +LL | mutex1.lock().unwrap().s.len(); + | ---------------------- another value with significant `Drop` created here +... +LL | }; + | - temporary lives until here + | + = note: this might lead to deadlocks or other unexpected behavior help: try moving the temporary above the match | LL ~ let value = mutex1.lock().unwrap().s.len(); LL ~ match (true, value, true) { | -error: temporary with significant drop in match scrutinee - --> $DIR/significant_drop_in_scrutinee.rs:243:16 +error: temporary with significant `Drop` in `match` scrutinee will live until the end of the `match` expression + --> $DIR/significant_drop_in_scrutinee.rs:256:16 | LL | match (mutex1.lock().unwrap().s.len(), true, mutex2.lock().unwrap().s.len()) { | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ - | +... +LL | mutex1.lock().unwrap().s.len(); + | ---------------------- another value with significant `Drop` created here +LL | mutex2.lock().unwrap().s.len(); + | ---------------------- another value with significant `Drop` created here +... +LL | }; + | - temporary lives until here + | + = note: this might lead to deadlocks or other unexpected behavior help: try moving the temporary above the match | LL ~ let value = mutex1.lock().unwrap().s.len(); LL ~ match (value, true, mutex2.lock().unwrap().s.len()) { | -error: temporary with significant drop in match scrutinee - --> $DIR/significant_drop_in_scrutinee.rs:243:54 +error: temporary with significant `Drop` in `match` scrutinee will live until the end of the `match` expression + --> $DIR/significant_drop_in_scrutinee.rs:256:54 | LL | match (mutex1.lock().unwrap().s.len(), true, mutex2.lock().unwrap().s.len()) { | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ - | +... +LL | mutex1.lock().unwrap().s.len(); + | ---------------------- another value with significant `Drop` created here +LL | mutex2.lock().unwrap().s.len(); + | ---------------------- another value with significant `Drop` created here +... +LL | }; + | - temporary lives until here + | + = note: this might lead to deadlocks or other unexpected behavior help: try moving the temporary above the match | LL ~ let value = mutex2.lock().unwrap().s.len(); LL ~ match (mutex1.lock().unwrap().s.len(), true, value) { | -error: temporary with significant drop in match scrutinee - --> $DIR/significant_drop_in_scrutinee.rs:254:15 +error: temporary with significant `Drop` in `match` scrutinee will live until the end of the `match` expression + --> $DIR/significant_drop_in_scrutinee.rs:267:15 | LL | match mutex3.lock().unwrap().s.as_str() { | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ +... +LL | mutex1.lock().unwrap().s.len(); + | ---------------------- another value with significant `Drop` created here +LL | mutex2.lock().unwrap().s.len(); + | ---------------------- another value with significant `Drop` created here +... +LL | }; + | - temporary lives until here + | + = note: this might lead to deadlocks or other unexpected behavior -error: temporary with significant drop in match scrutinee - --> $DIR/significant_drop_in_scrutinee.rs:264:22 +error: temporary with significant `Drop` in `match` scrutinee will live until the end of the `match` expression + --> $DIR/significant_drop_in_scrutinee.rs:277:22 | LL | match (true, mutex3.lock().unwrap().s.as_str()) { | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ +... +LL | mutex1.lock().unwrap().s.len(); + | ---------------------- another value with significant `Drop` created here +LL | mutex2.lock().unwrap().s.len(); + | ---------------------- another value with significant `Drop` created here +... +LL | }; + | - temporary lives until here + | + = note: this might lead to deadlocks or other unexpected behavior -error: temporary with significant drop in match scrutinee - --> $DIR/significant_drop_in_scrutinee.rs:283:11 +error: temporary with significant `Drop` in `match` scrutinee will live until the end of the `match` expression + --> $DIR/significant_drop_in_scrutinee.rs:296:11 | LL | match mutex.lock().unwrap().s.len() > 1 { | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ - | +LL | true => { +LL | mutex.lock().unwrap().s.len(); + | --------------------- another value with significant `Drop` created here +... +LL | }; + | - temporary lives until here + | + = note: this might lead to deadlocks or other unexpected behavior help: try moving the temporary above the match | LL ~ let value = mutex.lock().unwrap().s.len() > 1; LL ~ match value { | -error: temporary with significant drop in match scrutinee - --> $DIR/significant_drop_in_scrutinee.rs:290:11 +error: temporary with significant `Drop` in `match` scrutinee will live until the end of the `match` expression + --> $DIR/significant_drop_in_scrutinee.rs:303:11 | LL | match 1 < mutex.lock().unwrap().s.len() { | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ - | +LL | true => { +LL | mutex.lock().unwrap().s.len(); + | --------------------- another value with significant `Drop` created here +... +LL | }; + | - temporary lives until here + | + = note: this might lead to deadlocks or other unexpected behavior help: try moving the temporary above the match | LL ~ let value = 1 < mutex.lock().unwrap().s.len(); LL ~ match value { | -error: temporary with significant drop in match scrutinee - --> $DIR/significant_drop_in_scrutinee.rs:308:11 +error: temporary with significant `Drop` in `match` scrutinee will live until the end of the `match` expression + --> $DIR/significant_drop_in_scrutinee.rs:321:11 | LL | match mutex1.lock().unwrap().s.len() < mutex2.lock().unwrap().s.len() { | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ - | +... +LL | mutex1.lock().unwrap().s.len(), + | ---------------------- another value with significant `Drop` created here +LL | mutex2.lock().unwrap().s.len() + | ---------------------- another value with significant `Drop` created here +... +LL | }; + | - temporary lives until here + | + = note: this might lead to deadlocks or other unexpected behavior help: try moving the temporary above the match | LL ~ let value = mutex1.lock().unwrap().s.len() < mutex2.lock().unwrap().s.len(); LL ~ match value { | -error: temporary with significant drop in match scrutinee - --> $DIR/significant_drop_in_scrutinee.rs:319:11 +error: temporary with significant `Drop` in `match` scrutinee will live until the end of the `match` expression + --> $DIR/significant_drop_in_scrutinee.rs:332:11 | LL | match mutex1.lock().unwrap().s.len() >= mutex2.lock().unwrap().s.len() { | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ - | +... +LL | mutex1.lock().unwrap().s.len(), + | ---------------------- another value with significant `Drop` created here +LL | mutex2.lock().unwrap().s.len() + | ---------------------- another value with significant `Drop` created here +... +LL | }; + | - temporary lives until here + | + = note: this might lead to deadlocks or other unexpected behavior help: try moving the temporary above the match | LL ~ let value = mutex1.lock().unwrap().s.len() >= mutex2.lock().unwrap().s.len(); LL ~ match value { | -error: temporary with significant drop in match scrutinee - --> $DIR/significant_drop_in_scrutinee.rs:354:11 +error: temporary with significant `Drop` in `match` scrutinee will live until the end of the `match` expression + --> $DIR/significant_drop_in_scrutinee.rs:367:11 | LL | match get_mutex_guard().s.len() > 1 { | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ - | +LL | true => { +LL | mutex1.lock().unwrap().s.len(); + | ---------------------- another value with significant `Drop` created here +... +LL | }; + | - temporary lives until here + | + = note: this might lead to deadlocks or other unexpected behavior help: try moving the temporary above the match | LL ~ let value = get_mutex_guard().s.len() > 1; LL ~ match value { | -error: temporary with significant drop in match scrutinee - --> $DIR/significant_drop_in_scrutinee.rs:371:11 +error: temporary with significant `Drop` in `match` scrutinee will live until the end of the `match` expression + --> $DIR/significant_drop_in_scrutinee.rs:384:11 | LL | match match i { | ___________^ @@ -179,7 +295,14 @@ LL | | .s LL | | .len() LL | | > 1 | |___________^ - | +... +LL | mutex1.lock().unwrap().s.len(); + | ---------------------- another value with significant `Drop` created here +... +LL | }; + | - temporary lives until here + | + = note: this might lead to deadlocks or other unexpected behavior help: try moving the temporary above the match | LL ~ let value = match i { @@ -192,8 +315,8 @@ LL + > 1; LL ~ match value | -error: temporary with significant drop in match scrutinee - --> $DIR/significant_drop_in_scrutinee.rs:397:11 +error: temporary with significant `Drop` in `match` scrutinee will live until the end of the `match` expression + --> $DIR/significant_drop_in_scrutinee.rs:410:11 | LL | match if i > 1 { | ___________^ @@ -204,7 +327,14 @@ LL | | mutex2.lock().unwrap() LL | | .len() LL | | > 1 | |___________^ - | +... +LL | mutex1.lock().unwrap().s.len(); + | ---------------------- another value with significant `Drop` created here +... +LL | }; + | - temporary lives until here + | + = note: this might lead to deadlocks or other unexpected behavior help: try moving the temporary above the match | LL ~ let value = if i > 1 { @@ -218,83 +348,150 @@ LL + > 1; LL ~ match value | -error: temporary with significant drop in match scrutinee - --> $DIR/significant_drop_in_scrutinee.rs:451:11 +error: temporary with significant `Drop` in `match` scrutinee will live until the end of the `match` expression + --> $DIR/significant_drop_in_scrutinee.rs:464:11 | LL | match s.lock().deref().deref() { | ^^^^^^^^^^^^^^^^^^^^^^^^ +LL | 0 | 1 => println!("Value was less than 2"), +LL | _ => println!("Value is {}", s.lock().deref()), + | ---------------- another value with significant `Drop` created here +LL | }; + | - temporary lives until here | + = note: this might lead to deadlocks or other unexpected behavior help: try moving the temporary above the match and create a copy | LL ~ let value = *s.lock().deref().deref(); LL ~ match value { | -error: temporary with significant drop in match scrutinee - --> $DIR/significant_drop_in_scrutinee.rs:479:11 +error: temporary with significant `Drop` in `match` scrutinee will live until the end of the `match` expression + --> $DIR/significant_drop_in_scrutinee.rs:492:11 | LL | match s.lock().deref().deref() { | ^^^^^^^^^^^^^^^^^^^^^^^^ +LL | matcher => println!("Value is {}", s.lock().deref()), + | ---------------- another value with significant `Drop` created here +LL | _ => println!("Value was not a match"), +LL | }; + | - temporary lives until here + | + = note: this might lead to deadlocks or other unexpected behavior -error: temporary with significant drop in match scrutinee - --> $DIR/significant_drop_in_scrutinee.rs:498:11 +error: temporary with significant `Drop` in `match` scrutinee will live until the end of the `match` expression + --> $DIR/significant_drop_in_scrutinee.rs:511:11 | LL | match mutex.lock().unwrap().i = i { | ^^^^^^^^^^^^^^^^^^^^^^^^^^^ - | +LL | _ => { +LL | println!("{}", mutex.lock().unwrap().i); + | --------------------- another value with significant `Drop` created here +LL | }, +LL | }; + | - temporary lives until here + | + = note: this might lead to deadlocks or other unexpected behavior help: try moving the temporary above the match | LL ~ mutex.lock().unwrap().i = i; LL ~ match () { | -error: temporary with significant drop in match scrutinee - --> $DIR/significant_drop_in_scrutinee.rs:504:11 +error: temporary with significant `Drop` in `match` scrutinee will live until the end of the `match` expression + --> $DIR/significant_drop_in_scrutinee.rs:517:11 | LL | match i = mutex.lock().unwrap().i { | ^^^^^^^^^^^^^^^^^^^^^^^^^^^ - | +LL | _ => { +LL | println!("{}", mutex.lock().unwrap().i); + | --------------------- another value with significant `Drop` created here +LL | }, +LL | }; + | - temporary lives until here + | + = note: this might lead to deadlocks or other unexpected behavior help: try moving the temporary above the match | LL ~ i = mutex.lock().unwrap().i; LL ~ match () { | -error: temporary with significant drop in match scrutinee - --> $DIR/significant_drop_in_scrutinee.rs:510:11 +error: temporary with significant `Drop` in `match` scrutinee will live until the end of the `match` expression + --> $DIR/significant_drop_in_scrutinee.rs:523:11 | LL | match mutex.lock().unwrap().i += 1 { | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ - | +LL | _ => { +LL | println!("{}", mutex.lock().unwrap().i); + | --------------------- another value with significant `Drop` created here +LL | }, +LL | }; + | - temporary lives until here + | + = note: this might lead to deadlocks or other unexpected behavior help: try moving the temporary above the match | LL ~ mutex.lock().unwrap().i += 1; LL ~ match () { | -error: temporary with significant drop in match scrutinee - --> $DIR/significant_drop_in_scrutinee.rs:516:11 +error: temporary with significant `Drop` in `match` scrutinee will live until the end of the `match` expression + --> $DIR/significant_drop_in_scrutinee.rs:529:11 | LL | match i += mutex.lock().unwrap().i { | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ - | +LL | _ => { +LL | println!("{}", mutex.lock().unwrap().i); + | --------------------- another value with significant `Drop` created here +LL | }, +LL | }; + | - temporary lives until here + | + = note: this might lead to deadlocks or other unexpected behavior help: try moving the temporary above the match | LL ~ i += mutex.lock().unwrap().i; LL ~ match () { | -error: temporary with significant drop in match scrutinee - --> $DIR/significant_drop_in_scrutinee.rs:579:11 +error: temporary with significant `Drop` in `match` scrutinee will live until the end of the `match` expression + --> $DIR/significant_drop_in_scrutinee.rs:592:11 | LL | match rwlock.read().unwrap().to_number() { | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ +... +LL | }; + | - temporary lives until here + | + = note: this might lead to deadlocks or other unexpected behavior -error: temporary with significant drop in for loop - --> $DIR/significant_drop_in_scrutinee.rs:589:14 +error: temporary with significant `Drop` in `for` loop condition will live until the end of the `for` expression + --> $DIR/significant_drop_in_scrutinee.rs:602:14 | LL | for s in rwlock.read().unwrap().iter() { | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ +LL | println!("{}", s); +LL | } + | - temporary lives until here + | + = note: this might lead to deadlocks or other unexpected behavior + +error: temporary with significant `Drop` in `match` scrutinee will live until the end of the `match` expression + --> $DIR/significant_drop_in_scrutinee.rs:617:11 + | +LL | match mutex.lock().unwrap().foo() { + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^ +... +LL | }; + | - temporary lives until here + | + = note: this might lead to deadlocks or other unexpected behavior +help: try moving the temporary above the match + | +LL ~ let value = mutex.lock().unwrap().foo(); +LL ~ match value { + | -error: aborting due to 25 previous errors +error: aborting due to 26 previous errors diff --git a/src/tools/clippy/tests/ui/single_match.stderr b/src/tools/clippy/tests/ui/single_match.stderr index 318faf25717..4d2b9ec5f90 100644 --- a/src/tools/clippy/tests/ui/single_match.stderr +++ b/src/tools/clippy/tests/ui/single_match.stderr @@ -39,6 +39,15 @@ LL | | }; | |_____^ help: try this: `if let (2..=3, 7..=9) = z { dummy() }` error: you seem to be trying to use `match` for destructuring a single pattern. Consider using `if let` + --> $DIR/single_match.rs:54:5 + | +LL | / match x { +LL | | Some(y) => dummy(), +LL | | None => (), +LL | | }; + | |_____^ help: try this: `if let Some(y) = x { dummy() }` + +error: you seem to be trying to use `match` for destructuring a single pattern. Consider using `if let` --> $DIR/single_match.rs:59:5 | LL | / match y { @@ -146,5 +155,5 @@ LL | | (..) => {}, LL | | } | |_____^ help: try this: `if let (.., Some(E::V), _) = (Some(42), Some(E::V), Some(42)) {}` -error: aborting due to 15 previous errors +error: aborting due to 16 previous errors diff --git a/src/tools/clippy/tests/ui/single_match_else.rs b/src/tools/clippy/tests/ui/single_match_else.rs index 82387f3d80b..70d6febb71f 100644 --- a/src/tools/clippy/tests/ui/single_match_else.rs +++ b/src/tools/clippy/tests/ui/single_match_else.rs @@ -97,4 +97,23 @@ fn main() { return; }, } + + // lint here + use std::convert::Infallible; + match Result::<i32, Infallible>::Ok(1) { + Ok(a) => println!("${:?}", a), + Err(_) => { + println!("else block"); + return; + } + } + + use std::borrow::Cow; + match Cow::from("moo") { + Cow::Owned(a) => println!("${:?}", a), + Cow::Borrowed(_) => { + println!("else block"); + return; + } + } } diff --git a/src/tools/clippy/tests/ui/single_match_else.stderr b/src/tools/clippy/tests/ui/single_match_else.stderr index 7756c6f204e..38fd9c6a678 100644 --- a/src/tools/clippy/tests/ui/single_match_else.stderr +++ b/src/tools/clippy/tests/ui/single_match_else.stderr @@ -20,5 +20,85 @@ LL + None LL ~ }; | -error: aborting due to previous error +error: you seem to be trying to use `match` for destructuring a single pattern. Consider using `if let` + --> $DIR/single_match_else.rs:84:5 + | +LL | / match Some(1) { +LL | | Some(a) => println!("${:?}", a), +LL | | None => { +LL | | println!("else block"); +LL | | return +LL | | }, +LL | | } + | |_____^ + | +help: try this + | +LL ~ if let Some(a) = Some(1) { println!("${:?}", a) } else { +LL + println!("else block"); +LL + return +LL + } + | + +error: you seem to be trying to use `match` for destructuring a single pattern. Consider using `if let` + --> $DIR/single_match_else.rs:93:5 + | +LL | / match Some(1) { +LL | | Some(a) => println!("${:?}", a), +LL | | None => { +LL | | println!("else block"); +LL | | return; +LL | | }, +LL | | } + | |_____^ + | +help: try this + | +LL ~ if let Some(a) = Some(1) { println!("${:?}", a) } else { +LL + println!("else block"); +LL + return; +LL + } + | + +error: you seem to be trying to use `match` for destructuring a single pattern. Consider using `if let` + --> $DIR/single_match_else.rs:103:5 + | +LL | / match Result::<i32, Infallible>::Ok(1) { +LL | | Ok(a) => println!("${:?}", a), +LL | | Err(_) => { +LL | | println!("else block"); +LL | | return; +LL | | } +LL | | } + | |_____^ + | +help: try this + | +LL ~ if let Ok(a) = Result::<i32, Infallible>::Ok(1) { println!("${:?}", a) } else { +LL + println!("else block"); +LL + return; +LL + } + | + +error: you seem to be trying to use `match` for destructuring a single pattern. Consider using `if let` + --> $DIR/single_match_else.rs:112:5 + | +LL | / match Cow::from("moo") { +LL | | Cow::Owned(a) => println!("${:?}", a), +LL | | Cow::Borrowed(_) => { +LL | | println!("else block"); +LL | | return; +LL | | } +LL | | } + | |_____^ + | +help: try this + | +LL ~ if let Cow::Owned(a) = Cow::from("moo") { println!("${:?}", a) } else { +LL + println!("else block"); +LL + return; +LL + } + | + +error: aborting due to 5 previous errors diff --git a/src/tools/clippy/tests/ui/slow_vector_initialization.rs b/src/tools/clippy/tests/ui/slow_vector_initialization.rs index 7e3d357ae50..16be9f6d203 100644 --- a/src/tools/clippy/tests/ui/slow_vector_initialization.rs +++ b/src/tools/clippy/tests/ui/slow_vector_initialization.rs @@ -19,6 +19,9 @@ fn extend_vector() { // Extend with mismatching expression should not be warned let mut vec3 = Vec::with_capacity(24322); vec3.extend(repeat(0).take(2)); + + let mut vec4 = Vec::with_capacity(len); + vec4.extend(repeat(0).take(vec4.capacity())); } fn mixed_extend_resize_vector() { @@ -48,6 +51,9 @@ fn resize_vector() { let mut vec3 = Vec::with_capacity(len - 10); vec3.resize(len - 10, 0); + let mut vec4 = Vec::with_capacity(len); + vec4.resize(vec4.capacity(), 0); + // Reinitialization should be warned vec1 = Vec::with_capacity(10); vec1.resize(10, 0); diff --git a/src/tools/clippy/tests/ui/slow_vector_initialization.stderr b/src/tools/clippy/tests/ui/slow_vector_initialization.stderr index 5d2788ec260..cb3ce3e95a7 100644 --- a/src/tools/clippy/tests/ui/slow_vector_initialization.stderr +++ b/src/tools/clippy/tests/ui/slow_vector_initialization.stderr @@ -17,7 +17,15 @@ LL | vec2.extend(repeat(0).take(len - 10)); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ error: slow zero-filling initialization - --> $DIR/slow_vector_initialization.rs:31:5 + --> $DIR/slow_vector_initialization.rs:24:5 + | +LL | let mut vec4 = Vec::with_capacity(len); + | ----------------------- help: consider replace allocation with: `vec![0; len]` +LL | vec4.extend(repeat(0).take(vec4.capacity())); + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +error: slow zero-filling initialization + --> $DIR/slow_vector_initialization.rs:34:5 | LL | let mut resized_vec = Vec::with_capacity(30); | ---------------------- help: consider replace allocation with: `vec![0; 30]` @@ -25,7 +33,7 @@ LL | resized_vec.resize(30, 0); | ^^^^^^^^^^^^^^^^^^^^^^^^^ error: slow zero-filling initialization - --> $DIR/slow_vector_initialization.rs:34:5 + --> $DIR/slow_vector_initialization.rs:37:5 | LL | let mut extend_vec = Vec::with_capacity(30); | ---------------------- help: consider replace allocation with: `vec![0; 30]` @@ -33,7 +41,7 @@ LL | extend_vec.extend(repeat(0).take(30)); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ error: slow zero-filling initialization - --> $DIR/slow_vector_initialization.rs:41:5 + --> $DIR/slow_vector_initialization.rs:44:5 | LL | let mut vec1 = Vec::with_capacity(len); | ----------------------- help: consider replace allocation with: `vec![0; len]` @@ -41,7 +49,7 @@ LL | vec1.resize(len, 0); | ^^^^^^^^^^^^^^^^^^^ error: slow zero-filling initialization - --> $DIR/slow_vector_initialization.rs:49:5 + --> $DIR/slow_vector_initialization.rs:52:5 | LL | let mut vec3 = Vec::with_capacity(len - 10); | ---------------------------- help: consider replace allocation with: `vec![0; len - 10]` @@ -49,12 +57,20 @@ LL | vec3.resize(len - 10, 0); | ^^^^^^^^^^^^^^^^^^^^^^^^ error: slow zero-filling initialization - --> $DIR/slow_vector_initialization.rs:53:5 + --> $DIR/slow_vector_initialization.rs:55:5 + | +LL | let mut vec4 = Vec::with_capacity(len); + | ----------------------- help: consider replace allocation with: `vec![0; len]` +LL | vec4.resize(vec4.capacity(), 0); + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +error: slow zero-filling initialization + --> $DIR/slow_vector_initialization.rs:59:5 | LL | vec1 = Vec::with_capacity(10); | ---------------------- help: consider replace allocation with: `vec![0; 10]` LL | vec1.resize(10, 0); | ^^^^^^^^^^^^^^^^^^ -error: aborting due to 7 previous errors +error: aborting due to 9 previous errors diff --git a/src/tools/clippy/tests/ui/transmute_ptr_to_ref.fixed b/src/tools/clippy/tests/ui/transmute_ptr_to_ref.fixed new file mode 100644 index 00000000000..e5fe9133f97 --- /dev/null +++ b/src/tools/clippy/tests/ui/transmute_ptr_to_ref.fixed @@ -0,0 +1,78 @@ +// run-rustfix + +#![feature(custom_inner_attributes)] +#![warn(clippy::transmute_ptr_to_ref)] +#![allow(clippy::match_single_binding)] + +unsafe fn _ptr_to_ref<T, U>(p: *const T, m: *mut T, o: *const U, om: *mut U) { + let _: &T = &*p; + let _: &T = &*p; + + let _: &mut T = &mut *m; + let _: &mut T = &mut *m; + + let _: &T = &*m; + let _: &T = &*m; + + let _: &mut T = &mut *(p as *mut T); + let _ = &mut *(p as *mut T); + + let _: &T = &*(o as *const T); + let _: &T = &*(o as *const T); + + let _: &mut T = &mut *(om as *mut T); + let _: &mut T = &mut *(om as *mut T); + + let _: &T = &*(om as *const T); + let _: &T = &*(om as *const T); +} + +fn _issue1231() { + struct Foo<'a, T> { + bar: &'a T, + } + + let raw = 42 as *const i32; + let _: &Foo<u8> = unsafe { &*raw.cast::<Foo<_>>() }; + + let _: &Foo<&u8> = unsafe { &*raw.cast::<Foo<&_>>() }; + + type Bar<'a> = &'a u8; + let raw = 42 as *const i32; + unsafe { &*(raw as *const u8) }; +} + +unsafe fn _issue8924<'a, 'b, 'c>(x: *const &'a u32, y: *const &'b u32) -> &'c &'b u32 { + match 0 { + 0 => &*x.cast::<&u32>(), + 1 => &*y.cast::<&u32>(), + 2 => &*x.cast::<&'b u32>(), + _ => &*y.cast::<&'b u32>(), + } +} + +unsafe fn _meets_msrv<'a, 'b, 'c>(x: *const &'a u32) -> &'c &'b u32 { + #![clippy::msrv = "1.38"] + let a = 0u32; + let a = &a as *const u32; + let _: &u32 = &*a; + let _: &u32 = &*a.cast::<u32>(); + match 0 { + 0 => &*x.cast::<&u32>(), + _ => &*x.cast::<&'b u32>(), + } +} + +unsafe fn _under_msrv<'a, 'b, 'c>(x: *const &'a u32) -> &'c &'b u32 { + #![clippy::msrv = "1.37"] + let a = 0u32; + let a = &a as *const u32; + let _: &u32 = &*a; + let _: &u32 = &*(a as *const u32); + match 0 { + 0 => &*(x as *const () as *const &u32), + _ => &*(x as *const () as *const &'b u32), + } +} + +fn main() {} diff --git a/src/tools/clippy/tests/ui/transmute_ptr_to_ref.rs b/src/tools/clippy/tests/ui/transmute_ptr_to_ref.rs index ba35c6adc4d..fe49cdc324f 100644 --- a/src/tools/clippy/tests/ui/transmute_ptr_to_ref.rs +++ b/src/tools/clippy/tests/ui/transmute_ptr_to_ref.rs @@ -1,4 +1,8 @@ +// run-rustfix + +#![feature(custom_inner_attributes)] #![warn(clippy::transmute_ptr_to_ref)] +#![allow(clippy::match_single_binding)] unsafe fn _ptr_to_ref<T, U>(p: *const T, m: *mut T, o: *const U, om: *mut U) { let _: &T = std::mem::transmute(p); @@ -23,7 +27,7 @@ unsafe fn _ptr_to_ref<T, U>(p: *const T, m: *mut T, o: *const U, om: *mut U) { let _: &T = &*(om as *const T); } -fn issue1231() { +fn _issue1231() { struct Foo<'a, T> { bar: &'a T, } @@ -38,4 +42,37 @@ fn issue1231() { unsafe { std::mem::transmute::<_, Bar>(raw) }; } +unsafe fn _issue8924<'a, 'b, 'c>(x: *const &'a u32, y: *const &'b u32) -> &'c &'b u32 { + match 0 { + 0 => std::mem::transmute(x), + 1 => std::mem::transmute(y), + 2 => std::mem::transmute::<_, &&'b u32>(x), + _ => std::mem::transmute::<_, &&'b u32>(y), + } +} + +unsafe fn _meets_msrv<'a, 'b, 'c>(x: *const &'a u32) -> &'c &'b u32 { + #![clippy::msrv = "1.38"] + let a = 0u32; + let a = &a as *const u32; + let _: &u32 = std::mem::transmute(a); + let _: &u32 = std::mem::transmute::<_, &u32>(a); + match 0 { + 0 => std::mem::transmute(x), + _ => std::mem::transmute::<_, &&'b u32>(x), + } +} + +unsafe fn _under_msrv<'a, 'b, 'c>(x: *const &'a u32) -> &'c &'b u32 { + #![clippy::msrv = "1.37"] + let a = 0u32; + let a = &a as *const u32; + let _: &u32 = std::mem::transmute(a); + let _: &u32 = std::mem::transmute::<_, &u32>(a); + match 0 { + 0 => std::mem::transmute(x), + _ => std::mem::transmute::<_, &&'b u32>(x), + } +} + fn main() {} diff --git a/src/tools/clippy/tests/ui/transmute_ptr_to_ref.stderr b/src/tools/clippy/tests/ui/transmute_ptr_to_ref.stderr index df0598a58cd..2993e5e7b0c 100644 --- a/src/tools/clippy/tests/ui/transmute_ptr_to_ref.stderr +++ b/src/tools/clippy/tests/ui/transmute_ptr_to_ref.stderr @@ -1,5 +1,5 @@ error: transmute from a pointer type (`*const T`) to a reference type (`&T`) - --> $DIR/transmute_ptr_to_ref.rs:4:17 + --> $DIR/transmute_ptr_to_ref.rs:8:17 | LL | let _: &T = std::mem::transmute(p); | ^^^^^^^^^^^^^^^^^^^^^^ help: try: `&*p` @@ -7,58 +7,130 @@ LL | let _: &T = std::mem::transmute(p); = note: `-D clippy::transmute-ptr-to-ref` implied by `-D warnings` error: transmute from a pointer type (`*mut T`) to a reference type (`&mut T`) - --> $DIR/transmute_ptr_to_ref.rs:7:21 + --> $DIR/transmute_ptr_to_ref.rs:11:21 | LL | let _: &mut T = std::mem::transmute(m); | ^^^^^^^^^^^^^^^^^^^^^^ help: try: `&mut *m` error: transmute from a pointer type (`*mut T`) to a reference type (`&T`) - --> $DIR/transmute_ptr_to_ref.rs:10:17 + --> $DIR/transmute_ptr_to_ref.rs:14:17 | LL | let _: &T = std::mem::transmute(m); | ^^^^^^^^^^^^^^^^^^^^^^ help: try: `&*m` error: transmute from a pointer type (`*mut T`) to a reference type (`&mut T`) - --> $DIR/transmute_ptr_to_ref.rs:13:21 + --> $DIR/transmute_ptr_to_ref.rs:17:21 | LL | let _: &mut T = std::mem::transmute(p as *mut T); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `&mut *(p as *mut T)` error: transmute from a pointer type (`*const U`) to a reference type (`&T`) - --> $DIR/transmute_ptr_to_ref.rs:16:17 + --> $DIR/transmute_ptr_to_ref.rs:20:17 | LL | let _: &T = std::mem::transmute(o); | ^^^^^^^^^^^^^^^^^^^^^^ help: try: `&*(o as *const T)` error: transmute from a pointer type (`*mut U`) to a reference type (`&mut T`) - --> $DIR/transmute_ptr_to_ref.rs:19:21 + --> $DIR/transmute_ptr_to_ref.rs:23:21 | LL | let _: &mut T = std::mem::transmute(om); | ^^^^^^^^^^^^^^^^^^^^^^^ help: try: `&mut *(om as *mut T)` error: transmute from a pointer type (`*mut U`) to a reference type (`&T`) - --> $DIR/transmute_ptr_to_ref.rs:22:17 + --> $DIR/transmute_ptr_to_ref.rs:26:17 | LL | let _: &T = std::mem::transmute(om); | ^^^^^^^^^^^^^^^^^^^^^^^ help: try: `&*(om as *const T)` -error: transmute from a pointer type (`*const i32`) to a reference type (`&issue1231::Foo<u8>`) - --> $DIR/transmute_ptr_to_ref.rs:32:32 +error: transmute from a pointer type (`*const i32`) to a reference type (`&_issue1231::Foo<u8>`) + --> $DIR/transmute_ptr_to_ref.rs:36:32 | LL | let _: &Foo<u8> = unsafe { std::mem::transmute::<_, &Foo<_>>(raw) }; - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `&*(raw as *const Foo<_>)` + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `&*raw.cast::<Foo<_>>()` -error: transmute from a pointer type (`*const i32`) to a reference type (`&issue1231::Foo<&u8>`) - --> $DIR/transmute_ptr_to_ref.rs:34:33 +error: transmute from a pointer type (`*const i32`) to a reference type (`&_issue1231::Foo<&u8>`) + --> $DIR/transmute_ptr_to_ref.rs:38:33 | LL | let _: &Foo<&u8> = unsafe { std::mem::transmute::<_, &Foo<&_>>(raw) }; - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `&*(raw as *const Foo<&_>)` + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `&*raw.cast::<Foo<&_>>()` error: transmute from a pointer type (`*const i32`) to a reference type (`&u8`) - --> $DIR/transmute_ptr_to_ref.rs:38:14 + --> $DIR/transmute_ptr_to_ref.rs:42:14 | LL | unsafe { std::mem::transmute::<_, Bar>(raw) }; | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `&*(raw as *const u8)` -error: aborting due to 10 previous errors +error: transmute from a pointer type (`*const &u32`) to a reference type (`&&u32`) + --> $DIR/transmute_ptr_to_ref.rs:47:14 + | +LL | 0 => std::mem::transmute(x), + | ^^^^^^^^^^^^^^^^^^^^^^ help: try: `&*x.cast::<&u32>()` + +error: transmute from a pointer type (`*const &u32`) to a reference type (`&&u32`) + --> $DIR/transmute_ptr_to_ref.rs:48:14 + | +LL | 1 => std::mem::transmute(y), + | ^^^^^^^^^^^^^^^^^^^^^^ help: try: `&*y.cast::<&u32>()` + +error: transmute from a pointer type (`*const &u32`) to a reference type (`&&u32`) + --> $DIR/transmute_ptr_to_ref.rs:49:14 + | +LL | 2 => std::mem::transmute::<_, &&'b u32>(x), + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `&*x.cast::<&'b u32>()` + +error: transmute from a pointer type (`*const &u32`) to a reference type (`&&u32`) + --> $DIR/transmute_ptr_to_ref.rs:50:14 + | +LL | _ => std::mem::transmute::<_, &&'b u32>(y), + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `&*y.cast::<&'b u32>()` + +error: transmute from a pointer type (`*const u32`) to a reference type (`&u32`) + --> $DIR/transmute_ptr_to_ref.rs:58:19 + | +LL | let _: &u32 = std::mem::transmute(a); + | ^^^^^^^^^^^^^^^^^^^^^^ help: try: `&*a` + +error: transmute from a pointer type (`*const u32`) to a reference type (`&u32`) + --> $DIR/transmute_ptr_to_ref.rs:59:19 + | +LL | let _: &u32 = std::mem::transmute::<_, &u32>(a); + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `&*a.cast::<u32>()` + +error: transmute from a pointer type (`*const &u32`) to a reference type (`&&u32`) + --> $DIR/transmute_ptr_to_ref.rs:61:14 + | +LL | 0 => std::mem::transmute(x), + | ^^^^^^^^^^^^^^^^^^^^^^ help: try: `&*x.cast::<&u32>()` + +error: transmute from a pointer type (`*const &u32`) to a reference type (`&&u32`) + --> $DIR/transmute_ptr_to_ref.rs:62:14 + | +LL | _ => std::mem::transmute::<_, &&'b u32>(x), + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `&*x.cast::<&'b u32>()` + +error: transmute from a pointer type (`*const u32`) to a reference type (`&u32`) + --> $DIR/transmute_ptr_to_ref.rs:70:19 + | +LL | let _: &u32 = std::mem::transmute(a); + | ^^^^^^^^^^^^^^^^^^^^^^ help: try: `&*a` + +error: transmute from a pointer type (`*const u32`) to a reference type (`&u32`) + --> $DIR/transmute_ptr_to_ref.rs:71:19 + | +LL | let _: &u32 = std::mem::transmute::<_, &u32>(a); + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `&*(a as *const u32)` + +error: transmute from a pointer type (`*const &u32`) to a reference type (`&&u32`) + --> $DIR/transmute_ptr_to_ref.rs:73:14 + | +LL | 0 => std::mem::transmute(x), + | ^^^^^^^^^^^^^^^^^^^^^^ help: try: `&*(x as *const () as *const &u32)` + +error: transmute from a pointer type (`*const &u32`) to a reference type (`&&u32`) + --> $DIR/transmute_ptr_to_ref.rs:74:14 + | +LL | _ => std::mem::transmute::<_, &&'b u32>(x), + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `&*(x as *const () as *const &'b u32)` + +error: aborting due to 22 previous errors diff --git a/src/tools/clippy/tests/ui/trivially_copy_pass_by_ref.rs b/src/tools/clippy/tests/ui/trivially_copy_pass_by_ref.rs index ea3dce17081..8f78f16a0a1 100644 --- a/src/tools/clippy/tests/ui/trivially_copy_pass_by_ref.rs +++ b/src/tools/clippy/tests/ui/trivially_copy_pass_by_ref.rs @@ -113,6 +113,44 @@ mod issue5876 { } } +fn _ref_to_opt_ref_implicit(x: &u32) -> Option<&u32> { + Some(x) +} + +#[allow(clippy::needless_lifetimes)] +fn _ref_to_opt_ref_explicit<'a>(x: &'a u32) -> Option<&'a u32> { + Some(x) +} + +fn _with_constraint<'a, 'b: 'a>(x: &'b u32, y: &'a u32) -> &'a u32 { + if true { x } else { y } +} + +async fn _async_implicit(x: &u32) -> &u32 { + x +} + +#[allow(clippy::needless_lifetimes)] +async fn _async_explicit<'a>(x: &'a u32) -> &'a u32 { + x +} + +fn _unrelated_lifetimes<'a, 'b>(_x: &'a u32, y: &'b u32) -> &'b u32 { + y +} + +fn _return_ptr(x: &u32) -> *const u32 { + x +} + +fn _return_field_ptr(x: &(u32, u32)) -> *const u32 { + &x.0 +} + +fn _return_field_ptr_addr_of(x: &(u32, u32)) -> *const u32 { + core::ptr::addr_of!(x.0) +} + fn main() { let (mut foo, bar) = (Foo(0), Bar([0; 24])); let (mut a, b, c, x, y, z) = (0, 0, Bar([0; 24]), 0, Foo(0), 0); diff --git a/src/tools/clippy/tests/ui/trivially_copy_pass_by_ref.stderr b/src/tools/clippy/tests/ui/trivially_copy_pass_by_ref.stderr index a88d35f3ea5..66ecb3d8e77 100644 --- a/src/tools/clippy/tests/ui/trivially_copy_pass_by_ref.stderr +++ b/src/tools/clippy/tests/ui/trivially_copy_pass_by_ref.stderr @@ -106,5 +106,11 @@ error: this argument (N byte) is passed by reference, but would be more efficien LL | fn foo(x: &i32) { | ^^^^ help: consider passing by value instead: `i32` -error: aborting due to 17 previous errors +error: this argument (N byte) is passed by reference, but would be more efficient if passed by value (limit: N byte) + --> $DIR/trivially_copy_pass_by_ref.rs:138:37 + | +LL | fn _unrelated_lifetimes<'a, 'b>(_x: &'a u32, y: &'b u32) -> &'b u32 { + | ^^^^^^^ help: consider passing by value instead: `u32` + +error: aborting due to 18 previous errors diff --git a/src/tools/clippy/tests/ui/unused_async.rs b/src/tools/clippy/tests/ui/unused_async.rs index 2a3a506a57b..4ca7f29b34c 100644 --- a/src/tools/clippy/tests/ui/unused_async.rs +++ b/src/tools/clippy/tests/ui/unused_async.rs @@ -1,5 +1,8 @@ #![warn(clippy::unused_async)] +use std::future::Future; +use std::pin::Pin; + async fn foo() -> i32 { 4 } @@ -8,6 +11,37 @@ async fn bar() -> i32 { foo().await } +struct S; + +impl S { + async fn unused(&self) -> i32 { + 1 + } + + async fn used(&self) -> i32 { + self.unused().await + } +} + +trait AsyncTrait { + fn trait_method() -> Pin<Box<dyn Future<Output = i32>>>; +} + +macro_rules! async_trait_impl { + () => { + impl AsyncTrait for S { + fn trait_method() -> Pin<Box<dyn Future<Output = i32>>> { + async fn unused() -> i32 { + 5 + } + + Box::pin(unused()) + } + } + }; +} +async_trait_impl!(); + fn main() { foo(); bar(); diff --git a/src/tools/clippy/tests/ui/unused_async.stderr b/src/tools/clippy/tests/ui/unused_async.stderr index cc6096d65d9..8b8ad065a4c 100644 --- a/src/tools/clippy/tests/ui/unused_async.stderr +++ b/src/tools/clippy/tests/ui/unused_async.stderr @@ -1,5 +1,5 @@ error: unused `async` for function with no await statements - --> $DIR/unused_async.rs:3:1 + --> $DIR/unused_async.rs:6:1 | LL | / async fn foo() -> i32 { LL | | 4 @@ -9,5 +9,15 @@ LL | | } = note: `-D clippy::unused-async` implied by `-D warnings` = help: consider removing the `async` from this function -error: aborting due to previous error +error: unused `async` for function with no await statements + --> $DIR/unused_async.rs:17:5 + | +LL | / async fn unused(&self) -> i32 { +LL | | 1 +LL | | } + | |_____^ + | + = help: consider removing the `async` from this function + +error: aborting due to 2 previous errors diff --git a/src/tools/clippy/tests/ui/useless_asref.fixed b/src/tools/clippy/tests/ui/useless_asref.fixed index e431661d180..90cb8945e77 100644 --- a/src/tools/clippy/tests/ui/useless_asref.fixed +++ b/src/tools/clippy/tests/ui/useless_asref.fixed @@ -1,6 +1,7 @@ // run-rustfix #![deny(clippy::useless_asref)] +#![allow(clippy::explicit_auto_deref)] use std::fmt::Debug; diff --git a/src/tools/clippy/tests/ui/useless_asref.rs b/src/tools/clippy/tests/ui/useless_asref.rs index 6ae931d7aa4..cb9f8ae5909 100644 --- a/src/tools/clippy/tests/ui/useless_asref.rs +++ b/src/tools/clippy/tests/ui/useless_asref.rs @@ -1,6 +1,7 @@ // run-rustfix #![deny(clippy::useless_asref)] +#![allow(clippy::explicit_auto_deref)] use std::fmt::Debug; diff --git a/src/tools/clippy/tests/ui/useless_asref.stderr b/src/tools/clippy/tests/ui/useless_asref.stderr index 5876b54aca8..b21c67bb364 100644 --- a/src/tools/clippy/tests/ui/useless_asref.stderr +++ b/src/tools/clippy/tests/ui/useless_asref.stderr @@ -1,5 +1,5 @@ error: this call to `as_ref` does nothing - --> $DIR/useless_asref.rs:43:18 + --> $DIR/useless_asref.rs:44:18 | LL | foo_rstr(rstr.as_ref()); | ^^^^^^^^^^^^^ help: try this: `rstr` @@ -11,61 +11,61 @@ LL | #![deny(clippy::useless_asref)] | ^^^^^^^^^^^^^^^^^^^^^ error: this call to `as_ref` does nothing - --> $DIR/useless_asref.rs:45:20 + --> $DIR/useless_asref.rs:46:20 | LL | foo_rslice(rslice.as_ref()); | ^^^^^^^^^^^^^^^ help: try this: `rslice` error: this call to `as_mut` does nothing - --> $DIR/useless_asref.rs:49:21 + --> $DIR/useless_asref.rs:50:21 | LL | foo_mrslice(mrslice.as_mut()); | ^^^^^^^^^^^^^^^^ help: try this: `mrslice` error: this call to `as_ref` does nothing - --> $DIR/useless_asref.rs:51:20 + --> $DIR/useless_asref.rs:52:20 | LL | foo_rslice(mrslice.as_ref()); | ^^^^^^^^^^^^^^^^ help: try this: `mrslice` error: this call to `as_ref` does nothing - --> $DIR/useless_asref.rs:58:20 + --> $DIR/useless_asref.rs:59:20 | LL | foo_rslice(rrrrrslice.as_ref()); | ^^^^^^^^^^^^^^^^^^^ help: try this: `rrrrrslice` error: this call to `as_ref` does nothing - --> $DIR/useless_asref.rs:60:18 + --> $DIR/useless_asref.rs:61:18 | LL | foo_rstr(rrrrrstr.as_ref()); | ^^^^^^^^^^^^^^^^^ help: try this: `rrrrrstr` error: this call to `as_mut` does nothing - --> $DIR/useless_asref.rs:65:21 + --> $DIR/useless_asref.rs:66:21 | LL | foo_mrslice(mrrrrrslice.as_mut()); | ^^^^^^^^^^^^^^^^^^^^ help: try this: `mrrrrrslice` error: this call to `as_ref` does nothing - --> $DIR/useless_asref.rs:67:20 + --> $DIR/useless_asref.rs:68:20 | LL | foo_rslice(mrrrrrslice.as_ref()); | ^^^^^^^^^^^^^^^^^^^^ help: try this: `mrrrrrslice` error: this call to `as_ref` does nothing - --> $DIR/useless_asref.rs:71:16 + --> $DIR/useless_asref.rs:72:16 | LL | foo_rrrrmr((&&&&MoreRef).as_ref()); | ^^^^^^^^^^^^^^^^^^^^^^ help: try this: `(&&&&MoreRef)` error: this call to `as_mut` does nothing - --> $DIR/useless_asref.rs:121:13 + --> $DIR/useless_asref.rs:122:13 | LL | foo_mrt(mrt.as_mut()); | ^^^^^^^^^^^^ help: try this: `mrt` error: this call to `as_ref` does nothing - --> $DIR/useless_asref.rs:123:12 + --> $DIR/useless_asref.rs:124:12 | LL | foo_rt(mrt.as_ref()); | ^^^^^^^^^^^^ help: try this: `mrt` diff --git a/src/tools/clippy/tests/ui/while_let_loop.rs b/src/tools/clippy/tests/ui/while_let_loop.rs index 3ce699f551b..c42e2a79a9b 100644 --- a/src/tools/clippy/tests/ui/while_let_loop.rs +++ b/src/tools/clippy/tests/ui/while_let_loop.rs @@ -117,3 +117,29 @@ fn issue1948() { } }; } + +fn issue_7913(m: &std::sync::Mutex<Vec<u32>>) { + // Don't lint. The lock shouldn't be held while printing. + loop { + let x = if let Some(x) = m.lock().unwrap().pop() { + x + } else { + break; + }; + + println!("{}", x); + } +} + +fn issue_5715(mut m: core::cell::RefCell<Option<u32>>) { + // Don't lint. The temporary from `borrow_mut` must be dropped before overwriting the `RefCell`. + loop { + let x = if let &mut Some(x) = &mut *m.borrow_mut() { + x + } else { + break; + }; + + m = core::cell::RefCell::new(Some(x + 1)); + } +} diff --git a/src/tools/clippy/tests/ui/while_let_on_iterator.fixed b/src/tools/clippy/tests/ui/while_let_on_iterator.fixed index cb8892a3f00..e9ff64431e1 100644 --- a/src/tools/clippy/tests/ui/while_let_on_iterator.fixed +++ b/src/tools/clippy/tests/ui/while_let_on_iterator.fixed @@ -6,7 +6,8 @@ unreachable_code, unused_mut, dead_code, - clippy::equatable_if_let + clippy::equatable_if_let, + clippy::manual_find )] fn base() { diff --git a/src/tools/clippy/tests/ui/while_let_on_iterator.rs b/src/tools/clippy/tests/ui/while_let_on_iterator.rs index d9157184495..03da39526b2 100644 --- a/src/tools/clippy/tests/ui/while_let_on_iterator.rs +++ b/src/tools/clippy/tests/ui/while_let_on_iterator.rs @@ -6,7 +6,8 @@ unreachable_code, unused_mut, dead_code, - clippy::equatable_if_let + clippy::equatable_if_let, + clippy::manual_find )] fn base() { diff --git a/src/tools/clippy/tests/ui/while_let_on_iterator.stderr b/src/tools/clippy/tests/ui/while_let_on_iterator.stderr index fb2b0f2467c..42859243855 100644 --- a/src/tools/clippy/tests/ui/while_let_on_iterator.stderr +++ b/src/tools/clippy/tests/ui/while_let_on_iterator.stderr @@ -1,5 +1,5 @@ error: this loop could be written as a `for` loop - --> $DIR/while_let_on_iterator.rs:14:5 + --> $DIR/while_let_on_iterator.rs:15:5 | LL | while let Option::Some(x) = iter.next() { | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `for x in iter` @@ -7,85 +7,85 @@ LL | while let Option::Some(x) = iter.next() { = note: `-D clippy::while-let-on-iterator` implied by `-D warnings` error: this loop could be written as a `for` loop - --> $DIR/while_let_on_iterator.rs:19:5 + --> $DIR/while_let_on_iterator.rs:20:5 | LL | while let Some(x) = iter.next() { | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `for x in iter` error: this loop could be written as a `for` loop - --> $DIR/while_let_on_iterator.rs:24:5 + --> $DIR/while_let_on_iterator.rs:25:5 | LL | while let Some(_) = iter.next() {} | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `for _ in iter` error: this loop could be written as a `for` loop - --> $DIR/while_let_on_iterator.rs:100:9 + --> $DIR/while_let_on_iterator.rs:101:9 | LL | while let Some([..]) = it.next() {} | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `for [..] in it` error: this loop could be written as a `for` loop - --> $DIR/while_let_on_iterator.rs:107:9 + --> $DIR/while_let_on_iterator.rs:108:9 | LL | while let Some([_x]) = it.next() {} | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `for [_x] in it` error: this loop could be written as a `for` loop - --> $DIR/while_let_on_iterator.rs:120:9 + --> $DIR/while_let_on_iterator.rs:121:9 | LL | while let Some(x @ [_]) = it.next() { | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `for x @ [_] in it` error: this loop could be written as a `for` loop - --> $DIR/while_let_on_iterator.rs:140:9 + --> $DIR/while_let_on_iterator.rs:141:9 | LL | while let Some(_) = y.next() { | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `for _ in y` error: this loop could be written as a `for` loop - --> $DIR/while_let_on_iterator.rs:197:9 + --> $DIR/while_let_on_iterator.rs:198:9 | LL | while let Some(m) = it.next() { | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `for m in it.by_ref()` error: this loop could be written as a `for` loop - --> $DIR/while_let_on_iterator.rs:208:5 + --> $DIR/while_let_on_iterator.rs:209:5 | LL | while let Some(n) = it.next() { | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `for n in it` error: this loop could be written as a `for` loop - --> $DIR/while_let_on_iterator.rs:210:9 + --> $DIR/while_let_on_iterator.rs:211:9 | LL | while let Some(m) = it.next() { | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `for m in it` error: this loop could be written as a `for` loop - --> $DIR/while_let_on_iterator.rs:219:9 + --> $DIR/while_let_on_iterator.rs:220:9 | LL | while let Some(m) = it.next() { | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `for m in it` error: this loop could be written as a `for` loop - --> $DIR/while_let_on_iterator.rs:228:9 + --> $DIR/while_let_on_iterator.rs:229:9 | LL | while let Some(m) = it.next() { | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `for m in it.by_ref()` error: this loop could be written as a `for` loop - --> $DIR/while_let_on_iterator.rs:245:9 + --> $DIR/while_let_on_iterator.rs:246:9 | LL | while let Some(m) = it.next() { | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `for m in it.by_ref()` error: this loop could be written as a `for` loop - --> $DIR/while_let_on_iterator.rs:260:13 + --> $DIR/while_let_on_iterator.rs:261:13 | LL | while let Some(i) = self.0.next() { | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `for i in self.0.by_ref()` error: manual `!RangeInclusive::contains` implementation - --> $DIR/while_let_on_iterator.rs:261:20 + --> $DIR/while_let_on_iterator.rs:262:20 | LL | if i < 3 || i > 7 { | ^^^^^^^^^^^^^^ help: use: `!(3..=7).contains(&i)` @@ -93,49 +93,49 @@ LL | if i < 3 || i > 7 { = note: `-D clippy::manual-range-contains` implied by `-D warnings` error: this loop could be written as a `for` loop - --> $DIR/while_let_on_iterator.rs:292:13 + --> $DIR/while_let_on_iterator.rs:293:13 | LL | while let Some(i) = self.0.0.0.next() { | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `for i in self.0.0.0.by_ref()` error: this loop could be written as a `for` loop - --> $DIR/while_let_on_iterator.rs:321:5 + --> $DIR/while_let_on_iterator.rs:322:5 | LL | while let Some(n) = it.next() { | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `for n in it.by_ref()` error: this loop could be written as a `for` loop - --> $DIR/while_let_on_iterator.rs:333:9 + --> $DIR/while_let_on_iterator.rs:334:9 | LL | while let Some(x) = it.next() { | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `for x in it.by_ref()` error: this loop could be written as a `for` loop - --> $DIR/while_let_on_iterator.rs:347:5 + --> $DIR/while_let_on_iterator.rs:348:5 | LL | while let Some(x) = it.next() { | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `for x in it.by_ref()` error: this loop could be written as a `for` loop - --> $DIR/while_let_on_iterator.rs:358:5 + --> $DIR/while_let_on_iterator.rs:359:5 | LL | while let Some(x) = it.0.next() { | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `for x in it.0.by_ref()` error: this loop could be written as a `for` loop - --> $DIR/while_let_on_iterator.rs:393:5 + --> $DIR/while_let_on_iterator.rs:394:5 | LL | while let Some(x) = s.x.next() { | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `for x in s.x.by_ref()` error: this loop could be written as a `for` loop - --> $DIR/while_let_on_iterator.rs:400:5 + --> $DIR/while_let_on_iterator.rs:401:5 | LL | while let Some(x) = x[0].next() { | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `for x in x[0].by_ref()` error: this loop could be written as a `for` loop - --> $DIR/while_let_on_iterator.rs:407:5 + --> $DIR/while_let_on_iterator.rs:408:5 | LL | while let Some(..) = it.next() { | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `for _ in it` diff --git a/src/tools/clippy/tests/ui/zero_div_zero.rs b/src/tools/clippy/tests/ui/zero_div_zero.rs index ed3a9208fc3..968c58f40ae 100644 --- a/src/tools/clippy/tests/ui/zero_div_zero.rs +++ b/src/tools/clippy/tests/ui/zero_div_zero.rs @@ -1,4 +1,4 @@ -#[allow(unused_variables)] +#[allow(unused_variables, clippy::eq_op)] #[warn(clippy::zero_divided_by_zero)] fn main() { let nan = 0.0 / 0.0; diff --git a/src/tools/clippy/tests/ui/zero_div_zero.stderr b/src/tools/clippy/tests/ui/zero_div_zero.stderr index 0931dd32e7a..86563542e06 100644 --- a/src/tools/clippy/tests/ui/zero_div_zero.stderr +++ b/src/tools/clippy/tests/ui/zero_div_zero.stderr @@ -1,11 +1,3 @@ -error: equal expressions as operands to `/` - --> $DIR/zero_div_zero.rs:4:15 - | -LL | let nan = 0.0 / 0.0; - | ^^^^^^^^^ - | - = note: `#[deny(clippy::eq_op)]` on by default - error: constant division of `0.0` with `0.0` will always result in NaN --> $DIR/zero_div_zero.rs:4:15 | @@ -15,12 +7,6 @@ LL | let nan = 0.0 / 0.0; = note: `-D clippy::zero-divided-by-zero` implied by `-D warnings` = help: consider using `f64::NAN` if you would like a constant representing NaN -error: equal expressions as operands to `/` - --> $DIR/zero_div_zero.rs:5:19 - | -LL | let f64_nan = 0.0 / 0.0f64; - | ^^^^^^^^^^^^ - error: constant division of `0.0` with `0.0` will always result in NaN --> $DIR/zero_div_zero.rs:5:19 | @@ -29,12 +15,6 @@ LL | let f64_nan = 0.0 / 0.0f64; | = help: consider using `f64::NAN` if you would like a constant representing NaN -error: equal expressions as operands to `/` - --> $DIR/zero_div_zero.rs:6:25 - | -LL | let other_f64_nan = 0.0f64 / 0.0; - | ^^^^^^^^^^^^ - error: constant division of `0.0` with `0.0` will always result in NaN --> $DIR/zero_div_zero.rs:6:25 | @@ -43,12 +23,6 @@ LL | let other_f64_nan = 0.0f64 / 0.0; | = help: consider using `f64::NAN` if you would like a constant representing NaN -error: equal expressions as operands to `/` - --> $DIR/zero_div_zero.rs:7:28 - | -LL | let one_more_f64_nan = 0.0f64 / 0.0f64; - | ^^^^^^^^^^^^^^^ - error: constant division of `0.0` with `0.0` will always result in NaN --> $DIR/zero_div_zero.rs:7:28 | @@ -57,5 +31,5 @@ LL | let one_more_f64_nan = 0.0f64 / 0.0f64; | = help: consider using `f64::NAN` if you would like a constant representing NaN -error: aborting due to 8 previous errors +error: aborting due to 4 previous errors diff --git a/src/tools/clippy/util/gh-pages/index.html b/src/tools/clippy/util/gh-pages/index.html index 4999cce7511..6183089911b 100644 --- a/src/tools/clippy/util/gh-pages/index.html +++ b/src/tools/clippy/util/gh-pages/index.html @@ -10,6 +10,7 @@ Otherwise, have a great day =^.^= <head> <meta charset="UTF-8"/> <meta name="viewport" content="width=device-width, initial-scale=1"/> + <meta name="description" content="A collection of lints to catch common mistakes and improve your Rust code."> <title>Clippy Lints</title> diff --git a/src/tools/compiletest/src/common.rs b/src/tools/compiletest/src/common.rs index bdf26d040ad..be81ff881f3 100644 --- a/src/tools/compiletest/src/common.rs +++ b/src/tools/compiletest/src/common.rs @@ -269,6 +269,10 @@ pub struct Config { /// Flags to pass to the compiler when building for the target pub target_rustcflags: Option<String>, + /// Whether tests should be optimized by default. Individual test-suites and test files may + /// override this setting. + pub optimize_tests: bool, + /// What panic strategy the target is built with. Unwind supports Abort, but /// not vice versa. pub target_panic: PanicStrategy, diff --git a/src/tools/compiletest/src/header.rs b/src/tools/compiletest/src/header.rs index 31e979a574b..7cf4a88c470 100644 --- a/src/tools/compiletest/src/header.rs +++ b/src/tools/compiletest/src/header.rs @@ -244,6 +244,7 @@ impl TestProps { // copy over select properties to the aux build: props.incremental_dir = self.incremental_dir.clone(); + props.ignore_pass = true; props.load_from(testfile, cfg, config); props diff --git a/src/tools/compiletest/src/main.rs b/src/tools/compiletest/src/main.rs index 4e8e5afd4bb..a8a151ca114 100644 --- a/src/tools/compiletest/src/main.rs +++ b/src/tools/compiletest/src/main.rs @@ -102,6 +102,7 @@ pub fn parse_config(args: Vec<String>) -> Config { ) .optmulti("", "host-rustcflags", "flags to pass to rustc for host", "FLAGS") .optmulti("", "target-rustcflags", "flags to pass to rustc for target", "FLAGS") + .optflag("", "optimize-tests", "run tests with optimizations enabled") .optopt("", "target-panic", "what panic strategy the target supports", "unwind | abort") .optflag("", "verbose", "run tests verbosely, showing all output") .optflag( @@ -253,6 +254,7 @@ pub fn parse_config(args: Vec<String>) -> Config { runtool: matches.opt_str("runtool"), host_rustcflags: Some(matches.opt_strs("host-rustcflags").join(" ")), target_rustcflags: Some(matches.opt_strs("target-rustcflags").join(" ")), + optimize_tests: matches.opt_present("optimize-tests"), target_panic: match matches.opt_str("target-panic").as_deref() { Some("unwind") | None => PanicStrategy::Unwind, Some("abort") => PanicStrategy::Abort, diff --git a/src/tools/compiletest/src/runtest.rs b/src/tools/compiletest/src/runtest.rs index 160b9785d97..dd9e2a6687e 100644 --- a/src/tools/compiletest/src/runtest.rs +++ b/src/tools/compiletest/src/runtest.rs @@ -1862,6 +1862,31 @@ impl<'test> TestCx<'test> { } } + if self.config.optimize_tests && !is_rustdoc { + match self.config.mode { + Ui => { + // If optimize-tests is true we still only want to optimize tests that actually get + // executed and that don't specify their own optimization levels. + // Note: aux libs don't have a pass-mode, so they won't get optimized + // unless compile-flags are set in the aux file. + if self.config.optimize_tests + && self.props.pass_mode(&self.config) == Some(PassMode::Run) + && !self + .props + .compile_flags + .iter() + .any(|arg| arg == "-O" || arg.contains("opt-level")) + { + rustc.arg("-O"); + } + } + DebugInfo => { /* debuginfo tests must be unoptimized */ } + _ => { + rustc.arg("-O"); + } + } + } + match self.config.mode { Incremental => { // If we are extracting and matching errors in the new @@ -3245,7 +3270,8 @@ impl<'test> TestCx<'test> { if !self.props.error_patterns.is_empty() { // "// error-pattern" comments - self.check_error_patterns(&proc_res.stderr, &proc_res, pm); + let output_to_check = self.get_output(&proc_res); + self.check_error_patterns(&output_to_check, &proc_res, pm); } } @@ -3266,7 +3292,8 @@ impl<'test> TestCx<'test> { if check_patterns { // "// error-pattern" comments - self.check_error_patterns(&proc_res.stderr, &proc_res, pm); + let output_to_check = self.get_output(&proc_res); + self.check_error_patterns(&output_to_check, &proc_res, pm); } if check_annotations { diff --git a/src/tools/miri b/src/tools/miri -Subproject ff62c3ac98eb85816190afa1c1ec5d0ad2e4423 +Subproject f76ebd6feb9f59be993336f84ecfdc441ad33d8 diff --git a/src/tools/rust-analyzer b/src/tools/rust-analyzer -Subproject b74e96f509baf0be70281c55f14cb18fefbc6b2 +Subproject 75b22326dad1914c22484ab6672de5cae94f745 diff --git a/src/tools/tidy/src/bins.rs b/src/tools/tidy/src/bins.rs index 503df537047..9615c4db6b4 100644 --- a/src/tools/tidy/src/bins.rs +++ b/src/tools/tidy/src/bins.rs @@ -96,9 +96,25 @@ mod os_impl { #[cfg(unix)] pub fn check(path: &Path, bad: &mut bool) { + const ALLOWED: &[&str] = &["configure"]; + crate::walk_no_read( path, - &mut |path| crate::filter_dirs(path) || path.ends_with("src/etc"), + &mut |path| { + crate::filter_dirs(path) + || path.ends_with("src/etc") + // This is a list of directories that we almost certainly + // don't need to walk. A future PR will likely want to + // remove these in favor of crate::walk_no_read using git + // ls-files to discover the paths we should check, which + // would naturally ignore all of these directories. It's + // also likely faster than walking the directory tree + // directly (since git is just reading from a couple files + // to produce the results). + || path.ends_with("target") + || path.ends_with("build") + || path.ends_with(".git") + }, &mut |entry| { let file = entry.path(); let filename = file.file_name().unwrap().to_string_lossy(); @@ -110,6 +126,11 @@ mod os_impl { if t!(is_executable(&file), file) { let rel_path = file.strip_prefix(path).unwrap(); let git_friendly_path = rel_path.to_str().unwrap().replace("\\", "/"); + + if ALLOWED.contains(&git_friendly_path.as_str()) { + return; + } + let output = Command::new("git") .arg("ls-files") .arg(&git_friendly_path) diff --git a/src/tools/tidy/src/main.rs b/src/tools/tidy/src/main.rs index d555f7c8e34..aa8d8b4f64d 100644 --- a/src/tools/tidy/src/main.rs +++ b/src/tools/tidy/src/main.rs @@ -78,13 +78,8 @@ fn main() { check!(unit_tests, &compiler_path); check!(unit_tests, &library_path); - if bins::check_filesystem_support( - &[&src_path, &compiler_path, &library_path], - &output_directory, - ) { - check!(bins, &src_path); - check!(bins, &compiler_path); - check!(bins, &library_path); + if bins::check_filesystem_support(&[&root_path], &output_directory) { + check!(bins, &root_path); } check!(style, &src_path); diff --git a/src/tools/tidy/src/style.rs b/src/tools/tidy/src/style.rs index 5a061009b6b..3cf44a2d7d1 100644 --- a/src/tools/tidy/src/style.rs +++ b/src/tools/tidy/src/style.rs @@ -395,9 +395,6 @@ pub fn check(path: &Path, bad: &mut bool) { ); }; suppressible_tidy_err!(err, skip_file_length, ""); - } else if lines > (LINES * 7) / 10 { - // Just set it to something that doesn't trigger the "unnecessarily ignored" warning. - skip_file_length = Directive::Ignore(true); } if let Directive::Ignore(false) = skip_cr { @@ -406,12 +403,6 @@ pub fn check(path: &Path, bad: &mut bool) { if let Directive::Ignore(false) = skip_tab { tidy_error!(bad, "{}: ignoring tab characters unnecessarily", file.display()); } - if let Directive::Ignore(false) = skip_line_length { - tidy_error!(bad, "{}: ignoring line length unnecessarily", file.display()); - } - if let Directive::Ignore(false) = skip_file_length { - tidy_error!(bad, "{}: ignoring file length unnecessarily", file.display()); - } if let Directive::Ignore(false) = skip_end_whitespace { tidy_error!(bad, "{}: ignoring trailing whitespace unnecessarily", file.display()); } @@ -424,5 +415,9 @@ pub fn check(path: &Path, bad: &mut bool) { if let Directive::Ignore(false) = skip_copyright { tidy_error!(bad, "{}: ignoring copyright unnecessarily", file.display()); } + // We deliberately do not warn about these being unnecessary, + // that would just lead to annoying churn. + let _unused = skip_line_length; + let _unused = skip_file_length; }) } diff --git a/triagebot.toml b/triagebot.toml index e165dd4f17c..ba9ed20cc64 100644 --- a/triagebot.toml +++ b/triagebot.toml @@ -324,4 +324,4 @@ cc = ["@rust-lang/rustfmt"] [mentions."compiler/rustc_middle/src/mir/syntax.rs"] message = "This PR changes MIR" -cc = ["@oli-obk", "@RalfJung", "@JakobDegen", "@davidtwco"] +cc = ["@oli-obk", "@RalfJung", "@JakobDegen", "@davidtwco", "@celinval"] |
