From 848610fddc127b8fa44c5c40d336bc10ee34e563 Mon Sep 17 00:00:00 2001 From: Nicholas Nethercote Date: Fri, 22 Nov 2024 06:20:53 +1100 Subject: [PATCH 01/92] Add a comment to `MaybeInitializedPlaces::apply_terminator_effect`. I tried reordering this method to more closely match `MaybeUninitializedPlaces::apply_terminator_effect`, but doing so breaks tests. --- compiler/rustc_mir_dataflow/src/impls/initialized.rs | 2 ++ 1 file changed, 2 insertions(+) diff --git a/compiler/rustc_mir_dataflow/src/impls/initialized.rs b/compiler/rustc_mir_dataflow/src/impls/initialized.rs index fb02408e17df..9fdbbb1578e4 100644 --- a/compiler/rustc_mir_dataflow/src/impls/initialized.rs +++ b/compiler/rustc_mir_dataflow/src/impls/initialized.rs @@ -293,6 +293,8 @@ impl<'tcx> Analysis<'tcx> for MaybeInitializedPlaces<'_, 'tcx> { terminator: &'mir mir::Terminator<'tcx>, location: Location, ) -> TerminatorEdges<'mir, 'tcx> { + // Note: `edges` must be computed first because `drop_flag_effects_for_location` can change + // the result of `is_unwind_dead`. let mut edges = terminator.edges(); if self.skip_unreachable_unwind && let mir::TerminatorKind::Drop { target, unwind, place, replace: _ } = terminator.kind From 4d8316f4d40cc9fb431b9cab5825c32fac43a19a Mon Sep 17 00:00:00 2001 From: Nicholas Nethercote Date: Thu, 21 Nov 2024 10:20:30 +1100 Subject: [PATCH 02/92] Simplify dataflow `SwitchInt` handling. Current `SwitchInt` handling has complicated control flow. - The dataflow engine calls `Analysis::apply_switch_int_edge_effects`, passing in an "applier" that impls `SwitchIntEdgeEffects`. - `apply_switch_int_edge_effects` possibly calls `apply` on the applier, passing it a closure. - The `apply` method calls the closure on each `SwitchInt` edge. - The closure operates on the edge. I.e. control flow goes from the engine, to the analysis, to the applier (which came from the engine), to the closure (which came from the analysis). It took me a while to work this out. This commit changes to a simpler structure that maintains the important characteristics. - The dataflow engine calls `Analysis::get_switch_int_data`. - `get_switch_int_data` returns an `Option` value. - If that returned value was `Some`, the dataflow engine calls `Analysis::apply_switch_int_edge_effect` on each edge, passing the `Self::SwitchIntData` value. - `Analysis::apply_switch_int_edge_effect` operates on the edge. I.e. control flow goes from the engine, to the analysis, to the engine, to the analysis. Added: - The `Analysis::SwitchIntData` assoc type and the `Analysis::get_switch_int_data` method. Both only need to be defined by analyses that look at `SwitchInt` terminators. - The `MaybePlacesSwitchIntData` struct, which has three fields. Changes: - `Analysis::apply_switch_int_edge_effects` becomes `Analysis::apply_switch_int_edge_effect`, which is a little simpler because it's dealing with a single edge instead of all edges. Removed: - The `SwitchIntEdgeEffects` trait, and its two impls: `BackwardSwitchIntEdgeEffectsApplier` (which has six fields) and `ForwardSwitchIntEdgeEffectsApplier` structs (which has four fields). - The closure. The new structure is more concise and simpler. --- compiler/rustc_borrowck/src/dataflow.rs | 12 +- .../src/framework/direction.rs | 126 ++++------------ .../rustc_mir_dataflow/src/framework/mod.rs | 39 +++-- .../src/impls/initialized.rs | 137 ++++++++++-------- compiler/rustc_mir_dataflow/src/lib.rs | 4 +- 5 files changed, 137 insertions(+), 181 deletions(-) diff --git a/compiler/rustc_borrowck/src/dataflow.rs b/compiler/rustc_borrowck/src/dataflow.rs index dc4eab766c93..abe4d4f20ecc 100644 --- a/compiler/rustc_borrowck/src/dataflow.rs +++ b/compiler/rustc_borrowck/src/dataflow.rs @@ -12,7 +12,7 @@ use rustc_mir_dataflow::impls::{ EverInitializedPlaces, EverInitializedPlacesDomain, MaybeUninitializedPlaces, MaybeUninitializedPlacesDomain, }; -use rustc_mir_dataflow::{Analysis, GenKill, JoinSemiLattice, SwitchIntEdgeEffects}; +use rustc_mir_dataflow::{Analysis, GenKill, JoinSemiLattice}; use tracing::debug; use crate::{BorrowSet, PlaceConflictBias, PlaceExt, RegionInferenceContext, places_conflict}; @@ -101,16 +101,6 @@ impl<'a, 'tcx> Analysis<'tcx> for Borrowck<'a, 'tcx> { // This is only reachable from `iterate_to_fixpoint`, which this analysis doesn't use. unreachable!(); } - - fn apply_switch_int_edge_effects( - &mut self, - _block: BasicBlock, - _discr: &mir::Operand<'tcx>, - _apply_edge_effects: &mut impl SwitchIntEdgeEffects, - ) { - // This is only reachable from `iterate_to_fixpoint`, which this analysis doesn't use. - unreachable!(); - } } impl JoinSemiLattice for BorrowckDomain { diff --git a/compiler/rustc_mir_dataflow/src/framework/direction.rs b/compiler/rustc_mir_dataflow/src/framework/direction.rs index 9d943ebe327b..45b1023e7952 100644 --- a/compiler/rustc_mir_dataflow/src/framework/direction.rs +++ b/compiler/rustc_mir_dataflow/src/framework/direction.rs @@ -1,8 +1,6 @@ use std::ops::RangeInclusive; -use rustc_middle::mir::{ - self, BasicBlock, CallReturnPlaces, Location, SwitchTargets, TerminatorEdges, -}; +use rustc_middle::mir::{self, BasicBlock, CallReturnPlaces, Location, TerminatorEdges}; use super::visitor::ResultsVisitor; use super::{Analysis, Effect, EffectIndex, Results, SwitchIntTarget}; @@ -115,18 +113,18 @@ impl Direction for Backward { } mir::TerminatorKind::SwitchInt { targets: _, ref discr } => { - let mut applier = BackwardSwitchIntEdgeEffectsApplier { - body, - pred, - exit_state, - block, - propagate: &mut propagate, - effects_applied: false, - }; + if let Some(mut data) = analysis.get_switch_int_data(block, discr) { + let values = &body.basic_blocks.switch_sources()[&(block, pred)]; + let targets = + values.iter().map(|&value| SwitchIntTarget { value, target: block }); - analysis.apply_switch_int_edge_effects(pred, discr, &mut applier); - - if !applier.effects_applied { + let mut tmp = None; + for target in targets { + let tmp = opt_clone_from_or_clone(&mut tmp, exit_state); + analysis.apply_switch_int_edge_effect(&mut data, tmp, target); + propagate(pred, tmp); + } + } else { propagate(pred, exit_state) } } @@ -245,37 +243,6 @@ impl Direction for Backward { } } -struct BackwardSwitchIntEdgeEffectsApplier<'mir, 'tcx, D, F> { - body: &'mir mir::Body<'tcx>, - pred: BasicBlock, - exit_state: &'mir mut D, - block: BasicBlock, - propagate: &'mir mut F, - effects_applied: bool, -} - -impl super::SwitchIntEdgeEffects for BackwardSwitchIntEdgeEffectsApplier<'_, '_, D, F> -where - D: Clone, - F: FnMut(BasicBlock, &D), -{ - fn apply(&mut self, mut apply_edge_effect: impl FnMut(&mut D, SwitchIntTarget)) { - assert!(!self.effects_applied); - - let values = &self.body.basic_blocks.switch_sources()[&(self.block, self.pred)]; - let targets = values.iter().map(|&value| SwitchIntTarget { value, target: self.block }); - - let mut tmp = None; - for target in targets { - let tmp = opt_clone_from_or_clone(&mut tmp, self.exit_state); - apply_edge_effect(tmp, target); - (self.propagate)(self.pred, tmp); - } - - self.effects_applied = true; - } -} - /// Dataflow that runs from the entry of a block (the first statement), to its exit (terminator). pub struct Forward; @@ -324,23 +291,27 @@ impl Direction for Forward { } } TerminatorEdges::SwitchInt { targets, discr } => { - let mut applier = ForwardSwitchIntEdgeEffectsApplier { - exit_state, - targets, - propagate, - effects_applied: false, - }; + if let Some(mut data) = analysis.get_switch_int_data(block, discr) { + let mut tmp = None; + for (value, target) in targets.iter() { + let tmp = opt_clone_from_or_clone(&mut tmp, exit_state); + analysis.apply_switch_int_edge_effect(&mut data, tmp, SwitchIntTarget { + value: Some(value), + target, + }); + propagate(target, tmp); + } - analysis.apply_switch_int_edge_effects(block, discr, &mut applier); - - let ForwardSwitchIntEdgeEffectsApplier { - exit_state, - mut propagate, - effects_applied, - .. - } = applier; - - if !effects_applied { + // Once we get to the final, "otherwise" branch, there is no need to preserve + // `exit_state`, so pass it directly to `apply_switch_int_edge_effect` to save + // a clone of the dataflow state. + let otherwise = targets.otherwise(); + analysis.apply_switch_int_edge_effect(&mut data, exit_state, SwitchIntTarget { + value: None, + target: otherwise, + }); + propagate(otherwise, exit_state); + } else { for target in targets.all_targets() { propagate(*target, exit_state); } @@ -455,39 +426,6 @@ impl Direction for Forward { } } -struct ForwardSwitchIntEdgeEffectsApplier<'mir, D, F> { - exit_state: &'mir mut D, - targets: &'mir SwitchTargets, - propagate: F, - - effects_applied: bool, -} - -impl super::SwitchIntEdgeEffects for ForwardSwitchIntEdgeEffectsApplier<'_, D, F> -where - D: Clone, - F: FnMut(BasicBlock, &D), -{ - fn apply(&mut self, mut apply_edge_effect: impl FnMut(&mut D, SwitchIntTarget)) { - assert!(!self.effects_applied); - - let mut tmp = None; - for (value, target) in self.targets.iter() { - let tmp = opt_clone_from_or_clone(&mut tmp, self.exit_state); - apply_edge_effect(tmp, SwitchIntTarget { value: Some(value), target }); - (self.propagate)(target, tmp); - } - - // Once we get to the final, "otherwise" branch, there is no need to preserve `exit_state`, - // so pass it directly to `apply_edge_effect` to save a clone of the dataflow state. - let otherwise = self.targets.otherwise(); - apply_edge_effect(self.exit_state, SwitchIntTarget { value: None, target: otherwise }); - (self.propagate)(otherwise, self.exit_state); - - self.effects_applied = true; - } -} - /// An analogue of `Option::get_or_insert_with` that stores a clone of `val` into `opt`, but uses /// the more efficient `clone_from` if `opt` was `Some`. /// diff --git a/compiler/rustc_mir_dataflow/src/framework/mod.rs b/compiler/rustc_mir_dataflow/src/framework/mod.rs index 41df5fae0dea..3de2c6e3f47c 100644 --- a/compiler/rustc_mir_dataflow/src/framework/mod.rs +++ b/compiler/rustc_mir_dataflow/src/framework/mod.rs @@ -103,6 +103,9 @@ pub trait Analysis<'tcx> { /// The direction of this analysis. Either `Forward` or `Backward`. type Direction: Direction = Forward; + /// Auxiliary data used for analyzing `SwitchInt` terminators, if necessary. + type SwitchIntData = !; + /// A descriptive name for this analysis. Used only for debugging. /// /// This name should be brief and contain no spaces, periods or other characters that are not @@ -190,25 +193,36 @@ pub trait Analysis<'tcx> { ) { } - /// Updates the current dataflow state with the effect of taking a particular branch in a - /// `SwitchInt` terminator. + /// Used to update the current dataflow state with the effect of taking a particular branch in + /// a `SwitchInt` terminator. /// /// Unlike the other edge-specific effects, which are allowed to mutate `Self::Domain` - /// directly, overriders of this method must pass a callback to - /// `SwitchIntEdgeEffects::apply`. The callback will be run once for each outgoing edge and - /// will have access to the dataflow state that will be propagated along that edge. + /// directly, overriders of this method must return a `Self::SwitchIntData` value (wrapped in + /// `Some`). The `apply_switch_int_edge_effect` method will then be called once for each + /// outgoing edge and will have access to the dataflow state that will be propagated along that + /// edge, and also the `Self::SwitchIntData` value. /// /// This interface is somewhat more complex than the other visitor-like "effect" methods. /// However, it is both more ergonomic—callers don't need to recompute or cache information /// about a given `SwitchInt` terminator for each one of its edges—and more efficient—the /// engine doesn't need to clone the exit state for a block unless - /// `SwitchIntEdgeEffects::apply` is actually called. - fn apply_switch_int_edge_effects( + /// `get_switch_int_data` is actually called. + fn get_switch_int_data( &mut self, - _block: BasicBlock, + _block: mir::BasicBlock, _discr: &mir::Operand<'tcx>, - _apply_edge_effects: &mut impl SwitchIntEdgeEffects, + ) -> Option { + None + } + + /// See comments on `get_switch_int_data`. + fn apply_switch_int_edge_effect( + &mut self, + _data: &mut Self::SwitchIntData, + _state: &mut Self::Domain, + _edge: SwitchIntTarget, ) { + unreachable!(); } /* Extension methods */ @@ -421,12 +435,5 @@ pub struct SwitchIntTarget { pub target: BasicBlock, } -/// A type that records the edge-specific effects for a `SwitchInt` terminator. -pub trait SwitchIntEdgeEffects { - /// Calls `apply_edge_effect` for each outgoing edge from a `SwitchInt` terminator and - /// records the results. - fn apply(&mut self, apply_edge_effect: impl FnMut(&mut D, SwitchIntTarget)); -} - #[cfg(test)] mod tests; diff --git a/compiler/rustc_mir_dataflow/src/impls/initialized.rs b/compiler/rustc_mir_dataflow/src/impls/initialized.rs index 9fdbbb1578e4..d5982b9cba2e 100644 --- a/compiler/rustc_mir_dataflow/src/impls/initialized.rs +++ b/compiler/rustc_mir_dataflow/src/impls/initialized.rs @@ -1,20 +1,45 @@ use std::assert_matches::assert_matches; +use rustc_abi::VariantIdx; use rustc_index::Idx; use rustc_index::bit_set::{BitSet, MixedBitSet}; use rustc_middle::bug; use rustc_middle::mir::{self, Body, CallReturnPlaces, Location, TerminatorEdges}; +use rustc_middle::ty::util::Discr; use rustc_middle::ty::{self, TyCtxt}; use tracing::{debug, instrument}; use crate::elaborate_drops::DropFlagState; -use crate::framework::SwitchIntEdgeEffects; +use crate::framework::SwitchIntTarget; use crate::move_paths::{HasMoveData, InitIndex, InitKind, LookupResult, MoveData, MovePathIndex}; use crate::{ Analysis, GenKill, MaybeReachable, drop_flag_effects, drop_flag_effects_for_function_entry, drop_flag_effects_for_location, on_all_children_bits, on_lookup_result_bits, }; +// Used by both `MaybeInitializedPlaces` and `MaybeUninitializedPlaces`. +pub struct MaybePlacesSwitchIntData<'tcx> { + enum_place: mir::Place<'tcx>, + discriminants: Vec<(VariantIdx, Discr<'tcx>)>, + index: usize, +} + +impl<'tcx> MaybePlacesSwitchIntData<'tcx> { + // The discriminant order in the `SwitchInt` targets should match the order yielded by + // `AdtDef::discriminants`. We rely on this to match each discriminant in the targets to its + // corresponding variant in linear time. + fn next_discr(&mut self, value: u128) -> VariantIdx { + // An out-of-bounds abort will occur if the discriminant ordering isn't as described above. + loop { + let (variant, discr) = self.discriminants[self.index]; + self.index += 1; + if discr.val == value { + return variant; + } + } + } +} + /// `MaybeInitializedPlaces` tracks all places that might be /// initialized upon reaching a particular point in the control flow /// for a function. @@ -247,6 +272,8 @@ impl<'tcx> Analysis<'tcx> for MaybeInitializedPlaces<'_, 'tcx> { /// We use a mixed bitset to avoid paying too high a memory footprint. type Domain = MaybeReachable>; + type SwitchIntData = MaybePlacesSwitchIntData<'tcx>; + const NAME: &'static str = "maybe_init"; fn bottom_value(&self, _: &mir::Body<'tcx>) -> Self::Domain { @@ -328,46 +355,42 @@ impl<'tcx> Analysis<'tcx> for MaybeInitializedPlaces<'_, 'tcx> { }); } - fn apply_switch_int_edge_effects( + fn get_switch_int_data( &mut self, block: mir::BasicBlock, discr: &mir::Operand<'tcx>, - edge_effects: &mut impl SwitchIntEdgeEffects, - ) { + ) -> Option { if !self.tcx.sess.opts.unstable_opts.precise_enum_drop_elaboration { - return; + return None; } - let enum_ = discr.place().and_then(|discr| { - switch_on_enum_discriminant(self.tcx, self.body, &self.body[block], discr) - }); - - let Some((enum_place, enum_def)) = enum_ else { - return; - }; - - let mut discriminants = enum_def.discriminants(self.tcx); - edge_effects.apply(|state, edge| { - let Some(value) = edge.value else { - return; - }; - - // MIR building adds discriminants to the `values` array in the same order as they - // are yielded by `AdtDef::discriminants`. We rely on this to match each - // discriminant in `values` to its corresponding variant in linear time. - let (variant, _) = discriminants - .find(|&(_, discr)| discr.val == value) - .expect("Order of `AdtDef::discriminants` differed from `SwitchInt::values`"); + discr.place().and_then(|discr| { + switch_on_enum_discriminant(self.tcx, self.body, &self.body[block], discr).map( + |(enum_place, enum_def)| MaybePlacesSwitchIntData { + enum_place, + discriminants: enum_def.discriminants(self.tcx).collect(), + index: 0, + }, + ) + }) + } + fn apply_switch_int_edge_effect( + &mut self, + data: &mut Self::SwitchIntData, + state: &mut Self::Domain, + edge: SwitchIntTarget, + ) { + if let Some(value) = edge.value { // Kill all move paths that correspond to variants we know to be inactive along this // particular outgoing edge of a `SwitchInt`. drop_flag_effects::on_all_inactive_variants( - self.move_data(), - enum_place, - variant, + self.move_data, + data.enum_place, + data.next_discr(value), |mpi| state.kill(mpi), ); - }); + } } } @@ -378,6 +401,8 @@ pub type MaybeUninitializedPlacesDomain = MixedBitSet; impl<'tcx> Analysis<'tcx> for MaybeUninitializedPlaces<'_, 'tcx> { type Domain = MaybeUninitializedPlacesDomain; + type SwitchIntData = MaybePlacesSwitchIntData<'tcx>; + const NAME: &'static str = "maybe_uninit"; fn bottom_value(&self, _: &mir::Body<'tcx>) -> Self::Domain { @@ -447,50 +472,46 @@ impl<'tcx> Analysis<'tcx> for MaybeUninitializedPlaces<'_, 'tcx> { }); } - fn apply_switch_int_edge_effects( + fn get_switch_int_data( &mut self, block: mir::BasicBlock, discr: &mir::Operand<'tcx>, - edge_effects: &mut impl SwitchIntEdgeEffects, - ) { + ) -> Option { if !self.tcx.sess.opts.unstable_opts.precise_enum_drop_elaboration { - return; + return None; } if !self.mark_inactive_variants_as_uninit { - return; + return None; } - let enum_ = discr.place().and_then(|discr| { - switch_on_enum_discriminant(self.tcx, self.body, &self.body[block], discr) - }); - - let Some((enum_place, enum_def)) = enum_ else { - return; - }; - - let mut discriminants = enum_def.discriminants(self.tcx); - edge_effects.apply(|state, edge| { - let Some(value) = edge.value else { - return; - }; - - // MIR building adds discriminants to the `values` array in the same order as they - // are yielded by `AdtDef::discriminants`. We rely on this to match each - // discriminant in `values` to its corresponding variant in linear time. - let (variant, _) = discriminants - .find(|&(_, discr)| discr.val == value) - .expect("Order of `AdtDef::discriminants` differed from `SwitchInt::values`"); + discr.place().and_then(|discr| { + switch_on_enum_discriminant(self.tcx, self.body, &self.body[block], discr).map( + |(enum_place, enum_def)| MaybePlacesSwitchIntData { + enum_place, + discriminants: enum_def.discriminants(self.tcx).collect(), + index: 0, + }, + ) + }) + } + fn apply_switch_int_edge_effect( + &mut self, + data: &mut Self::SwitchIntData, + state: &mut Self::Domain, + edge: SwitchIntTarget, + ) { + if let Some(value) = edge.value { // Mark all move paths that correspond to variants other than this one as maybe // uninitialized (in reality, they are *definitely* uninitialized). drop_flag_effects::on_all_inactive_variants( - self.move_data(), - enum_place, - variant, + self.move_data, + data.enum_place, + data.next_discr(value), |mpi| state.gen_(mpi), ); - }); + } } } diff --git a/compiler/rustc_mir_dataflow/src/lib.rs b/compiler/rustc_mir_dataflow/src/lib.rs index 85255db5d9a6..0cc79b0c9390 100644 --- a/compiler/rustc_mir_dataflow/src/lib.rs +++ b/compiler/rustc_mir_dataflow/src/lib.rs @@ -5,6 +5,7 @@ #![feature(exact_size_is_empty)] #![feature(file_buffered)] #![feature(let_chains)] +#![feature(never_type)] #![feature(try_blocks)] #![warn(unreachable_pub)] // tidy-alphabetical-end @@ -19,8 +20,7 @@ pub use self::drop_flag_effects::{ }; pub use self::framework::{ Analysis, Backward, Direction, EntryStates, Forward, GenKill, JoinSemiLattice, MaybeReachable, - Results, ResultsCursor, ResultsVisitor, SwitchIntEdgeEffects, fmt, graphviz, lattice, - visit_results, + Results, ResultsCursor, ResultsVisitor, fmt, graphviz, lattice, visit_results, }; use self::move_paths::MoveData; From c8c50f4351e629da2dde6bb6b23f4a2f93bd84b8 Mon Sep 17 00:00:00 2001 From: Nicholas Nethercote Date: Fri, 22 Nov 2024 08:39:34 +1100 Subject: [PATCH 03/92] Factor out some shared code from `Maybe{In,Unin}itializedPlaces`. --- .../src/impls/initialized.rs | 113 ++++++++---------- 1 file changed, 53 insertions(+), 60 deletions(-) diff --git a/compiler/rustc_mir_dataflow/src/impls/initialized.rs b/compiler/rustc_mir_dataflow/src/impls/initialized.rs index d5982b9cba2e..769f9c7cfc3e 100644 --- a/compiler/rustc_mir_dataflow/src/impls/initialized.rs +++ b/compiler/rustc_mir_dataflow/src/impls/initialized.rs @@ -40,6 +40,57 @@ impl<'tcx> MaybePlacesSwitchIntData<'tcx> { } } +impl<'tcx> MaybePlacesSwitchIntData<'tcx> { + fn new( + tcx: TyCtxt<'tcx>, + body: &Body<'tcx>, + block: mir::BasicBlock, + discr: &mir::Operand<'tcx>, + ) -> Option { + let Some(discr) = discr.place() else { return None }; + + // Inspect a `SwitchInt`-terminated basic block to see if the condition of that `SwitchInt` + // is an enum discriminant. + // + // We expect such blocks to have a call to `discriminant` as their last statement like so: + // ```text + // ... + // _42 = discriminant(_1) + // SwitchInt(_42, ..) + // ``` + // If the basic block matches this pattern, this function gathers the place corresponding + // to the enum (`_1` in the example above) as well as the discriminants. + let block_data = &body[block]; + for statement in block_data.statements.iter().rev() { + match statement.kind { + mir::StatementKind::Assign(box (lhs, mir::Rvalue::Discriminant(enum_place))) + if lhs == discr => + { + match enum_place.ty(body, tcx).ty.kind() { + ty::Adt(enum_def, _) => { + return Some(MaybePlacesSwitchIntData { + enum_place, + discriminants: enum_def.discriminants(tcx).collect(), + index: 0, + }); + } + + // `Rvalue::Discriminant` is also used to get the active yield point for a + // coroutine, but we do not need edge-specific effects in that case. This + // may change in the future. + ty::Coroutine(..) => break, + + t => bug!("`discriminant` called on unexpected type {:?}", t), + } + } + mir::StatementKind::Coverage(_) => continue, + _ => break, + } + } + None + } +} + /// `MaybeInitializedPlaces` tracks all places that might be /// initialized upon reaching a particular point in the control flow /// for a function. @@ -364,15 +415,7 @@ impl<'tcx> Analysis<'tcx> for MaybeInitializedPlaces<'_, 'tcx> { return None; } - discr.place().and_then(|discr| { - switch_on_enum_discriminant(self.tcx, self.body, &self.body[block], discr).map( - |(enum_place, enum_def)| MaybePlacesSwitchIntData { - enum_place, - discriminants: enum_def.discriminants(self.tcx).collect(), - index: 0, - }, - ) - }) + MaybePlacesSwitchIntData::new(self.tcx, self.body, block, discr) } fn apply_switch_int_edge_effect( @@ -485,15 +528,7 @@ impl<'tcx> Analysis<'tcx> for MaybeUninitializedPlaces<'_, 'tcx> { return None; } - discr.place().and_then(|discr| { - switch_on_enum_discriminant(self.tcx, self.body, &self.body[block], discr).map( - |(enum_place, enum_def)| MaybePlacesSwitchIntData { - enum_place, - discriminants: enum_def.discriminants(self.tcx).collect(), - index: 0, - }, - ) - }) + MaybePlacesSwitchIntData::new(self.tcx, self.body, block, discr) } fn apply_switch_int_edge_effect( @@ -601,45 +636,3 @@ impl<'tcx> Analysis<'tcx> for EverInitializedPlaces<'_, 'tcx> { } } } - -/// Inspect a `SwitchInt`-terminated basic block to see if the condition of that `SwitchInt` is -/// an enum discriminant. -/// -/// We expect such blocks to have a call to `discriminant` as their last statement like so: -/// -/// ```text -/// ... -/// _42 = discriminant(_1) -/// SwitchInt(_42, ..) -/// ``` -/// -/// If the basic block matches this pattern, this function returns the place corresponding to the -/// enum (`_1` in the example above) as well as the `AdtDef` of that enum. -fn switch_on_enum_discriminant<'mir, 'tcx>( - tcx: TyCtxt<'tcx>, - body: &'mir mir::Body<'tcx>, - block: &'mir mir::BasicBlockData<'tcx>, - switch_on: mir::Place<'tcx>, -) -> Option<(mir::Place<'tcx>, ty::AdtDef<'tcx>)> { - for statement in block.statements.iter().rev() { - match &statement.kind { - mir::StatementKind::Assign(box (lhs, mir::Rvalue::Discriminant(discriminated))) - if *lhs == switch_on => - { - match discriminated.ty(body, tcx).ty.kind() { - ty::Adt(def, _) => return Some((*discriminated, *def)), - - // `Rvalue::Discriminant` is also used to get the active yield point for a - // coroutine, but we do not need edge-specific effects in that case. This may - // change in the future. - ty::Coroutine(..) => return None, - - t => bug!("`discriminant` called on unexpected type {:?}", t), - } - } - mir::StatementKind::Coverage(_) => continue, - _ => return None, - } - } - None -} From 83f3d204cf396502a15b3edf50b561b47c9f0884 Mon Sep 17 00:00:00 2001 From: Nicholas Nethercote Date: Fri, 6 Dec 2024 15:47:03 +1100 Subject: [PATCH 04/92] Remove `opt_clone_from_or_clone`. Switches to the idiom used elsewhere of calling `Analysis::bottom_value` to initialize a `state` value outside a loop, and then using `clone_from` to update it within the loop. This is simpler and has no impact on performance. --- .../src/framework/direction.rs | 43 ++++++------------- 1 file changed, 13 insertions(+), 30 deletions(-) diff --git a/compiler/rustc_mir_dataflow/src/framework/direction.rs b/compiler/rustc_mir_dataflow/src/framework/direction.rs index 45b1023e7952..f51d2a3da3a7 100644 --- a/compiler/rustc_mir_dataflow/src/framework/direction.rs +++ b/compiler/rustc_mir_dataflow/src/framework/direction.rs @@ -118,11 +118,11 @@ impl Direction for Backward { let targets = values.iter().map(|&value| SwitchIntTarget { value, target: block }); - let mut tmp = None; + let mut tmp = analysis.bottom_value(body); for target in targets { - let tmp = opt_clone_from_or_clone(&mut tmp, exit_state); - analysis.apply_switch_int_edge_effect(&mut data, tmp, target); - propagate(pred, tmp); + tmp.clone_from(&exit_state); + analysis.apply_switch_int_edge_effect(&mut data, &mut tmp, target); + propagate(pred, &tmp); } } else { propagate(pred, exit_state) @@ -251,7 +251,7 @@ impl Direction for Forward { fn apply_effects_in_block<'mir, 'tcx, A>( analysis: &mut A, - _body: &mir::Body<'tcx>, + body: &mir::Body<'tcx>, state: &mut A::Domain, block: BasicBlock, block_data: &'mir mir::BasicBlockData<'tcx>, @@ -292,14 +292,15 @@ impl Direction for Forward { } TerminatorEdges::SwitchInt { targets, discr } => { if let Some(mut data) = analysis.get_switch_int_data(block, discr) { - let mut tmp = None; + let mut tmp = analysis.bottom_value(body); for (value, target) in targets.iter() { - let tmp = opt_clone_from_or_clone(&mut tmp, exit_state); - analysis.apply_switch_int_edge_effect(&mut data, tmp, SwitchIntTarget { - value: Some(value), - target, - }); - propagate(target, tmp); + tmp.clone_from(&exit_state); + analysis.apply_switch_int_edge_effect( + &mut data, + &mut tmp, + SwitchIntTarget { value: Some(value), target }, + ); + propagate(target, &tmp); } // Once we get to the final, "otherwise" branch, there is no need to preserve @@ -425,21 +426,3 @@ impl Direction for Forward { vis.visit_block_end(state); } } - -/// An analogue of `Option::get_or_insert_with` that stores a clone of `val` into `opt`, but uses -/// the more efficient `clone_from` if `opt` was `Some`. -/// -/// Returns a mutable reference to the new clone that resides in `opt`. -// -// FIXME: Figure out how to express this using `Option::clone_from`, or maybe lift it into the -// standard library? -fn opt_clone_from_or_clone<'a, T: Clone>(opt: &'a mut Option, val: &T) -> &'a mut T { - if opt.is_some() { - let ret = opt.as_mut().unwrap(); - ret.clone_from(val); - ret - } else { - *opt = Some(val.clone()); - opt.as_mut().unwrap() - } -} From 5f40942f9c462576b4b7976e0a4c855ee350a9f9 Mon Sep 17 00:00:00 2001 From: Nicholas Nethercote Date: Fri, 6 Dec 2024 17:36:08 +1100 Subject: [PATCH 05/92] Remove a `FIXME` comment. It is possible to avoid the clone as suggested in the comment. It would require introducing an enum with two variants `CloneBeforeModifying(&Domain)` and `Modifiable(&mut Domain)`. But it's not worth the effort, because this code path just isn't very hot. E.g. when compiling a large benchmark like `cargo-0.60.0` it's only hit a few thousand times. --- compiler/rustc_mir_dataflow/src/framework/direction.rs | 2 -- 1 file changed, 2 deletions(-) diff --git a/compiler/rustc_mir_dataflow/src/framework/direction.rs b/compiler/rustc_mir_dataflow/src/framework/direction.rs index f51d2a3da3a7..6427fd0fd295 100644 --- a/compiler/rustc_mir_dataflow/src/framework/direction.rs +++ b/compiler/rustc_mir_dataflow/src/framework/direction.rs @@ -76,8 +76,6 @@ impl Direction for Backward { for pred in body.basic_blocks.predecessors()[block].iter().copied() { match body[pred].terminator().kind { // Apply terminator-specific edge effects. - // - // FIXME(ecstaticmorse): Avoid cloning the exit state unconditionally. mir::TerminatorKind::Call { destination, target: Some(dest), .. } if dest == block => { From 30f5a039f07f830427fec693cdaff8724042cb12 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E8=AE=B8=E6=9D=B0=E5=8F=8B=20Jieyou=20Xu=20=28Joe=29?= <39484203+jieyouxu@users.noreply.github.com> Date: Tue, 17 Dec 2024 19:09:00 +0800 Subject: [PATCH 06/92] Move `tests/ui/associated-path-shl.rs` to `tests/ui/parser/` --- tests/ui/{ => parser}/associated-path-shl.rs | 0 tests/ui/{ => parser}/associated-path-shl.stderr | 0 2 files changed, 0 insertions(+), 0 deletions(-) rename tests/ui/{ => parser}/associated-path-shl.rs (100%) rename tests/ui/{ => parser}/associated-path-shl.stderr (100%) diff --git a/tests/ui/associated-path-shl.rs b/tests/ui/parser/associated-path-shl.rs similarity index 100% rename from tests/ui/associated-path-shl.rs rename to tests/ui/parser/associated-path-shl.rs diff --git a/tests/ui/associated-path-shl.stderr b/tests/ui/parser/associated-path-shl.stderr similarity index 100% rename from tests/ui/associated-path-shl.stderr rename to tests/ui/parser/associated-path-shl.stderr From 4ca2d9f7f5f158187e8ffcdfe82a1b1c39fc8733 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E8=AE=B8=E6=9D=B0=E5=8F=8B=20Jieyou=20Xu=20=28Joe=29?= <39484203+jieyouxu@users.noreply.github.com> Date: Tue, 17 Dec 2024 19:10:56 +0800 Subject: [PATCH 07/92] Move `tests/ui/attempted-access-non-fatal.rs` to `tests/ui/typeck/` --- tests/ui/{ => typeck}/attempted-access-non-fatal.rs | 0 tests/ui/{ => typeck}/attempted-access-non-fatal.stderr | 0 2 files changed, 0 insertions(+), 0 deletions(-) rename tests/ui/{ => typeck}/attempted-access-non-fatal.rs (100%) rename tests/ui/{ => typeck}/attempted-access-non-fatal.stderr (100%) diff --git a/tests/ui/attempted-access-non-fatal.rs b/tests/ui/typeck/attempted-access-non-fatal.rs similarity index 100% rename from tests/ui/attempted-access-non-fatal.rs rename to tests/ui/typeck/attempted-access-non-fatal.rs diff --git a/tests/ui/attempted-access-non-fatal.stderr b/tests/ui/typeck/attempted-access-non-fatal.stderr similarity index 100% rename from tests/ui/attempted-access-non-fatal.stderr rename to tests/ui/typeck/attempted-access-non-fatal.stderr From 0fc6be7898578e7d0c915f14f9ddb3ac71673796 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E8=AE=B8=E6=9D=B0=E5=8F=8B=20Jieyou=20Xu=20=28Joe=29?= <39484203+jieyouxu@users.noreply.github.com> Date: Tue, 17 Dec 2024 19:18:30 +0800 Subject: [PATCH 08/92] Adjust `tests/ui/attr-bad-crate-attr.rs` - Move `tests/ui/attr-bad-crate-attr.rs` to `tests/ui/attributes/`. - Briefly document test intent add link to relevant Reference docs. --- tests/ui/attr-bad-crate-attr.rs | 4 ---- tests/ui/attributes/attr-bad-crate-attr.rs | 9 +++++++++ tests/ui/{ => attributes}/attr-bad-crate-attr.stderr | 2 +- 3 files changed, 10 insertions(+), 5 deletions(-) delete mode 100644 tests/ui/attr-bad-crate-attr.rs create mode 100644 tests/ui/attributes/attr-bad-crate-attr.rs rename tests/ui/{ => attributes}/attr-bad-crate-attr.stderr (79%) diff --git a/tests/ui/attr-bad-crate-attr.rs b/tests/ui/attr-bad-crate-attr.rs deleted file mode 100644 index b9100ecfb676..000000000000 --- a/tests/ui/attr-bad-crate-attr.rs +++ /dev/null @@ -1,4 +0,0 @@ -//@ error-pattern: expected item - -#![attr = "val"] -#[attr = "val"] // Unterminated diff --git a/tests/ui/attributes/attr-bad-crate-attr.rs b/tests/ui/attributes/attr-bad-crate-attr.rs new file mode 100644 index 000000000000..9de0abca9a75 --- /dev/null +++ b/tests/ui/attributes/attr-bad-crate-attr.rs @@ -0,0 +1,9 @@ +//! Check that we permit a crate-level inner attribute but reject a dangling outer attribute which +//! does not have a following thing that it can target. +//! +//! See . + +//@ error-pattern: expected item + +#![attr = "val"] +#[attr = "val"] // Unterminated diff --git a/tests/ui/attr-bad-crate-attr.stderr b/tests/ui/attributes/attr-bad-crate-attr.stderr similarity index 79% rename from tests/ui/attr-bad-crate-attr.stderr rename to tests/ui/attributes/attr-bad-crate-attr.stderr index 9df991f71b3f..69eabd32230f 100644 --- a/tests/ui/attr-bad-crate-attr.stderr +++ b/tests/ui/attributes/attr-bad-crate-attr.stderr @@ -1,5 +1,5 @@ error: expected item after attributes - --> $DIR/attr-bad-crate-attr.rs:4:1 + --> $DIR/attr-bad-crate-attr.rs:9:1 | LL | #[attr = "val"] // Unterminated | ^^^^^^^^^^^^^^^ From 88f8bf7e560f5ea9c2efe2f587b2586f95984c4c Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E8=AE=B8=E6=9D=B0=E5=8F=8B=20Jieyou=20Xu=20=28Joe=29?= <39484203+jieyouxu@users.noreply.github.com> Date: Tue, 17 Dec 2024 19:22:21 +0800 Subject: [PATCH 09/92] Adjust `tests/ui/attr-shebang.rs` - Move `tests/ui/attr-shebang.rs` to `tests/ui/attributes/`. - Downgrade test to `check-pass`, this would fail very early if the parser did not accept `#![..]` attributes. - Briefly document test intent. --- tests/ui/attr-shebang.rs | 5 ----- tests/ui/attributes/attr-shebang.rs | 7 +++++++ 2 files changed, 7 insertions(+), 5 deletions(-) delete mode 100644 tests/ui/attr-shebang.rs create mode 100644 tests/ui/attributes/attr-shebang.rs diff --git a/tests/ui/attr-shebang.rs b/tests/ui/attr-shebang.rs deleted file mode 100644 index 67c371aeaace..000000000000 --- a/tests/ui/attr-shebang.rs +++ /dev/null @@ -1,5 +0,0 @@ -//@ run-pass - -#![allow(stable_features)] -#![feature(rust1)] -pub fn main() { } diff --git a/tests/ui/attributes/attr-shebang.rs b/tests/ui/attributes/attr-shebang.rs new file mode 100644 index 000000000000..af446dc56e39 --- /dev/null +++ b/tests/ui/attributes/attr-shebang.rs @@ -0,0 +1,7 @@ +//! Check that we accept crate-level inner attributes with the `#![..]` shebang syntax. + +//@ check-pass + +#![allow(stable_features)] +#![feature(rust1)] +pub fn main() { } From 7424b898e94b019b49e0854ec061abfdc071e61e Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E8=AE=B8=E6=9D=B0=E5=8F=8B=20Jieyou=20Xu=20=28Joe=29?= <39484203+jieyouxu@users.noreply.github.com> Date: Tue, 17 Dec 2024 19:29:14 +0800 Subject: [PATCH 10/92] Adjust `tests/ui/attr-usage-inline.rs` - Move `tests/ui/attr-usage-inline.rs` to `tests/ui/attributes/inline/`. - Briefly document test intent. - Drop unnecessary `#[allow(dead_code)]` as this is allowed-by-default for ui test suite. --- tests/ui/{ => attributes/inline}/attr-usage-inline.rs | 3 ++- tests/ui/{ => attributes/inline}/attr-usage-inline.stderr | 4 ++-- 2 files changed, 4 insertions(+), 3 deletions(-) rename tests/ui/{ => attributes/inline}/attr-usage-inline.rs (66%) rename tests/ui/{ => attributes/inline}/attr-usage-inline.stderr (84%) diff --git a/tests/ui/attr-usage-inline.rs b/tests/ui/attributes/inline/attr-usage-inline.rs similarity index 66% rename from tests/ui/attr-usage-inline.rs rename to tests/ui/attributes/inline/attr-usage-inline.rs index 674c12454cda..d8ca0fce1631 100644 --- a/tests/ui/attr-usage-inline.rs +++ b/tests/ui/attributes/inline/attr-usage-inline.rs @@ -1,4 +1,5 @@ -#![allow(dead_code)] +//! Check that `#[inline]` attribute can only be applied to fn-like targets (e.g. function or +//! closure), and when misapplied to other targets an error is emitted. #[inline] fn f() {} diff --git a/tests/ui/attr-usage-inline.stderr b/tests/ui/attributes/inline/attr-usage-inline.stderr similarity index 84% rename from tests/ui/attr-usage-inline.stderr rename to tests/ui/attributes/inline/attr-usage-inline.stderr index 22a0bf47e202..2123438032cb 100644 --- a/tests/ui/attr-usage-inline.stderr +++ b/tests/ui/attributes/inline/attr-usage-inline.stderr @@ -1,5 +1,5 @@ error[E0518]: attribute should be applied to function or closure - --> $DIR/attr-usage-inline.rs:6:1 + --> $DIR/attr-usage-inline.rs:7:1 | LL | #[inline] | ^^^^^^^^^ @@ -7,7 +7,7 @@ LL | struct S; | --------- not a function or closure error[E0518]: attribute should be applied to function or closure - --> $DIR/attr-usage-inline.rs:20:1 + --> $DIR/attr-usage-inline.rs:21:1 | LL | #[inline] | ^^^^^^^^^ not a function or closure From 836a0e00e5d29b845748cf42713445076418473b Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E8=AE=B8=E6=9D=B0=E5=8F=8B=20Jieyou=20Xu=20=28Joe=29?= <39484203+jieyouxu@users.noreply.github.com> Date: Tue, 17 Dec 2024 19:40:31 +0800 Subject: [PATCH 11/92] Adjust `tests/ui/attrs-resolution-errors.rs` - Move `tests/ui/attrs-resolution-errors.rs` to `tests/ui/resolve/`. - Document test intent. - Rename test to `attr-macros-positional-rejection.rs` to better reflect test intent. --- .../attr-macros-positional-rejection.rs} | 11 ++++++++++- .../attr-macros-positional-rejection.stderr} | 10 +++++----- 2 files changed, 15 insertions(+), 6 deletions(-) rename tests/ui/{attrs-resolution-errors.rs => resolve/attr-macros-positional-rejection.rs} (73%) rename tests/ui/{attrs-resolution-errors.stderr => resolve/attr-macros-positional-rejection.stderr} (73%) diff --git a/tests/ui/attrs-resolution-errors.rs b/tests/ui/resolve/attr-macros-positional-rejection.rs similarity index 73% rename from tests/ui/attrs-resolution-errors.rs rename to tests/ui/resolve/attr-macros-positional-rejection.rs index 8770fb1ded8e..11382ff13998 100644 --- a/tests/ui/attrs-resolution-errors.rs +++ b/tests/ui/resolve/attr-macros-positional-rejection.rs @@ -1,3 +1,12 @@ +//! Check that certain positions (listed below) only permit *non-macro* attributes and reject +//! attribute macros: +//! +//! - Enum variants +//! - Struct fields +//! - Field in a struct pattern +//! - Match arm +//! - Field in struct initialization expression + enum FooEnum { #[test] //~^ ERROR expected non-macro attribute, found attribute macro @@ -32,7 +41,7 @@ fn main() { _ => {} } - let _another_foo_strunct = FooStruct { + let _another_foo_struct = FooStruct { #[test] //~^ ERROR expected non-macro attribute, found attribute macro bar: 1, diff --git a/tests/ui/attrs-resolution-errors.stderr b/tests/ui/resolve/attr-macros-positional-rejection.stderr similarity index 73% rename from tests/ui/attrs-resolution-errors.stderr rename to tests/ui/resolve/attr-macros-positional-rejection.stderr index 883f96e5c193..faea511f3150 100644 --- a/tests/ui/attrs-resolution-errors.stderr +++ b/tests/ui/resolve/attr-macros-positional-rejection.stderr @@ -1,29 +1,29 @@ error: expected non-macro attribute, found attribute macro `test` - --> $DIR/attrs-resolution-errors.rs:2:7 + --> $DIR/attr-macros-positional-rejection.rs:11:7 | LL | #[test] | ^^^^ not a non-macro attribute error: expected non-macro attribute, found attribute macro `test` - --> $DIR/attrs-resolution-errors.rs:8:7 + --> $DIR/attr-macros-positional-rejection.rs:17:7 | LL | #[test] | ^^^^ not a non-macro attribute error: expected non-macro attribute, found attribute macro `test` - --> $DIR/attrs-resolution-errors.rs:23:15 + --> $DIR/attr-macros-positional-rejection.rs:32:15 | LL | #[test] bar | ^^^^ not a non-macro attribute error: expected non-macro attribute, found attribute macro `test` - --> $DIR/attrs-resolution-errors.rs:30:11 + --> $DIR/attr-macros-positional-rejection.rs:39:11 | LL | #[test] | ^^^^ not a non-macro attribute error: expected non-macro attribute, found attribute macro `test` - --> $DIR/attrs-resolution-errors.rs:36:11 + --> $DIR/attr-macros-positional-rejection.rs:45:11 | LL | #[test] | ^^^^ not a non-macro attribute From 47ad3b2be42790a54840f5aec9a3526244bedc55 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E8=AE=B8=E6=9D=B0=E5=8F=8B=20Jieyou=20Xu=20=28Joe=29?= <39484203+jieyouxu@users.noreply.github.com> Date: Tue, 17 Dec 2024 19:43:05 +0800 Subject: [PATCH 12/92] Adjust `tests/ui/attrs-resolution.rs` - Move `tests/ui/attrs-resolution.rs` to `tests/ui/resolve/`. - Document test intent. - Rename test to `non-macro-attrs-accepted.rs` to better reflect test intent. --- .../non-macro-attrs-accepted.rs} | 10 +++++++++- 1 file changed, 9 insertions(+), 1 deletion(-) rename tests/ui/{attrs-resolution.rs => resolve/non-macro-attrs-accepted.rs} (66%) diff --git a/tests/ui/attrs-resolution.rs b/tests/ui/resolve/non-macro-attrs-accepted.rs similarity index 66% rename from tests/ui/attrs-resolution.rs rename to tests/ui/resolve/non-macro-attrs-accepted.rs index 38dd3812d689..76a04b2e8374 100644 --- a/tests/ui/attrs-resolution.rs +++ b/tests/ui/resolve/non-macro-attrs-accepted.rs @@ -1,3 +1,11 @@ +//! Check that certain positions (listed below) permit *non-macro* attributes. +//! +//! - Enum variants +//! - Struct fields +//! - Field in a struct pattern +//! - Match arm +//! - Field in struct initialization expression + //@ check-pass enum FooEnum { @@ -30,7 +38,7 @@ fn main() { _ => {} } - let _another_foo_strunct = FooStruct { + let _another_foo_struct = FooStruct { #[rustfmt::skip] bar: 1, }; From 1d4530b8714a8cb238ef0aa92b633afbadd59657 Mon Sep 17 00:00:00 2001 From: Nikita Popov Date: Tue, 17 Dec 2024 16:31:22 +0100 Subject: [PATCH 13/92] Update to LLVM 19.1.6 --- src/llvm-project | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/llvm-project b/src/llvm-project index 1268e87bdbae..59512b002738 160000 --- a/src/llvm-project +++ b/src/llvm-project @@ -1 +1 @@ -Subproject commit 1268e87bdbaed0693a9d782ccd5a21e2cab2de33 +Subproject commit 59512b00273829823da74050d373b8d46dbca558 From d03380957bf92412d48daac92966ff5129358d59 Mon Sep 17 00:00:00 2001 From: Guillaume Gomez Date: Tue, 17 Dec 2024 17:25:19 +0100 Subject: [PATCH 14/92] Fix intra doc links not generated inside footnote definitions --- src/librustdoc/html/markdown.rs | 66 +++++++++++++++++++++++++-------- 1 file changed, 50 insertions(+), 16 deletions(-) diff --git a/src/librustdoc/html/markdown.rs b/src/librustdoc/html/markdown.rs index 90c49270566d..aa8fdaaee4cb 100644 --- a/src/librustdoc/html/markdown.rs +++ b/src/librustdoc/html/markdown.rs @@ -344,35 +344,48 @@ impl<'a, I: Iterator>> Iterator for CodeBlocks<'_, 'a, I> { } /// Make headings links with anchor IDs and build up TOC. -struct LinkReplacer<'a, I: Iterator>> { - inner: I, +struct LinkReplacerInner<'a> { links: &'a [RenderedLink], shortcut_link: Option<&'a RenderedLink>, } +struct LinkReplacer<'a, I: Iterator>> { + iter: I, + inner: LinkReplacerInner<'a>, +} + impl<'a, I: Iterator>> LinkReplacer<'a, I> { fn new(iter: I, links: &'a [RenderedLink]) -> Self { - LinkReplacer { inner: iter, links, shortcut_link: None } + LinkReplacer { iter, inner: { LinkReplacerInner { links, shortcut_link: None } } } } } -impl<'a, I: Iterator>> Iterator for LinkReplacer<'a, I> { - type Item = Event<'a>; +// FIXME: Once we have specialized trait impl (for `Iterator` impl on `LinkReplacer`), +// we can remove this type and move back `LinkReplacerInner` fields into `LinkReplacer`. +struct SpannedLinkReplacer<'a, I: Iterator>> { + iter: I, + inner: LinkReplacerInner<'a>, +} - fn next(&mut self) -> Option { - let mut event = self.inner.next(); +impl<'a, I: Iterator>> SpannedLinkReplacer<'a, I> { + fn new(iter: I, links: &'a [RenderedLink]) -> Self { + SpannedLinkReplacer { iter, inner: { LinkReplacerInner { links, shortcut_link: None } } } + } +} +impl<'a> LinkReplacerInner<'a> { + fn handle_event(&mut self, event: &mut Event<'a>) { // Replace intra-doc links and remove disambiguators from shortcut links (`[fn@f]`). - match &mut event { + match event { // This is a shortcut link that was resolved by the broken_link_callback: `[fn@f]` // Remove any disambiguator. - Some(Event::Start(Tag::Link { + Event::Start(Tag::Link { // [fn@f] or [fn@f][] link_type: LinkType::ShortcutUnknown | LinkType::CollapsedUnknown, dest_url, title, .. - })) => { + }) => { debug!("saw start of shortcut link to {dest_url} with title {title}"); // If this is a shortcut link, it was resolved by the broken_link_callback. // So the URL will already be updated properly. @@ -389,13 +402,13 @@ impl<'a, I: Iterator>> Iterator for LinkReplacer<'a, I> { } } // Now that we're done with the shortcut link, don't replace any more text. - Some(Event::End(TagEnd::Link)) if self.shortcut_link.is_some() => { + Event::End(TagEnd::Link) if self.shortcut_link.is_some() => { debug!("saw end of shortcut link"); self.shortcut_link = None; } // Handle backticks in inline code blocks, but only if we're in the middle of a shortcut link. // [`fn@f`] - Some(Event::Code(text)) => { + Event::Code(text) => { trace!("saw code {text}"); if let Some(link) = self.shortcut_link { // NOTE: this only replaces if the code block is the *entire* text. @@ -418,7 +431,7 @@ impl<'a, I: Iterator>> Iterator for LinkReplacer<'a, I> { } // Replace plain text in links, but only in the middle of a shortcut link. // [fn@f] - Some(Event::Text(text)) => { + Event::Text(text) => { trace!("saw text {text}"); if let Some(link) = self.shortcut_link { // NOTE: same limitations as `Event::Code` @@ -434,7 +447,7 @@ impl<'a, I: Iterator>> Iterator for LinkReplacer<'a, I> { } // If this is a link, but not a shortcut link, // replace the URL, since the broken_link_callback was not called. - Some(Event::Start(Tag::Link { dest_url, title, .. })) => { + Event::Start(Tag::Link { dest_url, title, .. }) => { if let Some(link) = self.links.iter().find(|&link| *link.original_text == **dest_url) { @@ -447,12 +460,33 @@ impl<'a, I: Iterator>> Iterator for LinkReplacer<'a, I> { // Anything else couldn't have been a valid Rust path, so no need to replace the text. _ => {} } + } +} +impl<'a, I: Iterator>> Iterator for LinkReplacer<'a, I> { + type Item = Event<'a>; + + fn next(&mut self) -> Option { + let mut event = self.iter.next(); + if let Some(ref mut event) = event { + self.inner.handle_event(event); + } // Yield the modified event event } } +impl<'a, I: Iterator>> Iterator for SpannedLinkReplacer<'a, I> { + type Item = SpannedEvent<'a>; + + fn next(&mut self) -> Option { + let Some((mut event, range)) = self.iter.next() else { return None }; + self.inner.handle_event(&mut event); + // Yield the modified event + Some((event, range)) + } +} + /// Wrap HTML tables into `
` to prevent having the doc blocks width being too big. struct TableWrapper<'a, I: Iterator>> { inner: I, @@ -1339,9 +1373,9 @@ impl<'a> Markdown<'a> { ids.handle_footnotes(|ids, existing_footnotes| { let p = HeadingLinks::new(p, None, ids, heading_offset); + let p = SpannedLinkReplacer::new(p, links); let p = footnotes::Footnotes::new(p, existing_footnotes); - let p = LinkReplacer::new(p.map(|(ev, _)| ev), links); - let p = TableWrapper::new(p); + let p = TableWrapper::new(p.map(|(ev, _)| ev)); CodeBlocks::new(p, codes, edition, playground) }) } From 7eb0d8442444897395d5ac167860f710a2842205 Mon Sep 17 00:00:00 2001 From: Integral Date: Wed, 18 Dec 2024 00:28:34 +0800 Subject: [PATCH 15/92] refactor: replace &PathBuf with &Path to enhance generality --- compiler/rustc_driver_impl/src/lib.rs | 4 ++-- compiler/rustc_session/src/config.rs | 2 +- src/bootstrap/src/core/build_steps/setup.rs | 2 +- src/bootstrap/src/core/config/config.rs | 10 ++++------ src/tools/compiletest/src/debuggers.rs | 4 ++-- src/tools/compiletest/src/lib.rs | 7 +++---- src/tools/compiletest/src/runtest.rs | 2 +- src/tools/rustc-perf-wrapper/src/main.rs | 2 +- 8 files changed, 15 insertions(+), 18 deletions(-) diff --git a/compiler/rustc_driver_impl/src/lib.rs b/compiler/rustc_driver_impl/src/lib.rs index 6f7b943c6497..4049905dbe0f 100644 --- a/compiler/rustc_driver_impl/src/lib.rs +++ b/compiler/rustc_driver_impl/src/lib.rs @@ -26,7 +26,7 @@ use std::fmt::Write as _; use std::fs::{self, File}; use std::io::{self, IsTerminal, Read, Write}; use std::panic::{self, PanicHookInfo, catch_unwind}; -use std::path::PathBuf; +use std::path::{Path, PathBuf}; use std::process::{self, Command, Stdio}; use std::sync::atomic::{AtomicBool, Ordering}; use std::sync::{Arc, OnceLock}; @@ -460,7 +460,7 @@ fn run_compiler( }) } -fn dump_feature_usage_metrics(tcxt: TyCtxt<'_>, metrics_dir: &PathBuf) { +fn dump_feature_usage_metrics(tcxt: TyCtxt<'_>, metrics_dir: &Path) { let output_filenames = tcxt.output_filenames(()); let mut metrics_file_name = std::ffi::OsString::from("unstable_feature_usage_metrics-"); let mut metrics_path = output_filenames.with_directory_and_extension(metrics_dir, "json"); diff --git a/compiler/rustc_session/src/config.rs b/compiler/rustc_session/src/config.rs index 936c2ca87d69..4784a4d1953d 100644 --- a/compiler/rustc_session/src/config.rs +++ b/compiler/rustc_session/src/config.rs @@ -1076,7 +1076,7 @@ impl OutputFilenames { self.with_directory_and_extension(&self.out_directory, extension) } - pub fn with_directory_and_extension(&self, directory: &PathBuf, extension: &str) -> PathBuf { + pub fn with_directory_and_extension(&self, directory: &Path, extension: &str) -> PathBuf { let mut path = directory.join(&self.filestem); path.set_extension(extension); path diff --git a/src/bootstrap/src/core/build_steps/setup.rs b/src/bootstrap/src/core/build_steps/setup.rs index 7ed01f25c94b..fbd0dc3ec302 100644 --- a/src/bootstrap/src/core/build_steps/setup.rs +++ b/src/bootstrap/src/core/build_steps/setup.rs @@ -209,7 +209,7 @@ pub fn setup(config: &Config, profile: Profile) { setup_config_toml(path, profile, config); } -fn setup_config_toml(path: &PathBuf, profile: Profile, config: &Config) { +fn setup_config_toml(path: &Path, profile: Profile, config: &Config) { if profile == Profile::None { return; } diff --git a/src/bootstrap/src/core/config/config.rs b/src/bootstrap/src/core/config/config.rs index 22d361ff091c..435216ef534c 100644 --- a/src/bootstrap/src/core/config/config.rs +++ b/src/bootstrap/src/core/config/config.rs @@ -1942,7 +1942,7 @@ impl Config { ); let channel = config - .read_file_by_commit(&PathBuf::from("src/ci/channel"), commit) + .read_file_by_commit(Path::new("src/ci/channel"), commit) .trim() .to_owned(); @@ -2383,12 +2383,10 @@ impl Config { /// Return the version it would have used for the given commit. pub(crate) fn artifact_version_part(&self, commit: &str) -> String { let (channel, version) = if self.rust_info.is_managed_git_subrepository() { - let channel = self - .read_file_by_commit(&PathBuf::from("src/ci/channel"), commit) - .trim() - .to_owned(); + let channel = + self.read_file_by_commit(Path::new("src/ci/channel"), commit).trim().to_owned(); let version = - self.read_file_by_commit(&PathBuf::from("src/version"), commit).trim().to_owned(); + self.read_file_by_commit(Path::new("src/version"), commit).trim().to_owned(); (channel, version) } else { let channel = fs::read_to_string(self.src.join("src/ci/channel")); diff --git a/src/tools/compiletest/src/debuggers.rs b/src/tools/compiletest/src/debuggers.rs index b605bc813f19..20e3c8dfb9ee 100644 --- a/src/tools/compiletest/src/debuggers.rs +++ b/src/tools/compiletest/src/debuggers.rs @@ -1,6 +1,6 @@ use std::env; use std::ffi::OsString; -use std::path::PathBuf; +use std::path::{Path, PathBuf}; use std::process::Command; use std::sync::Arc; @@ -141,7 +141,7 @@ pub(crate) fn extract_cdb_version(full_version_line: &str) -> Option<[u16; 4]> { pub(crate) fn analyze_gdb( gdb: Option, target: &str, - android_cross_path: &PathBuf, + android_cross_path: &Path, ) -> (Option, Option) { #[cfg(not(windows))] const GDB_FALLBACK: &str = "gdb"; diff --git a/src/tools/compiletest/src/lib.rs b/src/tools/compiletest/src/lib.rs index a5a166af33b6..d3b4631a2128 100644 --- a/src/tools/compiletest/src/lib.rs +++ b/src/tools/compiletest/src/lib.rs @@ -598,10 +598,9 @@ pub fn collect_and_make_tests(config: Arc) -> Vec { let mut collector = TestCollector { tests: vec![], found_path_stems: HashSet::new(), poisoned: false }; - collect_tests_from_dir(&cx, &mut collector, &cx.config.src_base, &PathBuf::new()) - .unwrap_or_else(|reason| { - panic!("Could not read tests from {}: {reason}", cx.config.src_base.display()) - }); + collect_tests_from_dir(&cx, &mut collector, &cx.config.src_base, Path::new("")).unwrap_or_else( + |reason| panic!("Could not read tests from {}: {reason}", cx.config.src_base.display()), + ); let TestCollector { tests, found_path_stems, poisoned } = collector; diff --git a/src/tools/compiletest/src/runtest.rs b/src/tools/compiletest/src/runtest.rs index 8af4325e7b10..cb31b03dd2af 100644 --- a/src/tools/compiletest/src/runtest.rs +++ b/src/tools/compiletest/src/runtest.rs @@ -2560,7 +2560,7 @@ impl<'test> TestCx<'test> { }) } - fn delete_file(&self, file: &PathBuf) { + fn delete_file(&self, file: &Path) { if !file.exists() { // Deleting a nonexistent file would error. return; diff --git a/src/tools/rustc-perf-wrapper/src/main.rs b/src/tools/rustc-perf-wrapper/src/main.rs index 951d36b788b5..0b4c894e29d9 100644 --- a/src/tools/rustc-perf-wrapper/src/main.rs +++ b/src/tools/rustc-perf-wrapper/src/main.rs @@ -163,7 +163,7 @@ fn apply_shared_opts(cmd: &mut Command, opts: &SharedOpts) { } } -fn execute_benchmark(cmd: &mut Command, compiler: &PathBuf) { +fn execute_benchmark(cmd: &mut Command, compiler: &Path) { cmd.arg(compiler); println!("Running `rustc-perf` using `{}`", compiler.display()); From a01de760bbcbbdf6935f0cd82107d48529c48138 Mon Sep 17 00:00:00 2001 From: Guillaume Gomez Date: Tue, 17 Dec 2024 17:32:11 +0100 Subject: [PATCH 16/92] Add regression test for #132208 --- .../intra-doc/link-in-footnotes-132208.rs | 24 +++++++++++++++++++ 1 file changed, 24 insertions(+) create mode 100644 tests/rustdoc/intra-doc/link-in-footnotes-132208.rs diff --git a/tests/rustdoc/intra-doc/link-in-footnotes-132208.rs b/tests/rustdoc/intra-doc/link-in-footnotes-132208.rs new file mode 100644 index 000000000000..c9b97eafd2f8 --- /dev/null +++ b/tests/rustdoc/intra-doc/link-in-footnotes-132208.rs @@ -0,0 +1,24 @@ +// Rustdoc has multiple passes and if the footnote pass is run before the link replacer +// one, intra doc links are not generated inside footnote definitions. This test +// therefore ensures that intra-doc link are correctly generated inside footnote +// definitions. +// +// Regression test for . + +#![crate_name = "foo"] + +//@ has 'foo/index.html' +//@ has - '//*[@class="docblock"]//a[@href="struct.Bar.html"]' 'a' +//@ has - '//*[@class="docblock"]//*[@class="footnotes"]//a[@href="struct.Foo.html"]' 'b' + +//! [a]: crate::Bar +//! [b]: crate::Foo +//! +//! link in body: [a] +//! +//! see footnote[^1] +//! +//! [^1]: link in footnote: [b] + +pub struct Bar; +pub struct Foo; From ca2068ec43f1822db677beda397c8d9e59df92bd Mon Sep 17 00:00:00 2001 From: MarcoIeni <11428655+MarcoIeni@users.noreply.github.com> Date: Tue, 17 Dec 2024 18:00:02 +0100 Subject: [PATCH 17/92] ci: use ubuntu-22 for large runners --- src/ci/github-actions/jobs.yml | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/src/ci/github-actions/jobs.yml b/src/ci/github-actions/jobs.yml index fe0fdde39d0f..60d8071b5802 100644 --- a/src/ci/github-actions/jobs.yml +++ b/src/ci/github-actions/jobs.yml @@ -12,15 +12,15 @@ runners: # Large runner used mainly for its bigger disk capacity - &job-linux-4c-largedisk - os: ubuntu-20.04-4core-16gb + os: ubuntu-22.04-4core-16gb <<: *base-job - &job-linux-8c - os: ubuntu-20.04-8core-32gb + os: ubuntu-22.04-8core-32gb <<: *base-job - &job-linux-16c - os: ubuntu-20.04-16core-64gb + os: ubuntu-22.04-16core-64gb <<: *base-job - &job-macos-xl From 5980dfe063cea6135400046ce252a276ba8362bc Mon Sep 17 00:00:00 2001 From: MarcoIeni <11428655+MarcoIeni@users.noreply.github.com> Date: Tue, 17 Dec 2024 18:15:33 +0100 Subject: [PATCH 18/92] ci: remove duplicate task definition --- .../host-x86_64/i686-gnu-nopt/Dockerfile | 4 ++- src/ci/docker/host-x86_64/i686-gnu/Dockerfile | 4 ++- .../host-x86_64/x86_64-gnu-llvm-18/Dockerfile | 15 +++++---- .../host-x86_64/x86_64-gnu-llvm-19/Dockerfile | 15 +++++---- src/ci/docker/scripts/stage_2_test_set1.sh | 9 +++++ ...6_64-gnu-llvm1.sh => stage_2_test_set2.sh} | 2 +- src/ci/docker/scripts/x86_64-gnu-llvm.sh | 2 -- src/ci/docker/scripts/x86_64-gnu-llvm2.sh | 6 +--- src/ci/github-actions/jobs.yml | 33 ++++--------------- 9 files changed, 41 insertions(+), 49 deletions(-) create mode 100755 src/ci/docker/scripts/stage_2_test_set1.sh rename src/ci/docker/scripts/{x86_64-gnu-llvm1.sh => stage_2_test_set2.sh} (67%) diff --git a/src/ci/docker/host-x86_64/i686-gnu-nopt/Dockerfile b/src/ci/docker/host-x86_64/i686-gnu-nopt/Dockerfile index e27367206073..241199d3bafb 100644 --- a/src/ci/docker/host-x86_64/i686-gnu-nopt/Dockerfile +++ b/src/ci/docker/host-x86_64/i686-gnu-nopt/Dockerfile @@ -28,4 +28,6 @@ RUN echo "optimize = false" >> /config/nopt-std-config.toml ENV RUST_CONFIGURE_ARGS --build=i686-unknown-linux-gnu --disable-optimize-tests ARG SCRIPT_ARG -ENV SCRIPT=${SCRIPT_ARG} +COPY scripts/stage_2_test_set1.sh /scripts/ +COPY scripts/stage_2_test_set2.sh /scripts/ +ENV SCRIPT ${SCRIPT_ARG} diff --git a/src/ci/docker/host-x86_64/i686-gnu/Dockerfile b/src/ci/docker/host-x86_64/i686-gnu/Dockerfile index dec25461bb4e..a715f7182d2a 100644 --- a/src/ci/docker/host-x86_64/i686-gnu/Dockerfile +++ b/src/ci/docker/host-x86_64/i686-gnu/Dockerfile @@ -25,4 +25,6 @@ RUN sh /scripts/sccache.sh ENV RUST_CONFIGURE_ARGS --build=i686-unknown-linux-gnu ARG SCRIPT_ARG -ENV SCRIPT=${SCRIPT_ARG} +COPY scripts/stage_2_test_set1.sh /scripts/ +COPY scripts/stage_2_test_set2.sh /scripts/ +ENV SCRIPT /scripts/${SCRIPT_ARG} diff --git a/src/ci/docker/host-x86_64/x86_64-gnu-llvm-18/Dockerfile b/src/ci/docker/host-x86_64/x86_64-gnu-llvm-18/Dockerfile index 42df58517caf..e157debfd09a 100644 --- a/src/ci/docker/host-x86_64/x86_64-gnu-llvm-18/Dockerfile +++ b/src/ci/docker/host-x86_64/x86_64-gnu-llvm-18/Dockerfile @@ -60,9 +60,12 @@ COPY host-x86_64/dist-x86_64-linux/build-gccjit.sh /scripts/ RUN /scripts/build-gccjit.sh /scripts ARG SCRIPT_ARG -COPY scripts/add_dummy_commit.sh /tmp/add_dummy_commit.sh -COPY scripts/x86_64-gnu-llvm.sh /tmp/x86_64-gnu-llvm.sh -COPY scripts/x86_64-gnu-llvm1.sh /tmp/x86_64-gnu-llvm1.sh -COPY scripts/x86_64-gnu-llvm2.sh /tmp/x86_64-gnu-llvm2.sh -COPY scripts/x86_64-gnu-llvm3.sh /tmp/x86_64-gnu-llvm3.sh -ENV SCRIPT /tmp/${SCRIPT_ARG} + +COPY scripts/add_dummy_commit.sh /tmp/ +COPY scripts/x86_64-gnu-llvm.sh /tmp/ +COPY scripts/x86_64-gnu-llvm2.sh /tmp/ +COPY scripts/x86_64-gnu-llvm3.sh /tmp/ +COPY scripts/stage_2_test_set1.sh /tmp/ +COPY scripts/stage_2_test_set2.sh /tmp/ + +ENV SCRIPT "/tmp/add_dummy_commit.sh && /tmp/${SCRIPT_ARG}" diff --git a/src/ci/docker/host-x86_64/x86_64-gnu-llvm-19/Dockerfile b/src/ci/docker/host-x86_64/x86_64-gnu-llvm-19/Dockerfile index f2aadbe87cfe..e7016e7d3c0d 100644 --- a/src/ci/docker/host-x86_64/x86_64-gnu-llvm-19/Dockerfile +++ b/src/ci/docker/host-x86_64/x86_64-gnu-llvm-19/Dockerfile @@ -60,9 +60,12 @@ COPY host-x86_64/dist-x86_64-linux/build-gccjit.sh /scripts/ RUN /scripts/build-gccjit.sh /scripts ARG SCRIPT_ARG -COPY scripts/add_dummy_commit.sh /tmp/add_dummy_commit.sh -COPY scripts/x86_64-gnu-llvm.sh /tmp/x86_64-gnu-llvm.sh -COPY scripts/x86_64-gnu-llvm1.sh /tmp/x86_64-gnu-llvm1.sh -COPY scripts/x86_64-gnu-llvm2.sh /tmp/x86_64-gnu-llvm2.sh -COPY scripts/x86_64-gnu-llvm3.sh /tmp/x86_64-gnu-llvm3.sh -ENV SCRIPT /tmp/${SCRIPT_ARG} + +COPY scripts/add_dummy_commit.sh /tmp/ +COPY scripts/x86_64-gnu-llvm.sh /tmp/ +COPY scripts/x86_64-gnu-llvm2.sh /tmp/ +COPY scripts/x86_64-gnu-llvm3.sh /tmp/ +COPY scripts/stage_2_test_set1.sh /tmp/ +COPY scripts/stage_2_test_set2.sh /tmp/ + +ENV SCRIPT "/tmp/add_dummy_commit.sh && /tmp/${SCRIPT_ARG}" diff --git a/src/ci/docker/scripts/stage_2_test_set1.sh b/src/ci/docker/scripts/stage_2_test_set1.sh new file mode 100755 index 000000000000..3baff4b52215 --- /dev/null +++ b/src/ci/docker/scripts/stage_2_test_set1.sh @@ -0,0 +1,9 @@ +#!/bin/bash + +set -ex + +# Run a subset of tests. Used to run tests in parallel in multiple jobs. + +../x.py --stage 2 test \ + --skip compiler \ + --skip src diff --git a/src/ci/docker/scripts/x86_64-gnu-llvm1.sh b/src/ci/docker/scripts/stage_2_test_set2.sh similarity index 67% rename from src/ci/docker/scripts/x86_64-gnu-llvm1.sh rename to src/ci/docker/scripts/stage_2_test_set2.sh index 56ef39aae155..872d758dce38 100755 --- a/src/ci/docker/scripts/x86_64-gnu-llvm1.sh +++ b/src/ci/docker/scripts/stage_2_test_set2.sh @@ -2,7 +2,7 @@ set -ex -/tmp/add_dummy_commit.sh +# Run a subset of tests. Used to run tests in parallel in multiple jobs. ../x.py --stage 2 test \ --skip tests \ diff --git a/src/ci/docker/scripts/x86_64-gnu-llvm.sh b/src/ci/docker/scripts/x86_64-gnu-llvm.sh index e7dcc1ddff44..e0435a3ff5c1 100755 --- a/src/ci/docker/scripts/x86_64-gnu-llvm.sh +++ b/src/ci/docker/scripts/x86_64-gnu-llvm.sh @@ -2,8 +2,6 @@ set -ex -/tmp/add_dummy_commit.sh - # NOTE: intentionally uses all of `x.py`, `x`, and `x.ps1` to make sure they all work on Linux. ../x.py --stage 2 test --skip src/tools/tidy diff --git a/src/ci/docker/scripts/x86_64-gnu-llvm2.sh b/src/ci/docker/scripts/x86_64-gnu-llvm2.sh index c9f6b98f01f4..fe5382aaa48c 100755 --- a/src/ci/docker/scripts/x86_64-gnu-llvm2.sh +++ b/src/ci/docker/scripts/x86_64-gnu-llvm2.sh @@ -2,13 +2,9 @@ set -ex -/tmp/add_dummy_commit.sh - ##### Test stage 2 ##### -../x.py --stage 2 test \ - --skip compiler \ - --skip src +/tmp/stage_2_test_set1.sh # Run the `mir-opt` tests again but this time for a 32-bit target. # This enforces that tests using `// EMIT_MIR_FOR_EACH_BIT_WIDTH` have diff --git a/src/ci/github-actions/jobs.yml b/src/ci/github-actions/jobs.yml index fe0fdde39d0f..9819c26cba8b 100644 --- a/src/ci/github-actions/jobs.yml +++ b/src/ci/github-actions/jobs.yml @@ -58,22 +58,6 @@ envs: NO_DEBUG_ASSERTIONS: 1 NO_OVERFLOW_CHECKS: 1 - # Different set of tests to run tests in parallel in multiple jobs. - stage_2_test_set1: &stage_2_test_set1 - DOCKER_SCRIPT: >- - python3 ../x.py --stage 2 test - --skip compiler - --skip src - - stage_2_test_set2: &stage_2_test_set2 - DOCKER_SCRIPT: >- - python3 ../x.py --stage 2 test - --skip tests - --skip coverage-map - --skip coverage-run - --skip library - --skip tidyselftest - production: &production DEPLOY_BUCKET: rust-lang-ci2 @@ -234,14 +218,14 @@ auto: - image: i686-gnu-1 env: IMAGE: i686-gnu - <<: *stage_2_test_set1 + DOCKER_SCRIPT: stage_2_test_set1.sh <<: *job-linux-4c # Skip tests that run in i686-gnu-1 - image: i686-gnu-2 env: IMAGE: i686-gnu - <<: *stage_2_test_set2 + DOCKER_SCRIPT: stage_2_test_set2.sh <<: *job-linux-4c # The i686-gnu-nopt job is split into multiple jobs to run tests in parallel. @@ -249,7 +233,7 @@ auto: - image: i686-gnu-nopt-1 env: IMAGE: i686-gnu-nopt - <<: *stage_2_test_set1 + DOCKER_SCRIPT: /scripts/stage_2_test_set1.sh <<: *job-linux-4c # Skip tests that run in i686-gnu-nopt-1 @@ -258,12 +242,7 @@ auto: IMAGE: i686-gnu-nopt DOCKER_SCRIPT: >- python3 ../x.py test --stage 0 --config /config/nopt-std-config.toml library/std && - python3 ../x.py --stage 2 test - --skip tests - --skip coverage-map - --skip coverage-run - --skip library - --skip tidyselftest + /scripts/stage_2_test_set2.sh <<: *job-linux-4c - image: mingw-check @@ -319,7 +298,7 @@ auto: env: RUST_BACKTRACE: 1 IMAGE: x86_64-gnu-llvm-19 - DOCKER_SCRIPT: x86_64-gnu-llvm1.sh + DOCKER_SCRIPT: stage_2_test_set1.sh <<: *job-linux-4c # Skip tests that run in x86_64-gnu-llvm-19-{1,3} @@ -345,7 +324,7 @@ auto: RUST_BACKTRACE: 1 READ_ONLY_SRC: "0" IMAGE: x86_64-gnu-llvm-18 - DOCKER_SCRIPT: x86_64-gnu-llvm1.sh + DOCKER_SCRIPT: stage_2_test_set1.sh <<: *job-linux-4c # Skip tests that run in x86_64-gnu-llvm-18-{1,3} From 0b095f80d8f2256aec9f9dad20c5f0c86662ec9d Mon Sep 17 00:00:00 2001 From: clubby789 Date: Tue, 17 Dec 2024 13:17:39 +0000 Subject: [PATCH 19/92] compiler & tools dependencies: Updating allocator-api2 v0.2.20 -> v0.2.21 Updating annotate-snippets v0.11.4 -> v0.11.5 Updating anyhow v1.0.93 -> v1.0.94 Updating bstr v1.11.0 -> v1.11.1 Updating chrono v0.4.38 -> v0.4.39 Updating clap v4.5.21 -> v4.5.23 Updating clap_builder v4.5.21 -> v4.5.23 Updating clap_complete v4.5.38 -> v4.5.39 Updating clap_lex v0.7.3 -> v0.7.4 Updating colored v2.1.0 -> v2.2.0 Updating console v0.15.8 -> v0.15.10 Updating crossbeam-channel v0.5.13 -> v0.5.14 Updating crossbeam-deque v0.8.5 -> v0.8.6 Updating crossbeam-utils v0.8.20 -> v0.8.21 Updating encode_unicode v0.3.6 -> v1.0.0 Updating fastrand v2.2.0 -> v2.3.0 Updating home v0.5.9 -> v0.5.11 Updating js-sys v0.3.74 -> v0.3.76 Updating libc v0.2.167 -> v0.2.168 Updating miniz_oxide v0.8.0 -> v0.8.1 Updating pest v2.7.14 -> v2.7.15 Updating pest_derive v2.7.14 -> v2.7.15 Updating pest_generator v2.7.14 -> v2.7.15 Updating pest_meta v2.7.14 -> v2.7.15 Updating redox_syscall v0.5.7 -> v0.5.8 Updating rustc-stable-hash v0.1.0 -> v0.1.1 Updating rustix v0.38.41 -> v0.38.42 Updating self_cell v1.0.4 -> v1.1.0 Updating semver v1.0.23 -> v1.0.24 Updating serde v1.0.215 -> v1.0.216 Updating serde_derive v1.0.215 -> v1.0.216 Adding thiserror v2.0.7 Adding thiserror-impl v2.0.7 Updating time v0.3.36 -> v0.3.37 Updating time-macros v0.2.18 -> v0.2.19 Updating tokio v1.41.1 -> v1.42.0 Updating wasm-bindgen v0.2.97 -> v0.2.99 Updating wasm-bindgen-backend v0.2.97 -> v0.2.99 Updating wasm-bindgen-macro v0.2.97 -> v0.2.99 Updating wasm-bindgen-macro-support v0.2.97 -> v0.2.99 Updating wasm-bindgen-shared v0.2.97 -> v0.2.99 Updating wasm-encoder v0.221.0 -> v0.221.2 Updating wasmparser v0.221.0 -> v0.221.2 Updating wast v221.0.0 -> v221.0.2 Updating wat v1.221.0 -> v1.221.2 library dependencies: Updating allocator-api2 v0.2.20 -> v0.2.21 Updating libc v0.2.167 -> v0.2.168 rustbook dependencies: Updating anyhow v1.0.93 -> v1.0.94 Updating bstr v1.11.0 -> v1.11.1 Updating chrono v0.4.38 -> v0.4.39 Updating clap v4.5.21 -> v4.5.23 Updating clap_builder v4.5.21 -> v4.5.23 Updating clap_complete v4.5.38 -> v4.5.39 Updating clap_lex v0.7.3 -> v0.7.4 Updating fastrand v2.2.0 -> v2.3.0 Updating js-sys v0.3.74 -> v0.3.76 Updating libc v0.2.167 -> v0.2.168 Updating miniz_oxide v0.8.0 -> v0.8.1 Updating pest v2.7.14 -> v2.7.15 Updating pest_derive v2.7.14 -> v2.7.15 Updating pest_generator v2.7.14 -> v2.7.15 Updating pest_meta v2.7.14 -> v2.7.15 Updating pulldown-cmark-to-cmark v19.0.0 -> v19.0.1 Updating redox_syscall v0.5.7 -> v0.5.8 Updating rustix v0.38.41 -> v0.38.42 Updating semver v1.0.23 -> v1.0.24 Updating serde v1.0.215 -> v1.0.216 Updating serde_derive v1.0.215 -> v1.0.216 Adding thiserror v2.0.7 Adding thiserror-impl v2.0.7 Updating wasm-bindgen v0.2.97 -> v0.2.99 Updating wasm-bindgen-backend v0.2.97 -> v0.2.99 Updating wasm-bindgen-macro v0.2.97 -> v0.2.99 Updating wasm-bindgen-macro-support v0.2.97 -> v0.2.99 Updating wasm-bindgen-shared v0.2.97 -> v0.2.99 Removing windows-sys v0.52.0 --- Cargo.lock | 245 ++++++++++++++------------ compiler/rustc_codegen_ssa/Cargo.toml | 3 +- library/Cargo.lock | 8 +- library/profiler_builtins/Cargo.toml | 3 +- src/tools/rustbook/Cargo.lock | 166 +++++++++-------- 5 files changed, 228 insertions(+), 197 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index 5eeb855aacb8..4a2770b92eb9 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -57,9 +57,9 @@ dependencies = [ [[package]] name = "allocator-api2" -version = "0.2.20" +version = "0.2.21" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "45862d1c77f2228b9e10bc609d5bc203d86ebc9b87ad8d5d5167a6c9abf739d9" +checksum = "683d7910e743518b0e34f1186f92494becacb047c7b6bf616c96772180fef923" [[package]] name = "ammonia" @@ -101,12 +101,12 @@ dependencies = [ [[package]] name = "annotate-snippets" -version = "0.11.4" +version = "0.11.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "24e35ed54e5ea7997c14ed4c70ba043478db1112e98263b3b035907aa197d991" +checksum = "710e8eae58854cdc1790fcb56cca04d712a17be849eeb81da2a724bf4bae2bc4" dependencies = [ "anstyle", - "unicode-width 0.1.14", + "unicode-width 0.2.0", ] [[package]] @@ -182,9 +182,9 @@ dependencies = [ [[package]] name = "anyhow" -version = "1.0.93" +version = "1.0.94" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4c95c10ba0b00a02636238b814946408b1322d5ac4760326e6fb8ec956d85775" +checksum = "c1fd03a028ef38ba2276dce7e33fcd6369c158a1bca17946c4b1b701891c1ff7" dependencies = [ "backtrace", ] @@ -285,9 +285,9 @@ dependencies = [ [[package]] name = "bstr" -version = "1.11.0" +version = "1.11.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1a68f1f47cdf0ec8ee4b941b2eee2a80cb796db73118c0dd09ac63fbe405be22" +checksum = "786a307d683a5bf92e6fd5fd69a7eb613751668d1d8d67d802846dfe367c62c8" dependencies = [ "memchr", "regex-automata 0.4.9", @@ -396,7 +396,7 @@ dependencies = [ "semver", "serde", "serde_json", - "thiserror", + "thiserror 1.0.69", ] [[package]] @@ -426,9 +426,9 @@ checksum = "613afe47fcd5fac7ccf1db93babcb082c5994d996f20b8b159f2ad1658eb5724" [[package]] name = "chrono" -version = "0.4.38" +version = "0.4.39" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a21f936df1771bf62b77f047b726c4625ff2e8aa607c01ec06e5a05bd8463401" +checksum = "7e36cc9d416881d2e24f9a963be5fb1cd90966419ac844274161d10488b3e825" dependencies = [ "android-tzdata", "iana-time-zone", @@ -470,9 +470,9 @@ dependencies = [ [[package]] name = "clap" -version = "4.5.21" +version = "4.5.23" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "fb3b4b9e5a7c7514dfa52869339ee98b3156b0bfb4e8a77c4ff4babb64b1604f" +checksum = "3135e7ec2ef7b10c6ed8950f0f792ed96ee093fa088608f1c76e569722700c84" dependencies = [ "clap_builder", "clap_derive", @@ -490,9 +490,9 @@ dependencies = [ [[package]] name = "clap_builder" -version = "4.5.21" +version = "4.5.23" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b17a95aa67cc7b5ebd32aa5370189aa0d79069ef1c64ce893bd30fb24bff20ec" +checksum = "30582fc632330df2bd26877bde0c1f4470d57c582bbc070376afcd04d8cb4838" dependencies = [ "anstream", "anstyle", @@ -503,9 +503,9 @@ dependencies = [ [[package]] name = "clap_complete" -version = "4.5.38" +version = "4.5.39" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d9647a559c112175f17cf724dc72d3645680a883c58481332779192b0d8e7a01" +checksum = "fd4db298d517d5fa00b2b84bbe044efd3fde43874a41db0d46f91994646a2da4" dependencies = [ "clap", ] @@ -524,9 +524,9 @@ dependencies = [ [[package]] name = "clap_lex" -version = "0.7.3" +version = "0.7.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "afb84c814227b90d6895e01398aee0d8033c00e7466aca416fb6a8e0eb19d8a7" +checksum = "f46ad14479a25103f283c0f10005961cf086d8dc42205bb44c46ac563475dca6" [[package]] name = "clippy" @@ -683,12 +683,12 @@ checksum = "5b63caa9aa9397e2d9480a9b13673856c78d8ac123288526c37d7839f2a86990" [[package]] name = "colored" -version = "2.1.0" +version = "2.2.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "cbf2150cce219b664a8a70df7a1f933836724b503f8a413af9365b4dcc4d90b8" +checksum = "117725a109d387c937a1533ce01b450cbde6b88abceea8473c4d7a85853cda3c" dependencies = [ "lazy_static", - "windows-sys 0.48.0", + "windows-sys 0.59.0", ] [[package]] @@ -727,15 +727,15 @@ dependencies = [ [[package]] name = "console" -version = "0.15.8" +version = "0.15.10" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0e1f83fc076bd6dd27517eacdf25fef6c4dfe5f1d7448bafaaf3a26f13b5e4eb" +checksum = "ea3c6ecd8059b57859df5c69830340ed3c41d30e3da0c1cbed90a96ac853041b" dependencies = [ "encode_unicode", - "lazy_static", "libc", - "unicode-width 0.1.14", - "windows-sys 0.52.0", + "once_cell", + "unicode-width 0.2.0", + "windows-sys 0.59.0", ] [[package]] @@ -782,18 +782,18 @@ dependencies = [ [[package]] name = "crossbeam-channel" -version = "0.5.13" +version = "0.5.14" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "33480d6946193aa8033910124896ca395333cae7e2d1113d1fef6c3272217df2" +checksum = "06ba6d68e24814cb8de6bb986db8222d3a027d15872cabc0d18817bc3c0e4471" dependencies = [ "crossbeam-utils", ] [[package]] name = "crossbeam-deque" -version = "0.8.5" +version = "0.8.6" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "613f8cc01fe9cf1a3eb3d7f488fd2fa8388403e97039e2f73692932e291a770d" +checksum = "9dd111b7b7f7d55b72c0a6ae361660ee5853c9af73f70c3c2ef6858b950e2e51" dependencies = [ "crossbeam-epoch", "crossbeam-utils", @@ -810,9 +810,9 @@ dependencies = [ [[package]] name = "crossbeam-utils" -version = "0.8.20" +version = "0.8.21" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "22ec99545bb0ed0ea7bb9b8e1e9122ea386ff8a48c0922e43f36d45ab09e0e80" +checksum = "d0a5c400df2834b80a4c3327b3aad3a4c4cd4de0629063962b03235697506a28" [[package]] name = "crypto-common" @@ -1101,9 +1101,9 @@ dependencies = [ [[package]] name = "encode_unicode" -version = "0.3.6" +version = "1.0.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a357d28ed41a50f9c765dbfe56cbc04a64e53e5fc58ba79fbc34c10ef3df831f" +checksum = "34aa73646ffb006b8f5147f3dc182bd4bcb190227ce861fc4a4844bf8e3cb2c0" [[package]] name = "env_filter" @@ -1179,9 +1179,9 @@ checksum = "2acce4a10f12dc2fb14a218589d4f1f62ef011b2d0cc4b3cb1bba8e94da14649" [[package]] name = "fastrand" -version = "2.2.0" +version = "2.3.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "486f806e73c5707928240ddc295403b1b93c96a02038563881c4a2fd84b81ac4" +checksum = "37909eebbb50d72f9059c3b6d82c0463f2ff062c9e95845c43a6c9c0355411be" [[package]] name = "field-offset" @@ -1212,7 +1212,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "c936bfdafb507ebbf50b8074c54fa31c5be9a1e7e5f467dd659697041407d07c" dependencies = [ "crc32fast", - "miniz_oxide 0.8.0", + "miniz_oxide 0.8.1", ] [[package]] @@ -1246,7 +1246,7 @@ version = "0.11.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "2a530c4694a6a8d528794ee9bbd8ba0122e779629ac908d15ad5a7ae7763a33d" dependencies = [ - "thiserror", + "thiserror 1.0.69", ] [[package]] @@ -1393,7 +1393,7 @@ dependencies = [ "rinja", "serde", "serde_json", - "thiserror", + "thiserror 1.0.69", ] [[package]] @@ -1501,7 +1501,7 @@ dependencies = [ "pest_derive", "serde", "serde_json", - "thiserror", + "thiserror 1.0.69", ] [[package]] @@ -1550,11 +1550,11 @@ checksum = "7f24254aa9a54b5c858eaee2f5bccdb46aaf0e486a595ed5fd8f86ba55232a70" [[package]] name = "home" -version = "0.5.9" +version = "0.5.11" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e3d1354bf6b7235cb4a0576c2619fd4ed18183f689b12b006a0ee7329eeff9a5" +checksum = "589533453244b0995c858700322199b2becb13b627df2851f64a2775d024abcf" dependencies = [ - "windows-sys 0.52.0", + "windows-sys 0.59.0", ] [[package]] @@ -1942,9 +1942,9 @@ dependencies = [ [[package]] name = "js-sys" -version = "0.3.74" +version = "0.3.76" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a865e038f7f6ed956f788f0d7d60c541fff74c7bd74272c5d4cf15c63743e705" +checksum = "6717b6b5b077764fb5966237269cb3c64edddde4b14ce42647430a78ced9e7b7" dependencies = [ "once_cell", "wasm-bindgen", @@ -2012,9 +2012,9 @@ checksum = "baff4b617f7df3d896f97fe922b64817f6cd9a756bb81d40f8883f2f66dcb401" [[package]] name = "libc" -version = "0.2.167" +version = "0.2.168" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "09d6582e104315a817dff97f75133544b2e094ee22447d2acf4a74e189ba06fc" +checksum = "5aaeb2981e0606ca11d79718f8bb01164f1d6ed75080182d3abf017e6d244b6d" [[package]] name = "libdbus-sys" @@ -2123,7 +2123,7 @@ version = "0.0.1" dependencies = [ "anyhow", "clap", - "thiserror", + "thiserror 1.0.69", "tracing", "tracing-subscriber", ] @@ -2305,9 +2305,9 @@ dependencies = [ [[package]] name = "miniz_oxide" -version = "0.8.0" +version = "0.8.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e2d80299ef12ff69b16a84bb182e3b9df68b5a91574d3d4fa6e41b65deec4df1" +checksum = "a2ef2593ffb6958c941575cee70c8e257438749971869c4ae5acf6f91a168a61" dependencies = [ "adler2", ] @@ -2701,20 +2701,20 @@ dependencies = [ [[package]] name = "pest" -version = "2.7.14" +version = "2.7.15" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "879952a81a83930934cbf1786752d6dedc3b1f29e8f8fb2ad1d0a36f377cf442" +checksum = "8b7cafe60d6cf8e62e1b9b2ea516a089c008945bb5a275416789e7db0bc199dc" dependencies = [ "memchr", - "thiserror", + "thiserror 2.0.7", "ucd-trie", ] [[package]] name = "pest_derive" -version = "2.7.14" +version = "2.7.15" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d214365f632b123a47fd913301e14c946c61d1c183ee245fa76eb752e59a02dd" +checksum = "816518421cfc6887a0d62bf441b6ffb4536fcc926395a69e1a85852d4363f57e" dependencies = [ "pest", "pest_generator", @@ -2722,9 +2722,9 @@ dependencies = [ [[package]] name = "pest_generator" -version = "2.7.14" +version = "2.7.15" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "eb55586734301717aea2ac313f50b2eb8f60d2fc3dc01d190eefa2e625f60c4e" +checksum = "7d1396fd3a870fc7838768d171b4616d5c91f6cc25e377b673d714567d99377b" dependencies = [ "pest", "pest_meta", @@ -2735,9 +2735,9 @@ dependencies = [ [[package]] name = "pest_meta" -version = "2.7.14" +version = "2.7.15" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b75da2a70cf4d9cb76833c990ac9cd3923c9a8905a8929789ce347c84564d03d" +checksum = "e1e58089ea25d717bfd31fb534e4f3afcc2cc569c70de3e239778991ea3b7dea" dependencies = [ "once_cell", "pest", @@ -3020,9 +3020,9 @@ dependencies = [ [[package]] name = "redox_syscall" -version = "0.5.7" +version = "0.5.8" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9b6dfecf2c74bce2466cabf93f6664d6998a69eb21e39f4207930065b27b771f" +checksum = "03a862b389f93e68874fbf580b9de08dd02facb9a788ebadaf4a3fd33cf58834" dependencies = [ "bitflags", ] @@ -3035,7 +3035,7 @@ checksum = "ba009ff324d1fc1b900bd1fdb31564febe58a8ccc8a6fdbb93b543d33b13ca43" dependencies = [ "getrandom", "libredox", - "thiserror", + "thiserror 1.0.69", ] [[package]] @@ -3249,9 +3249,9 @@ dependencies = [ [[package]] name = "rustc-stable-hash" -version = "0.1.0" +version = "0.1.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e5c9f15eec8235d7cb775ee6f81891db79b98fd54ba1ad8fae565b88ef1ae4e2" +checksum = "2febf9acc5ee5e99d1ad0afcdbccc02d87aa3f857a1f01f825b80eacf8edfcd1" [[package]] name = "rustc-std-workspace-alloc" @@ -3692,7 +3692,7 @@ dependencies = [ name = "rustc_errors" version = "0.0.0" dependencies = [ - "annotate-snippets 0.11.4", + "annotate-snippets 0.11.5", "derive_setters", "rustc_abi", "rustc_ast", @@ -3755,7 +3755,7 @@ dependencies = [ name = "rustc_fluent_macro" version = "0.0.0" dependencies = [ - "annotate-snippets 0.11.4", + "annotate-snippets 0.11.5", "fluent-bundle", "fluent-syntax", "proc-macro2", @@ -4710,7 +4710,7 @@ checksum = "81864b097046da5df3758fdc6e4822bbb70afa06317e8ca45ea1b51cb8c5e5a4" dependencies = [ "serde", "serde_json", - "thiserror", + "thiserror 1.0.69", "tracing", ] @@ -4744,7 +4744,7 @@ dependencies = [ "serde", "serde_json", "term", - "thiserror", + "thiserror 1.0.69", "toml 0.7.8", "tracing", "tracing-subscriber", @@ -4755,15 +4755,15 @@ dependencies = [ [[package]] name = "rustix" -version = "0.38.41" +version = "0.38.42" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d7f649912bc1495e167a6edee79151c84b1bad49748cb4f1f1167f459f6224f6" +checksum = "f93dc38ecbab2eb790ff964bb77fa94faf256fd3e73285fd7ba0903b76bedb85" dependencies = [ "bitflags", "errno", "libc", "linux-raw-sys", - "windows-sys 0.52.0", + "windows-sys 0.59.0", ] [[package]] @@ -4823,38 +4823,38 @@ version = "0.10.3" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "e14e4d63b804dc0c7ec4a1e52bcb63f02c7ac94476755aa579edac21e01f915d" dependencies = [ - "self_cell 1.0.4", + "self_cell 1.1.0", ] [[package]] name = "self_cell" -version = "1.0.4" +version = "1.1.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d369a96f978623eb3dc28807c4852d6cc617fed53da5d3c400feff1ef34a714a" +checksum = "c2fdfc24bc566f839a2da4c4295b82db7d25a24253867d5c64355abb5799bdbe" [[package]] name = "semver" -version = "1.0.23" +version = "1.0.24" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "61697e0a1c7e512e84a621326239844a24d8207b4669b41bc18b32ea5cbf988b" +checksum = "3cb6eb87a131f756572d7fb904f6e7b68633f09cca868c5df1c4b8d1a694bbba" dependencies = [ "serde", ] [[package]] name = "serde" -version = "1.0.215" +version = "1.0.216" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6513c1ad0b11a9376da888e3e0baa0077f1aed55c17f50e7b2397136129fb88f" +checksum = "0b9781016e935a97e8beecf0c933758c97a5520d32930e460142b4cd80c6338e" dependencies = [ "serde_derive", ] [[package]] name = "serde_derive" -version = "1.0.215" +version = "1.0.216" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ad1e866f866923f252f05c889987993144fb74e722403468a4ebd70c3cd756c0" +checksum = "46f859dbbf73865c6627ed570e78961cd3ac92407a2d117204c49232485da55e" dependencies = [ "proc-macro2", "quote", @@ -4990,7 +4990,7 @@ checksum = "53d7ac03c67c572d85049d6db815e20a4a19b41b3d5cca732ac582342021ad77" dependencies = [ "nom", "serde", - "thiserror", + "thiserror 1.0.69", "tracing", ] @@ -5007,7 +5007,7 @@ dependencies = [ "spdx-expression", "strum", "strum_macros", - "thiserror", + "thiserror 1.0.69", "uuid", ] @@ -5255,7 +5255,16 @@ version = "1.0.69" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "b6aaf5339b578ea85b50e080feb250a3e8ae8cfcdff9a461c9ec2904bc923f52" dependencies = [ - "thiserror-impl", + "thiserror-impl 1.0.69", +] + +[[package]] +name = "thiserror" +version = "2.0.7" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "93605438cbd668185516ab499d589afb7ee1859ea3d5fc8f6b0755e1c7443767" +dependencies = [ + "thiserror-impl 2.0.7", ] [[package]] @@ -5269,6 +5278,17 @@ dependencies = [ "syn 2.0.90", ] +[[package]] +name = "thiserror-impl" +version = "2.0.7" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e1d8749b4531af2117677a5fcd12b1348a3fe2b81e36e61ffeac5c4aa3273e36" +dependencies = [ + "proc-macro2", + "quote", + "syn 2.0.90", +] + [[package]] name = "thorin-dwp" version = "0.8.0" @@ -5333,9 +5353,9 @@ dependencies = [ [[package]] name = "time" -version = "0.3.36" +version = "0.3.37" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5dfd88e563464686c916c7e46e623e520ddc6d79fa6641390f2e3fa86e83e885" +checksum = "35e7868883861bd0e56d9ac6efcaaca0d6d5d82a2a7ec8209ff492c07cf37b21" dependencies = [ "deranged", "itoa", @@ -5354,9 +5374,9 @@ checksum = "ef927ca75afb808a4d64dd374f00a2adf8d0fcff8e7b184af886c3c87ec4a3f3" [[package]] name = "time-macros" -version = "0.2.18" +version = "0.2.19" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3f252a68540fde3a3877aeea552b832b40ab9a69e318efd078774a01ddee1ccf" +checksum = "2834e6017e3e5e4b9834939793b282bc03b37a3336245fa820e35e233e2a85de" dependencies = [ "num-conv", "time-core", @@ -5389,9 +5409,9 @@ checksum = "1f3ccbac311fea05f86f61904b462b55fb3df8837a366dfc601a0161d0532f20" [[package]] name = "tokio" -version = "1.41.1" +version = "1.42.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "22cfb5bee7a6a52939ca9224d6ac897bb669134078daa8735560897f69de4d33" +checksum = "5cec9b21b0450273377fc97bd4c33a8acffc8c996c987a7c5b319a0083707551" dependencies = [ "backtrace", "bytes", @@ -5579,7 +5599,7 @@ version = "0.26.5" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "32ee4c40e5a5f9fa6864ff976473e5d6a6e9884b6ce68b40690d9f87e1994c83" dependencies = [ - "annotate-snippets 0.11.4", + "annotate-snippets 0.11.5", "anyhow", "bstr", "cargo-platform", @@ -5825,9 +5845,9 @@ checksum = "0f76d9fa52234153eeb40b088de91a8c13dc28a912cf6f31cd89ca4bac9024e0" [[package]] name = "wasm-bindgen" -version = "0.2.97" +version = "0.2.99" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d15e63b4482863c109d70a7b8706c1e364eb6ea449b201a76c5b89cedcec2d5c" +checksum = "a474f6281d1d70c17ae7aa6a613c87fce69a127e2624002df63dcb39d6cf6396" dependencies = [ "cfg-if", "once_cell", @@ -5836,13 +5856,12 @@ dependencies = [ [[package]] name = "wasm-bindgen-backend" -version = "0.2.97" +version = "0.2.99" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8d36ef12e3aaca16ddd3f67922bc63e48e953f126de60bd33ccc0101ef9998cd" +checksum = "5f89bb38646b4f81674e8f5c3fb81b562be1fd936d84320f3264486418519c79" dependencies = [ "bumpalo", "log", - "once_cell", "proc-macro2", "quote", "syn 2.0.90", @@ -5851,9 +5870,9 @@ dependencies = [ [[package]] name = "wasm-bindgen-macro" -version = "0.2.97" +version = "0.2.99" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "705440e08b42d3e4b36de7d66c944be628d579796b8090bfa3471478a2260051" +checksum = "2cc6181fd9a7492eef6fef1f33961e3695e4579b9872a6f7c83aee556666d4fe" dependencies = [ "quote", "wasm-bindgen-macro-support", @@ -5861,9 +5880,9 @@ dependencies = [ [[package]] name = "wasm-bindgen-macro-support" -version = "0.2.97" +version = "0.2.99" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "98c9ae5a76e46f4deecd0f0255cc223cfa18dc9b261213b8aa0c7b36f61b3f1d" +checksum = "30d7a95b763d3c45903ed6c81f156801839e5ee968bb07e534c44df0fcd330c2" dependencies = [ "proc-macro2", "quote", @@ -5874,9 +5893,9 @@ dependencies = [ [[package]] name = "wasm-bindgen-shared" -version = "0.2.97" +version = "0.2.99" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6ee99da9c5ba11bd675621338ef6fa52296b76b83305e9b6e5c77d4c286d6d49" +checksum = "943aab3fdaaa029a6e0271b35ea10b72b943135afe9bffca82384098ad0e06a6" [[package]] name = "wasm-component-ld" @@ -5917,12 +5936,12 @@ dependencies = [ [[package]] name = "wasm-encoder" -version = "0.221.0" +version = "0.221.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "de35b6c3ef1f53ac7a31b5e69bc00f1542ea337e7e7162dc34c68b537ff82690" +checksum = "c17a3bd88f2155da63a1f2fcb8a56377a24f0b6dfed12733bb5f544e86f690c5" dependencies = [ "leb128", - "wasmparser 0.221.0", + "wasmparser 0.221.2", ] [[package]] @@ -5966,9 +5985,9 @@ dependencies = [ [[package]] name = "wasmparser" -version = "0.221.0" +version = "0.221.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8659e755615170cfe20da468865c989da78c5da16d8652e69a75acda02406a92" +checksum = "9845c470a2e10b61dd42c385839cdd6496363ed63b5c9e420b5488b77bd22083" dependencies = [ "bitflags", "indexmap", @@ -5977,22 +5996,22 @@ dependencies = [ [[package]] name = "wast" -version = "221.0.0" +version = "221.0.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9d8eb1933d493dd07484a255c3f52236123333f5befaa3be36182a50d393ec54" +checksum = "fcc4470b9de917ba199157d1f0ae104f2ae362be728c43e68c571c7715bd629e" dependencies = [ "bumpalo", "leb128", "memchr", "unicode-width 0.2.0", - "wasm-encoder 0.221.0", + "wasm-encoder 0.221.2", ] [[package]] name = "wat" -version = "1.221.0" +version = "1.221.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c813fd4e5b2b97242830b56e7b7dc5479bc17aaa8730109be35e61909af83993" +checksum = "6b1f3c6d82af47286494c6caea1d332037f5cbeeac82bbf5ef59cb8c201c466e" dependencies = [ "wast", ] diff --git a/compiler/rustc_codegen_ssa/Cargo.toml b/compiler/rustc_codegen_ssa/Cargo.toml index f5c155667ba7..b361ac8c739f 100644 --- a/compiler/rustc_codegen_ssa/Cargo.toml +++ b/compiler/rustc_codegen_ssa/Cargo.toml @@ -8,7 +8,8 @@ edition = "2021" ar_archive_writer = "0.4.2" arrayvec = { version = "0.7", default-features = false } bitflags = "2.4.1" -cc = "1.1.23" +# Pinned so `cargo update` bumps don't cause breakage +cc = "=1.2.0" either = "1.5.0" itertools = "0.12" pathdiff = "0.2.0" diff --git a/library/Cargo.lock b/library/Cargo.lock index 03c2356e542a..fd450c7d3dd8 100644 --- a/library/Cargo.lock +++ b/library/Cargo.lock @@ -36,9 +36,9 @@ dependencies = [ [[package]] name = "allocator-api2" -version = "0.2.20" +version = "0.2.21" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "45862d1c77f2228b9e10bc609d5bc203d86ebc9b87ad8d5d5167a6c9abf739d9" +checksum = "683d7910e743518b0e34f1186f92494becacb047c7b6bf616c96772180fef923" [[package]] name = "cc" @@ -158,9 +158,9 @@ dependencies = [ [[package]] name = "libc" -version = "0.2.167" +version = "0.2.168" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "09d6582e104315a817dff97f75133544b2e094ee22447d2acf4a74e189ba06fc" +checksum = "5aaeb2981e0606ca11d79718f8bb01164f1d6ed75080182d3abf017e6d244b6d" dependencies = [ "rustc-std-workspace-core", ] diff --git a/library/profiler_builtins/Cargo.toml b/library/profiler_builtins/Cargo.toml index c601a41b433c..230e8051602e 100644 --- a/library/profiler_builtins/Cargo.toml +++ b/library/profiler_builtins/Cargo.toml @@ -11,4 +11,5 @@ doc = false [dependencies] [build-dependencies] -cc = "1.2" +# Pinned so `cargo update` bumps don't cause breakage +cc = "=1.2.0" diff --git a/src/tools/rustbook/Cargo.lock b/src/tools/rustbook/Cargo.lock index e8c9c4f4cd10..c2f4ba161b7f 100644 --- a/src/tools/rustbook/Cargo.lock +++ b/src/tools/rustbook/Cargo.lock @@ -81,7 +81,7 @@ version = "1.1.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "79947af37f4177cfead1110013d678905c37501914fba0efea834c3fe9a8d60c" dependencies = [ - "windows-sys 0.59.0", + "windows-sys", ] [[package]] @@ -91,14 +91,14 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "2109dbce0e72be3ec00bed26e6a7479ca384ad226efdd66db8fa2e3a38c83125" dependencies = [ "anstyle", - "windows-sys 0.59.0", + "windows-sys", ] [[package]] name = "anyhow" -version = "1.0.93" +version = "1.0.94" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4c95c10ba0b00a02636238b814946408b1322d5ac4760326e6fb8ec956d85775" +checksum = "c1fd03a028ef38ba2276dce7e33fcd6369c158a1bca17946c4b1b701891c1ff7" [[package]] name = "autocfg" @@ -138,9 +138,9 @@ dependencies = [ [[package]] name = "bstr" -version = "1.11.0" +version = "1.11.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1a68f1f47cdf0ec8ee4b941b2eee2a80cb796db73118c0dd09ac63fbe405be22" +checksum = "786a307d683a5bf92e6fd5fd69a7eb613751668d1d8d67d802846dfe367c62c8" dependencies = [ "memchr", "regex-automata", @@ -176,9 +176,9 @@ checksum = "baf1de4339761588bc0619e3cbc0120ee582ebb74b53b4efbf79117bd2da40fd" [[package]] name = "chrono" -version = "0.4.38" +version = "0.4.39" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a21f936df1771bf62b77f047b726c4625ff2e8aa607c01ec06e5a05bd8463401" +checksum = "7e36cc9d416881d2e24f9a963be5fb1cd90966419ac844274161d10488b3e825" dependencies = [ "android-tzdata", "iana-time-zone", @@ -190,9 +190,9 @@ dependencies = [ [[package]] name = "clap" -version = "4.5.21" +version = "4.5.23" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "fb3b4b9e5a7c7514dfa52869339ee98b3156b0bfb4e8a77c4ff4babb64b1604f" +checksum = "3135e7ec2ef7b10c6ed8950f0f792ed96ee093fa088608f1c76e569722700c84" dependencies = [ "clap_builder", "clap_derive", @@ -200,9 +200,9 @@ dependencies = [ [[package]] name = "clap_builder" -version = "4.5.21" +version = "4.5.23" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b17a95aa67cc7b5ebd32aa5370189aa0d79069ef1c64ce893bd30fb24bff20ec" +checksum = "30582fc632330df2bd26877bde0c1f4470d57c582bbc070376afcd04d8cb4838" dependencies = [ "anstream", "anstyle", @@ -213,9 +213,9 @@ dependencies = [ [[package]] name = "clap_complete" -version = "4.5.38" +version = "4.5.39" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d9647a559c112175f17cf724dc72d3645680a883c58481332779192b0d8e7a01" +checksum = "fd4db298d517d5fa00b2b84bbe044efd3fde43874a41db0d46f91994646a2da4" dependencies = [ "clap", ] @@ -234,9 +234,9 @@ dependencies = [ [[package]] name = "clap_lex" -version = "0.7.3" +version = "0.7.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "afb84c814227b90d6895e01398aee0d8033c00e7466aca416fb6a8e0eb19d8a7" +checksum = "f46ad14479a25103f283c0f10005961cf086d8dc42205bb44c46ac563475dca6" [[package]] name = "colorchoice" @@ -376,14 +376,14 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "33d852cb9b869c2a9b3df2f71a3074817f01e1844f839a144f5fcef059a4eb5d" dependencies = [ "libc", - "windows-sys 0.59.0", + "windows-sys", ] [[package]] name = "fastrand" -version = "2.2.0" +version = "2.3.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "486f806e73c5707928240ddc295403b1b93c96a02038563881c4a2fd84b81ac4" +checksum = "37909eebbb50d72f9059c3b6d82c0463f2ff062c9e95845c43a6c9c0355411be" [[package]] name = "flate2" @@ -462,7 +462,7 @@ dependencies = [ "pest_derive", "serde", "serde_json", - "thiserror", + "thiserror 1.0.69", ] [[package]] @@ -503,7 +503,7 @@ dependencies = [ "serde", "serde_derive", "serde_json", - "thiserror", + "thiserror 1.0.69", ] [[package]] @@ -698,9 +698,9 @@ checksum = "d75a2a4b1b190afb6f5425f10f6a8f959d2ea0b9c2b1d79553551850539e4674" [[package]] name = "js-sys" -version = "0.3.74" +version = "0.3.76" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a865e038f7f6ed956f788f0d7d60c541fff74c7bd74272c5d4cf15c63743e705" +checksum = "6717b6b5b077764fb5966237269cb3c64edddde4b14ce42647430a78ced9e7b7" dependencies = [ "once_cell", "wasm-bindgen", @@ -714,9 +714,9 @@ checksum = "bbd2bcb4c963f2ddae06a2efc7e9f3591312473c50c6685e1f298068316e66fe" [[package]] name = "libc" -version = "0.2.167" +version = "0.2.168" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "09d6582e104315a817dff97f75133544b2e094ee22447d2acf4a74e189ba06fc" +checksum = "5aaeb2981e0606ca11d79718f8bb01164f1d6ed75080182d3abf017e6d244b6d" [[package]] name = "libdbus-sys" @@ -864,9 +864,9 @@ dependencies = [ "html_parser", "mdbook", "pulldown-cmark 0.12.2", - "pulldown-cmark-to-cmark 19.0.0", + "pulldown-cmark-to-cmark 19.0.1", "serde_json", - "thiserror", + "thiserror 1.0.69", "toml 0.8.19", ] @@ -878,9 +878,9 @@ checksum = "78ca9ab1a0babb1e7d5695e3530886289c18cf2f87ec19a575a0abdce112e3a3" [[package]] name = "miniz_oxide" -version = "0.8.0" +version = "0.8.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e2d80299ef12ff69b16a84bb182e3b9df68b5a91574d3d4fa6e41b65deec4df1" +checksum = "a2ef2593ffb6958c941575cee70c8e257438749971869c4ae5acf6f91a168a61" dependencies = [ "adler2", ] @@ -897,7 +897,7 @@ version = "1.3.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "c8911957c4b1549ac0dc74e30db9c8b0e66ddcd6d7acc33098f4c63a64a6d7ed" dependencies = [ - "windows-sys 0.59.0", + "windows-sys", ] [[package]] @@ -961,7 +961,7 @@ dependencies = [ "bstr", "dbus", "normpath", - "windows-sys 0.59.0", + "windows-sys", ] [[package]] @@ -1001,20 +1001,20 @@ checksum = "e3148f5046208a5d56bcfc03053e3ca6334e51da8dfb19b6cdc8b306fae3283e" [[package]] name = "pest" -version = "2.7.14" +version = "2.7.15" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "879952a81a83930934cbf1786752d6dedc3b1f29e8f8fb2ad1d0a36f377cf442" +checksum = "8b7cafe60d6cf8e62e1b9b2ea516a089c008945bb5a275416789e7db0bc199dc" dependencies = [ "memchr", - "thiserror", + "thiserror 2.0.7", "ucd-trie", ] [[package]] name = "pest_derive" -version = "2.7.14" +version = "2.7.15" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d214365f632b123a47fd913301e14c946c61d1c183ee245fa76eb752e59a02dd" +checksum = "816518421cfc6887a0d62bf441b6ffb4536fcc926395a69e1a85852d4363f57e" dependencies = [ "pest", "pest_generator", @@ -1022,9 +1022,9 @@ dependencies = [ [[package]] name = "pest_generator" -version = "2.7.14" +version = "2.7.15" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "eb55586734301717aea2ac313f50b2eb8f60d2fc3dc01d190eefa2e625f60c4e" +checksum = "7d1396fd3a870fc7838768d171b4616d5c91f6cc25e377b673d714567d99377b" dependencies = [ "pest", "pest_meta", @@ -1035,9 +1035,9 @@ dependencies = [ [[package]] name = "pest_meta" -version = "2.7.14" +version = "2.7.15" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b75da2a70cf4d9cb76833c990ac9cd3923c9a8905a8929789ce347c84564d03d" +checksum = "e1e58089ea25d717bfd31fb534e4f3afcc2cc569c70de3e239778991ea3b7dea" dependencies = [ "once_cell", "pest", @@ -1200,9 +1200,9 @@ dependencies = [ [[package]] name = "pulldown-cmark-to-cmark" -version = "19.0.0" +version = "19.0.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7d742adcc7b655dba3e9ebab47954ca229fc0fa1df01fdc94349b6f3a2e6d257" +checksum = "e84a87de49d1b6c63f0998da7ade299905387ae1feae350efc98e0632637f589" dependencies = [ "pulldown-cmark 0.12.2", ] @@ -1248,9 +1248,9 @@ dependencies = [ [[package]] name = "redox_syscall" -version = "0.5.7" +version = "0.5.8" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9b6dfecf2c74bce2466cabf93f6664d6998a69eb21e39f4207930065b27b771f" +checksum = "03a862b389f93e68874fbf580b9de08dd02facb9a788ebadaf4a3fd33cf58834" dependencies = [ "bitflags 2.6.0", ] @@ -1298,15 +1298,15 @@ dependencies = [ [[package]] name = "rustix" -version = "0.38.41" +version = "0.38.42" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d7f649912bc1495e167a6edee79151c84b1bad49748cb4f1f1167f459f6224f6" +checksum = "f93dc38ecbab2eb790ff964bb77fa94faf256fd3e73285fd7ba0903b76bedb85" dependencies = [ "bitflags 2.6.0", "errno", "libc", "linux-raw-sys", - "windows-sys 0.52.0", + "windows-sys", ] [[package]] @@ -1332,24 +1332,24 @@ checksum = "94143f37725109f92c262ed2cf5e59bce7498c01bcc1502d7b9afe439a4e9f49" [[package]] name = "semver" -version = "1.0.23" +version = "1.0.24" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "61697e0a1c7e512e84a621326239844a24d8207b4669b41bc18b32ea5cbf988b" +checksum = "3cb6eb87a131f756572d7fb904f6e7b68633f09cca868c5df1c4b8d1a694bbba" [[package]] name = "serde" -version = "1.0.215" +version = "1.0.216" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6513c1ad0b11a9376da888e3e0baa0077f1aed55c17f50e7b2397136129fb88f" +checksum = "0b9781016e935a97e8beecf0c933758c97a5520d32930e460142b4cd80c6338e" dependencies = [ "serde_derive", ] [[package]] name = "serde_derive" -version = "1.0.215" +version = "1.0.216" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ad1e866f866923f252f05c889987993144fb74e722403468a4ebd70c3cd756c0" +checksum = "46f859dbbf73865c6627ed570e78961cd3ac92407a2d117204c49232485da55e" dependencies = [ "proc-macro2", "quote", @@ -1482,7 +1482,7 @@ dependencies = [ "serde", "serde_derive", "serde_json", - "thiserror", + "thiserror 1.0.69", "walkdir", ] @@ -1496,7 +1496,7 @@ dependencies = [ "fastrand", "once_cell", "rustix", - "windows-sys 0.59.0", + "windows-sys", ] [[package]] @@ -1517,7 +1517,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "5352447f921fda68cf61b4101566c0bdb5104eff6804d0678e5227580ab6a4e9" dependencies = [ "rustix", - "windows-sys 0.59.0", + "windows-sys", ] [[package]] @@ -1532,7 +1532,16 @@ version = "1.0.69" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "b6aaf5339b578ea85b50e080feb250a3e8ae8cfcdff9a461c9ec2904bc923f52" dependencies = [ - "thiserror-impl", + "thiserror-impl 1.0.69", +] + +[[package]] +name = "thiserror" +version = "2.0.7" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "93605438cbd668185516ab499d589afb7ee1859ea3d5fc8f6b0755e1c7443767" +dependencies = [ + "thiserror-impl 2.0.7", ] [[package]] @@ -1546,6 +1555,17 @@ dependencies = [ "syn", ] +[[package]] +name = "thiserror-impl" +version = "2.0.7" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e1d8749b4531af2117677a5fcd12b1348a3fe2b81e36e61ffeac5c4aa3273e36" +dependencies = [ + "proc-macro2", + "quote", + "syn", +] + [[package]] name = "tinystr" version = "0.7.6" @@ -1694,9 +1714,9 @@ checksum = "9c8d87e72b64a3b4db28d11ce29237c246188f4f51057d65a7eab63b7987e423" [[package]] name = "wasm-bindgen" -version = "0.2.97" +version = "0.2.99" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d15e63b4482863c109d70a7b8706c1e364eb6ea449b201a76c5b89cedcec2d5c" +checksum = "a474f6281d1d70c17ae7aa6a613c87fce69a127e2624002df63dcb39d6cf6396" dependencies = [ "cfg-if", "once_cell", @@ -1705,13 +1725,12 @@ dependencies = [ [[package]] name = "wasm-bindgen-backend" -version = "0.2.97" +version = "0.2.99" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8d36ef12e3aaca16ddd3f67922bc63e48e953f126de60bd33ccc0101ef9998cd" +checksum = "5f89bb38646b4f81674e8f5c3fb81b562be1fd936d84320f3264486418519c79" dependencies = [ "bumpalo", "log", - "once_cell", "proc-macro2", "quote", "syn", @@ -1720,9 +1739,9 @@ dependencies = [ [[package]] name = "wasm-bindgen-macro" -version = "0.2.97" +version = "0.2.99" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "705440e08b42d3e4b36de7d66c944be628d579796b8090bfa3471478a2260051" +checksum = "2cc6181fd9a7492eef6fef1f33961e3695e4579b9872a6f7c83aee556666d4fe" dependencies = [ "quote", "wasm-bindgen-macro-support", @@ -1730,9 +1749,9 @@ dependencies = [ [[package]] name = "wasm-bindgen-macro-support" -version = "0.2.97" +version = "0.2.99" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "98c9ae5a76e46f4deecd0f0255cc223cfa18dc9b261213b8aa0c7b36f61b3f1d" +checksum = "30d7a95b763d3c45903ed6c81f156801839e5ee968bb07e534c44df0fcd330c2" dependencies = [ "proc-macro2", "quote", @@ -1743,9 +1762,9 @@ dependencies = [ [[package]] name = "wasm-bindgen-shared" -version = "0.2.97" +version = "0.2.99" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6ee99da9c5ba11bd675621338ef6fa52296b76b83305e9b6e5c77d4c286d6d49" +checksum = "943aab3fdaaa029a6e0271b35ea10b72b943135afe9bffca82384098ad0e06a6" [[package]] name = "winapi" @@ -1769,7 +1788,7 @@ version = "0.1.9" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "cf221c93e13a30d793f7645a0e7762c55d169dbb0a49671918a2319d289b10bb" dependencies = [ - "windows-sys 0.59.0", + "windows-sys", ] [[package]] @@ -1787,15 +1806,6 @@ dependencies = [ "windows-targets", ] -[[package]] -name = "windows-sys" -version = "0.52.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "282be5f36a8ce781fad8c8ae18fa3f9beff57ec1b52cb3de0789201425d9a33d" -dependencies = [ - "windows-targets", -] - [[package]] name = "windows-sys" version = "0.59.0" From bd7213ff89122c8ef881ef402a97fce7aef17ec9 Mon Sep 17 00:00:00 2001 From: Taiki Endo Date: Wed, 18 Dec 2024 02:59:07 +0900 Subject: [PATCH 20/92] tests/assembly/asm: Remove uses of rustc_attrs and lang_items features by using minicore --- tests/assembly/asm/aarch64-el2vmsa.rs | 12 +++------ tests/assembly/asm/aarch64-modifiers.rs | 20 +++----------- tests/assembly/asm/aarch64-types.rs | 36 ++++--------------------- tests/assembly/asm/arm-modifiers.rs | 28 +++---------------- tests/assembly/asm/arm-types.rs | 33 +++-------------------- tests/assembly/asm/avr-modifiers.rs | 24 +++-------------- tests/assembly/asm/avr-types.rs | 24 +++-------------- tests/assembly/asm/bpf-types.rs | 28 +++---------------- tests/assembly/asm/hexagon-types.rs | 27 +++---------------- tests/assembly/asm/loongarch-type.rs | 29 +++----------------- tests/assembly/asm/m68k-types.rs | 24 +++-------------- tests/assembly/asm/mips-types.rs | 30 +++------------------ tests/assembly/asm/msp430-types.rs | 24 +++-------------- tests/assembly/asm/nvptx-types.rs | 28 ++++--------------- tests/assembly/asm/powerpc-types.rs | 34 ++++------------------- tests/assembly/asm/riscv-types.rs | 31 +++------------------ tests/assembly/asm/s390x-types.rs | 34 +++-------------------- tests/assembly/asm/sparc-types.rs | 31 +++------------------ tests/assembly/asm/wasm-types.rs | 28 ++++--------------- tests/assembly/asm/x86-modifiers.rs | 24 +++-------------- tests/assembly/asm/x86-types.rs | 26 +++--------------- tests/auxiliary/minicore.rs | 24 +++++++++++++++-- 22 files changed, 110 insertions(+), 489 deletions(-) diff --git a/tests/assembly/asm/aarch64-el2vmsa.rs b/tests/assembly/asm/aarch64-el2vmsa.rs index c217f008c070..3652d58d85a0 100644 --- a/tests/assembly/asm/aarch64-el2vmsa.rs +++ b/tests/assembly/asm/aarch64-el2vmsa.rs @@ -1,18 +1,14 @@ +//@ add-core-stubs //@ assembly-output: emit-asm //@ compile-flags: --target aarch64-unknown-linux-gnu //@ needs-llvm-components: aarch64 -#![feature(no_core, lang_items, rustc_attrs)] +#![feature(no_core)] #![crate_type = "rlib"] #![no_core] -#[rustc_builtin_macro] -macro_rules! asm { - () => {}; -} - -#[lang = "sized"] -trait Sized {} +extern crate minicore; +use minicore::*; // CHECK-LABEL: ttbr0_el2: #[no_mangle] diff --git a/tests/assembly/asm/aarch64-modifiers.rs b/tests/assembly/asm/aarch64-modifiers.rs index a4a41dd96c16..a3956d21a067 100644 --- a/tests/assembly/asm/aarch64-modifiers.rs +++ b/tests/assembly/asm/aarch64-modifiers.rs @@ -1,29 +1,17 @@ +//@ add-core-stubs //@ assembly-output: emit-asm //@ compile-flags: -O -C panic=abort //@ compile-flags: --target aarch64-unknown-linux-gnu //@ compile-flags: -Zmerge-functions=disabled //@ needs-llvm-components: aarch64 -#![feature(no_core, lang_items, rustc_attrs)] +#![feature(no_core)] #![crate_type = "rlib"] #![no_core] #![allow(asm_sub_register)] -#[rustc_builtin_macro] -macro_rules! asm { - () => {}; -} -#[rustc_builtin_macro] -macro_rules! stringify { - () => {}; -} - -#[lang = "sized"] -trait Sized {} -#[lang = "copy"] -trait Copy {} - -impl Copy for i32 {} +extern crate minicore; +use minicore::*; macro_rules! check { ($func:ident $reg:ident $code:literal) => { diff --git a/tests/assembly/asm/aarch64-types.rs b/tests/assembly/asm/aarch64-types.rs index 22e60cd8159b..439385b14b05 100644 --- a/tests/assembly/asm/aarch64-types.rs +++ b/tests/assembly/asm/aarch64-types.rs @@ -1,3 +1,4 @@ +//@ add-core-stubs //@ revisions: aarch64 arm64ec //@ assembly-output: emit-asm //@ [aarch64] compile-flags: --target aarch64-unknown-linux-gnu @@ -6,33 +7,15 @@ //@ [arm64ec] needs-llvm-components: aarch64 //@ compile-flags: -Zmerge-functions=disabled -#![feature(no_core, lang_items, rustc_attrs, repr_simd, f16, f128)] +#![feature(no_core, repr_simd, f16, f128)] #![crate_type = "rlib"] #![no_core] #![allow(asm_sub_register, non_camel_case_types)] // FIXME(f16_f128): Only needed for FIXME in check! and check_reg! -#![feature(auto_traits)] +#![feature(auto_traits, lang_items)] -#[rustc_builtin_macro] -macro_rules! asm { - () => {}; -} -#[rustc_builtin_macro] -macro_rules! concat { - () => {}; -} -#[rustc_builtin_macro] -macro_rules! stringify { - () => {}; -} - -#[lang = "sized"] -trait Sized {} -#[lang = "copy"] -trait Copy {} - -// Do we really need to use no_core for this?!? -impl Copy for [T; N] {} +extern crate minicore; +use minicore::*; type ptr = *mut u8; @@ -65,15 +48,6 @@ pub struct f32x4([f32; 4]); #[repr(simd)] pub struct f64x2([f64; 2]); -impl Copy for i8 {} -impl Copy for i16 {} -impl Copy for f16 {} -impl Copy for i32 {} -impl Copy for f32 {} -impl Copy for i64 {} -impl Copy for f64 {} -impl Copy for f128 {} -impl Copy for ptr {} impl Copy for i8x8 {} impl Copy for i16x4 {} impl Copy for i32x2 {} diff --git a/tests/assembly/asm/arm-modifiers.rs b/tests/assembly/asm/arm-modifiers.rs index 7d8d7e838703..562b6bed74c3 100644 --- a/tests/assembly/asm/arm-modifiers.rs +++ b/tests/assembly/asm/arm-modifiers.rs @@ -1,3 +1,4 @@ +//@ add-core-stubs //@ assembly-output: emit-asm //@ compile-flags: -O -C panic=abort //@ compile-flags: --target armv7-unknown-linux-gnueabihf @@ -5,38 +6,17 @@ //@ compile-flags: -Zmerge-functions=disabled //@ needs-llvm-components: arm -#![feature(no_core, lang_items, rustc_attrs, repr_simd)] +#![feature(no_core, repr_simd)] #![crate_type = "rlib"] #![no_core] #![allow(asm_sub_register, non_camel_case_types)] -#[rustc_builtin_macro] -macro_rules! asm { - () => {}; -} -#[rustc_builtin_macro] -macro_rules! concat { - () => {}; -} -#[rustc_builtin_macro] -macro_rules! stringify { - () => {}; -} - -#[lang = "sized"] -trait Sized {} -#[lang = "copy"] -trait Copy {} - -// Do we really need to use no_core for this?!? -impl Copy for [T; N] {} +extern crate minicore; +use minicore::*; #[repr(simd)] pub struct f32x4([f32; 4]); -impl Copy for i32 {} -impl Copy for f32 {} -impl Copy for f64 {} impl Copy for f32x4 {} macro_rules! check { diff --git a/tests/assembly/asm/arm-types.rs b/tests/assembly/asm/arm-types.rs index 9cebb588aaf8..fb93f474c20e 100644 --- a/tests/assembly/asm/arm-types.rs +++ b/tests/assembly/asm/arm-types.rs @@ -1,3 +1,4 @@ +//@ add-core-stubs //@ revisions: base d32 neon //@ assembly-output: emit-asm //@ compile-flags: --target armv7-unknown-linux-gnueabihf @@ -8,31 +9,13 @@ //@[neon] filecheck-flags: --check-prefix d32 //@ needs-llvm-components: arm -#![feature(no_core, lang_items, rustc_attrs, repr_simd, f16)] +#![feature(no_core, repr_simd, f16)] #![crate_type = "rlib"] #![no_core] #![allow(asm_sub_register, non_camel_case_types)] -#[rustc_builtin_macro] -macro_rules! asm { - () => {}; -} -#[rustc_builtin_macro] -macro_rules! concat { - () => {}; -} -#[rustc_builtin_macro] -macro_rules! stringify { - () => {}; -} - -#[lang = "sized"] -trait Sized {} -#[lang = "copy"] -trait Copy {} - -// Do we really need to use no_core for this?!? -impl Copy for [T; N] {} +extern crate minicore; +use minicore::*; type ptr = *mut u8; @@ -61,14 +44,6 @@ pub struct f16x8([f16; 8]); #[repr(simd)] pub struct f32x4([f32; 4]); -impl Copy for i8 {} -impl Copy for i16 {} -impl Copy for i32 {} -impl Copy for f16 {} -impl Copy for f32 {} -impl Copy for i64 {} -impl Copy for f64 {} -impl Copy for ptr {} impl Copy for i8x8 {} impl Copy for i16x4 {} impl Copy for i32x2 {} diff --git a/tests/assembly/asm/avr-modifiers.rs b/tests/assembly/asm/avr-modifiers.rs index e94375f95969..585fdd7b7253 100644 --- a/tests/assembly/asm/avr-modifiers.rs +++ b/tests/assembly/asm/avr-modifiers.rs @@ -1,34 +1,18 @@ +//@ add-core-stubs //@ assembly-output: emit-asm //@ compile-flags: --target avr-unknown-gnu-atmega328 //@ needs-llvm-components: avr -#![feature(no_core, lang_items, rustc_attrs, asm_experimental_arch)] +#![feature(no_core, asm_experimental_arch)] #![crate_type = "rlib"] #![no_core] #![allow(non_camel_case_types)] -#[rustc_builtin_macro] -macro_rules! asm { - () => {}; -} -#[rustc_builtin_macro] -macro_rules! concat { - () => {}; -} - -#[lang = "sized"] -trait Sized {} -#[lang = "copy"] -trait Copy {} +extern crate minicore; +use minicore::*; type ptr = *const u64; -impl Copy for i8 {} -impl Copy for i16 {} -impl Copy for i32 {} -impl Copy for i64 {} -impl Copy for ptr {} - macro_rules! check { ($func:ident $hi:literal $lo:literal $reg:tt) => { #[no_mangle] diff --git a/tests/assembly/asm/avr-types.rs b/tests/assembly/asm/avr-types.rs index 88b16895e8dc..25cf3ec3b4bd 100644 --- a/tests/assembly/asm/avr-types.rs +++ b/tests/assembly/asm/avr-types.rs @@ -1,34 +1,18 @@ +//@ add-core-stubs //@ assembly-output: emit-asm //@ compile-flags: --target avr-unknown-gnu-atmega328 //@ needs-llvm-components: avr -#![feature(no_core, lang_items, rustc_attrs, asm_experimental_arch)] +#![feature(no_core, asm_experimental_arch)] #![crate_type = "rlib"] #![no_core] #![allow(non_camel_case_types)] -#[rustc_builtin_macro] -macro_rules! asm { - () => {}; -} -#[rustc_builtin_macro] -macro_rules! concat { - () => {}; -} - -#[lang = "sized"] -trait Sized {} -#[lang = "copy"] -trait Copy {} +extern crate minicore; +use minicore::*; type ptr = *const u64; -impl Copy for i8 {} -impl Copy for i16 {} -impl Copy for i32 {} -impl Copy for i64 {} -impl Copy for ptr {} - macro_rules! check { ($func:ident $ty:ident $class:ident) => { #[no_mangle] diff --git a/tests/assembly/asm/bpf-types.rs b/tests/assembly/asm/bpf-types.rs index 0a9ec7dd52ba..07ea7bd5ce05 100644 --- a/tests/assembly/asm/bpf-types.rs +++ b/tests/assembly/asm/bpf-types.rs @@ -1,38 +1,18 @@ +//@ add-core-stubs //@ assembly-output: emit-asm //@ compile-flags: --target bpfel-unknown-none -C target_feature=+alu32 //@ needs-llvm-components: bpf -#![feature(no_core, lang_items, rustc_attrs, repr_simd, asm_experimental_arch)] +#![feature(no_core, asm_experimental_arch)] #![crate_type = "rlib"] #![no_core] #![allow(asm_sub_register, non_camel_case_types)] -#[rustc_builtin_macro] -macro_rules! asm { - () => {}; -} -#[rustc_builtin_macro] -macro_rules! concat { - () => {}; -} -#[rustc_builtin_macro] -macro_rules! stringify { - () => {}; -} - -#[lang = "sized"] -trait Sized {} -#[lang = "copy"] -trait Copy {} +extern crate minicore; +use minicore::*; type ptr = *const u64; -impl Copy for i8 {} -impl Copy for i16 {} -impl Copy for i32 {} -impl Copy for i64 {} -impl Copy for ptr {} - macro_rules! check { ($func:ident $ty:ident $class:ident) => { #[no_mangle] diff --git a/tests/assembly/asm/hexagon-types.rs b/tests/assembly/asm/hexagon-types.rs index 9389fcf9cbac..ce80fa75b359 100644 --- a/tests/assembly/asm/hexagon-types.rs +++ b/tests/assembly/asm/hexagon-types.rs @@ -1,38 +1,19 @@ +//@ add-core-stubs //@ assembly-output: emit-asm //@ compile-flags: --target hexagon-unknown-linux-musl //@ compile-flags: -Zmerge-functions=disabled //@ needs-llvm-components: hexagon -#![feature(no_core, lang_items, rustc_attrs, repr_simd, asm_experimental_arch)] +#![feature(no_core, asm_experimental_arch)] #![crate_type = "rlib"] #![no_core] #![allow(asm_sub_register, non_camel_case_types)] -#[rustc_builtin_macro] -macro_rules! asm { - () => {}; -} -#[rustc_builtin_macro] -macro_rules! concat { - () => {}; -} -#[rustc_builtin_macro] -macro_rules! stringify { - () => {}; -} - -#[lang = "sized"] -trait Sized {} -#[lang = "copy"] -trait Copy {} +extern crate minicore; +use minicore::*; type ptr = *const i32; -impl Copy for i8 {} -impl Copy for i16 {} -impl Copy for i32 {} -impl Copy for f32 {} -impl Copy for ptr {} extern "C" { fn extern_func(); static extern_static: u8; diff --git a/tests/assembly/asm/loongarch-type.rs b/tests/assembly/asm/loongarch-type.rs index c51d35876d92..86d9e03bc931 100644 --- a/tests/assembly/asm/loongarch-type.rs +++ b/tests/assembly/asm/loongarch-type.rs @@ -1,40 +1,19 @@ +//@ add-core-stubs //@ assembly-output: emit-asm //@ compile-flags: --target loongarch64-unknown-linux-gnu //@ compile-flags: -Zmerge-functions=disabled //@ needs-llvm-components: loongarch -#![feature(no_core, lang_items, rustc_attrs)] +#![feature(no_core)] #![crate_type = "rlib"] #![no_core] #![allow(asm_sub_register, non_camel_case_types)] -#[rustc_builtin_macro] -macro_rules! asm { - () => {}; -} -#[rustc_builtin_macro] -macro_rules! concat { - () => {}; -} -#[rustc_builtin_macro] -macro_rules! stringify { - () => {}; -} - -#[lang = "sized"] -trait Sized {} -#[lang = "copy"] -trait Copy {} +extern crate minicore; +use minicore::*; type ptr = *const i32; -impl Copy for i8 {} -impl Copy for i16 {} -impl Copy for i32 {} -impl Copy for i64 {} -impl Copy for f32 {} -impl Copy for f64 {} -impl Copy for ptr {} extern "C" { fn extern_func(); static extern_static: u8; diff --git a/tests/assembly/asm/m68k-types.rs b/tests/assembly/asm/m68k-types.rs index b3e86b709c3d..9e4f6d9a1a9d 100644 --- a/tests/assembly/asm/m68k-types.rs +++ b/tests/assembly/asm/m68k-types.rs @@ -1,34 +1,18 @@ +//@ add-core-stubs //@ assembly-output: emit-asm //@ compile-flags: --target m68k-unknown-linux-gnu //@ needs-llvm-components: m68k -#![feature(no_core, lang_items, rustc_attrs, asm_experimental_arch)] +#![feature(no_core, asm_experimental_arch)] #![crate_type = "rlib"] #![no_core] #![allow(non_camel_case_types)] -#[rustc_builtin_macro] -macro_rules! asm { - () => {}; -} -#[rustc_builtin_macro] -macro_rules! concat { - () => {}; -} - -#[lang = "sized"] -trait Sized {} -#[lang = "copy"] -trait Copy {} +extern crate minicore; +use minicore::*; type ptr = *const u64; -impl Copy for i8 {} -impl Copy for i16 {} -impl Copy for i32 {} -impl Copy for i64 {} -impl Copy for ptr {} - macro_rules! check { ($func:ident $ty:ident $class:ident $mov:literal) => { #[no_mangle] diff --git a/tests/assembly/asm/mips-types.rs b/tests/assembly/asm/mips-types.rs index f40a28be4a7e..00e8ce0b874a 100644 --- a/tests/assembly/asm/mips-types.rs +++ b/tests/assembly/asm/mips-types.rs @@ -1,3 +1,4 @@ +//@ add-core-stubs //@ revisions: mips32 mips64 //@ assembly-output: emit-asm //@[mips32] compile-flags: --target mips-unknown-linux-gnu @@ -6,39 +7,16 @@ //@[mips64] needs-llvm-components: mips //@ compile-flags: -Zmerge-functions=disabled -#![feature(no_core, lang_items, rustc_attrs, repr_simd, asm_experimental_arch)] +#![feature(no_core, asm_experimental_arch)] #![crate_type = "rlib"] #![no_core] #![allow(asm_sub_register, non_camel_case_types)] -#[rustc_builtin_macro] -macro_rules! asm { - () => {}; -} -#[rustc_builtin_macro] -macro_rules! concat { - () => {}; -} -#[rustc_builtin_macro] -macro_rules! stringify { - () => {}; -} - -#[lang = "sized"] -trait Sized {} -#[lang = "copy"] -trait Copy {} +extern crate minicore; +use minicore::*; type ptr = *const i32; -impl Copy for i8 {} -impl Copy for u8 {} -impl Copy for i16 {} -impl Copy for i32 {} -impl Copy for i64 {} -impl Copy for f32 {} -impl Copy for f64 {} -impl Copy for ptr {} extern "C" { fn extern_func(); static extern_static: u8; diff --git a/tests/assembly/asm/msp430-types.rs b/tests/assembly/asm/msp430-types.rs index ae09b8b070da..442dc77999f5 100644 --- a/tests/assembly/asm/msp430-types.rs +++ b/tests/assembly/asm/msp430-types.rs @@ -1,34 +1,18 @@ +//@ add-core-stubs //@ assembly-output: emit-asm //@ compile-flags: --target msp430-none-elf //@ needs-llvm-components: msp430 -#![feature(no_core, lang_items, rustc_attrs, asm_experimental_arch)] +#![feature(no_core, asm_experimental_arch)] #![crate_type = "rlib"] #![no_core] #![allow(non_camel_case_types)] -#[rustc_builtin_macro] -macro_rules! asm { - () => {}; -} -#[rustc_builtin_macro] -macro_rules! concat { - () => {}; -} - -#[lang = "sized"] -trait Sized {} -#[lang = "copy"] -trait Copy {} +extern crate minicore; +use minicore::*; type ptr = *const i16; -impl Copy for i8 {} -impl Copy for i16 {} -impl Copy for i32 {} -impl Copy for i64 {} -impl Copy for ptr {} - macro_rules! check { ($func:ident $ty:ident $class:ident) => { #[no_mangle] diff --git a/tests/assembly/asm/nvptx-types.rs b/tests/assembly/asm/nvptx-types.rs index 0dd3162b4c02..7e8ebd03024e 100644 --- a/tests/assembly/asm/nvptx-types.rs +++ b/tests/assembly/asm/nvptx-types.rs @@ -1,35 +1,17 @@ +//@ add-core-stubs //@ assembly-output: emit-asm //@ compile-flags: --target nvptx64-nvidia-cuda -//@ compile-flags: --crate-type cdylib //@ needs-llvm-components: nvptx -#![feature(no_core, lang_items, rustc_attrs, asm_experimental_arch)] +#![feature(no_core, asm_experimental_arch)] +#![crate_type = "rlib"] #![no_core] -#[rustc_builtin_macro] -macro_rules! asm { - () => {}; -} -#[rustc_builtin_macro] -macro_rules! concat { - () => {}; -} - -#[lang = "sized"] -trait Sized {} -#[lang = "copy"] -trait Copy {} +extern crate minicore; +use minicore::*; type ptr = *mut u8; -impl Copy for i8 {} -impl Copy for i16 {} -impl Copy for i32 {} -impl Copy for f32 {} -impl Copy for i64 {} -impl Copy for f64 {} -impl Copy for ptr {} - // NVPTX does not support static variables #[no_mangle] fn extern_func() {} diff --git a/tests/assembly/asm/powerpc-types.rs b/tests/assembly/asm/powerpc-types.rs index aa35c4d88658..4291e4c02f3b 100644 --- a/tests/assembly/asm/powerpc-types.rs +++ b/tests/assembly/asm/powerpc-types.rs @@ -1,3 +1,4 @@ +//@ add-core-stubs //@ revisions: powerpc powerpc_altivec powerpc_vsx powerpc64 powerpc64_vsx //@ assembly-output: emit-asm //@[powerpc] compile-flags: --target powerpc-unknown-linux-gnu @@ -12,11 +13,14 @@ //@[powerpc64_vsx] needs-llvm-components: powerpc //@ compile-flags: -Zmerge-functions=disabled -#![feature(no_core, lang_items, rustc_attrs, repr_simd, asm_experimental_arch)] +#![feature(no_core, repr_simd, asm_experimental_arch)] #![crate_type = "rlib"] #![no_core] #![allow(asm_sub_register, non_camel_case_types)] +extern crate minicore; +use minicore::*; + #[cfg_attr(altivec, cfg(not(target_feature = "altivec")))] #[cfg_attr(not(altivec), cfg(target_feature = "altivec"))] compile_error!("altivec cfg and target feature mismatch"); @@ -24,26 +28,6 @@ compile_error!("altivec cfg and target feature mismatch"); #[cfg_attr(not(vsx), cfg(target_feature = "vsx"))] compile_error!("vsx cfg and target feature mismatch"); -#[rustc_builtin_macro] -macro_rules! asm { - () => {}; -} -#[rustc_builtin_macro] -macro_rules! concat { - () => {}; -} -#[rustc_builtin_macro] -macro_rules! stringify { - () => {}; -} - -#[lang = "sized"] -trait Sized {} -#[lang = "copy"] -trait Copy {} - -impl Copy for [T; N] {} - type ptr = *const i32; #[repr(simd)] @@ -59,14 +43,6 @@ pub struct f32x4([f32; 4]); #[repr(simd)] pub struct f64x2([f64; 2]); -impl Copy for i8 {} -impl Copy for u8 {} -impl Copy for i16 {} -impl Copy for i32 {} -impl Copy for i64 {} -impl Copy for f32 {} -impl Copy for f64 {} -impl Copy for ptr {} impl Copy for i8x16 {} impl Copy for i16x8 {} impl Copy for i32x4 {} diff --git a/tests/assembly/asm/riscv-types.rs b/tests/assembly/asm/riscv-types.rs index 1f5d7d85b0ad..724aa154da8c 100644 --- a/tests/assembly/asm/riscv-types.rs +++ b/tests/assembly/asm/riscv-types.rs @@ -1,3 +1,4 @@ +//@ add-core-stubs //@ revisions: riscv64 riscv32 riscv64-zfhmin riscv32-zfhmin riscv64-zfh riscv32-zfh //@ assembly-output: emit-asm @@ -29,40 +30,16 @@ //@ compile-flags: -C target-feature=+d //@ compile-flags: -Zmerge-functions=disabled -#![feature(no_core, lang_items, rustc_attrs, f16)] +#![feature(no_core, f16)] #![crate_type = "rlib"] #![no_core] #![allow(asm_sub_register)] -#[rustc_builtin_macro] -macro_rules! asm { - () => {}; -} -#[rustc_builtin_macro] -macro_rules! concat { - () => {}; -} -#[rustc_builtin_macro] -macro_rules! stringify { - () => {}; -} - -#[lang = "sized"] -trait Sized {} -#[lang = "copy"] -trait Copy {} +extern crate minicore; +use minicore::*; type ptr = *mut u8; -impl Copy for i8 {} -impl Copy for i16 {} -impl Copy for f16 {} -impl Copy for i32 {} -impl Copy for f32 {} -impl Copy for i64 {} -impl Copy for f64 {} -impl Copy for ptr {} - extern "C" { fn extern_func(); static extern_static: u8; diff --git a/tests/assembly/asm/s390x-types.rs b/tests/assembly/asm/s390x-types.rs index 3da22d6c77b6..e6fe38ecb0df 100644 --- a/tests/assembly/asm/s390x-types.rs +++ b/tests/assembly/asm/s390x-types.rs @@ -1,3 +1,4 @@ +//@ add-core-stubs //@ revisions: s390x s390x_vector //@ assembly-output: emit-asm //@[s390x] compile-flags: --target s390x-unknown-linux-gnu @@ -6,31 +7,14 @@ //@[s390x_vector] needs-llvm-components: systemz //@ compile-flags: -Zmerge-functions=disabled -#![feature(no_core, lang_items, rustc_attrs, repr_simd, f128)] +#![feature(no_core, repr_simd, f128)] #![cfg_attr(s390x_vector, feature(asm_experimental_reg))] #![crate_type = "rlib"] #![no_core] #![allow(asm_sub_register, non_camel_case_types)] -#[rustc_builtin_macro] -macro_rules! asm { - () => {}; -} -#[rustc_builtin_macro] -macro_rules! concat { - () => {}; -} -#[rustc_builtin_macro] -macro_rules! stringify { - () => {}; -} - -#[lang = "sized"] -trait Sized {} -#[lang = "copy"] -trait Copy {} - -impl Copy for [T; N] {} +extern crate minicore; +use minicore::*; type ptr = *const i32; @@ -47,16 +31,6 @@ pub struct f32x4([f32; 4]); #[repr(simd)] pub struct f64x2([f64; 2]); -impl Copy for i8 {} -impl Copy for u8 {} -impl Copy for i16 {} -impl Copy for i32 {} -impl Copy for i64 {} -impl Copy for i128 {} -impl Copy for f32 {} -impl Copy for f64 {} -impl Copy for f128 {} -impl Copy for ptr {} impl Copy for i8x16 {} impl Copy for i16x8 {} impl Copy for i32x4 {} diff --git a/tests/assembly/asm/sparc-types.rs b/tests/assembly/asm/sparc-types.rs index 2270679e837e..49cc377cd952 100644 --- a/tests/assembly/asm/sparc-types.rs +++ b/tests/assembly/asm/sparc-types.rs @@ -1,3 +1,4 @@ +//@ add-core-stubs //@ revisions: sparc sparcv8plus sparc64 //@ assembly-output: emit-asm //@[sparc] compile-flags: --target sparc-unknown-none-elf @@ -8,40 +9,16 @@ //@[sparc64] needs-llvm-components: sparc //@ compile-flags: -Zmerge-functions=disabled -#![feature(no_core, lang_items, rustc_attrs, repr_simd, asm_experimental_arch)] +#![feature(no_core, asm_experimental_arch)] #![crate_type = "rlib"] #![no_core] #![allow(asm_sub_register, non_camel_case_types)] -#[rustc_builtin_macro] -macro_rules! asm { - () => {}; -} -#[rustc_builtin_macro] -macro_rules! concat { - () => {}; -} -#[rustc_builtin_macro] -macro_rules! stringify { - () => {}; -} - -#[lang = "sized"] -trait Sized {} -#[lang = "copy"] -trait Copy {} +extern crate minicore; +use minicore::*; type ptr = *const i32; -impl Copy for i8 {} -impl Copy for u8 {} -impl Copy for i16 {} -impl Copy for i32 {} -impl Copy for i64 {} -impl Copy for f32 {} -impl Copy for f64 {} -impl Copy for ptr {} - extern "C" { fn extern_func(); static extern_static: u8; diff --git a/tests/assembly/asm/wasm-types.rs b/tests/assembly/asm/wasm-types.rs index fe5ce836bc6e..78e555c53173 100644 --- a/tests/assembly/asm/wasm-types.rs +++ b/tests/assembly/asm/wasm-types.rs @@ -1,35 +1,17 @@ +//@ add-core-stubs //@ assembly-output: emit-asm //@ compile-flags: --target wasm32-unknown-unknown -//@ compile-flags: --crate-type cdylib //@ needs-llvm-components: webassembly -#![feature(no_core, lang_items, rustc_attrs, asm_experimental_arch)] +#![feature(no_core, asm_experimental_arch)] +#![crate_type = "rlib"] #![no_core] -#[rustc_builtin_macro] -macro_rules! asm { - () => {}; -} -#[rustc_builtin_macro] -macro_rules! concat { - () => {}; -} - -#[lang = "sized"] -trait Sized {} -#[lang = "copy"] -trait Copy {} +extern crate minicore; +use minicore::*; type ptr = *mut u8; -impl Copy for i8 {} -impl Copy for i16 {} -impl Copy for i32 {} -impl Copy for f32 {} -impl Copy for i64 {} -impl Copy for f64 {} -impl Copy for ptr {} - extern "C" { fn extern_func(); static extern_static: u8; diff --git a/tests/assembly/asm/x86-modifiers.rs b/tests/assembly/asm/x86-modifiers.rs index 5a48af9205f7..53e4b92f84ac 100644 --- a/tests/assembly/asm/x86-modifiers.rs +++ b/tests/assembly/asm/x86-modifiers.rs @@ -1,3 +1,4 @@ +//@ add-core-stubs //@ revisions: x86_64 i686 //@ assembly-output: emit-asm //@ compile-flags: -O -C panic=abort @@ -9,30 +10,13 @@ //@ compile-flags: -C target-feature=+avx512bw //@ compile-flags: -Zmerge-functions=disabled -#![feature(no_core, lang_items, rustc_attrs)] +#![feature(no_core)] #![crate_type = "rlib"] #![no_core] #![allow(asm_sub_register)] -#[rustc_builtin_macro] -macro_rules! asm { - () => {}; -} -#[rustc_builtin_macro] -macro_rules! concat { - () => {}; -} -#[rustc_builtin_macro] -macro_rules! stringify { - () => {}; -} - -#[lang = "sized"] -trait Sized {} -#[lang = "copy"] -trait Copy {} - -impl Copy for i32 {} +extern crate minicore; +use minicore::*; macro_rules! check { ($func:ident $modifier:literal $reg:ident $mov:literal) => { diff --git a/tests/assembly/asm/x86-types.rs b/tests/assembly/asm/x86-types.rs index 567dc7a8245f..6120ed0d5327 100644 --- a/tests/assembly/asm/x86-types.rs +++ b/tests/assembly/asm/x86-types.rs @@ -1,3 +1,4 @@ +//@ add-core-stubs //@ revisions: x86_64 i686 //@ assembly-output: emit-asm //@[x86_64] compile-flags: --target x86_64-unknown-linux-gnu @@ -8,31 +9,13 @@ //@ compile-flags: -C target-feature=+avx512bw //@ compile-flags: -Zmerge-functions=disabled -#![feature(no_core, lang_items, rustc_attrs, repr_simd, f16, f128)] +#![feature(no_core, repr_simd, f16, f128)] #![crate_type = "rlib"] #![no_core] #![allow(asm_sub_register, non_camel_case_types)] -#[rustc_builtin_macro] -macro_rules! asm { - () => {}; -} -#[rustc_builtin_macro] -macro_rules! concat { - () => {}; -} -#[rustc_builtin_macro] -macro_rules! stringify { - () => {}; -} - -#[lang = "sized"] -trait Sized {} -#[lang = "copy"] -trait Copy {} - -// Do we really need to use no_core for this?!? -impl Copy for [T; N] {} +extern crate minicore; +use minicore::*; type ptr = *mut u8; @@ -90,7 +73,6 @@ macro_rules! impl_copy { } impl_copy!( - i8 i16 f16 i32 f32 i64 f64 f128 ptr i8x16 i16x8 i32x4 i64x2 f16x8 f32x4 f64x2 i8x32 i16x16 i32x8 i64x4 f16x16 f32x8 f64x4 i8x64 i16x32 i32x16 i64x8 f16x32 f32x16 f64x8 diff --git a/tests/auxiliary/minicore.rs b/tests/auxiliary/minicore.rs index 2fa0c550efbc..a68552175c31 100644 --- a/tests/auxiliary/minicore.rs +++ b/tests/auxiliary/minicore.rs @@ -14,7 +14,7 @@ //! . // ignore-tidy-linelength -#![feature(no_core, lang_items, rustc_attrs, decl_macro, naked_functions)] +#![feature(no_core, lang_items, rustc_attrs, decl_macro, naked_functions, f16, f128)] #![allow(unused, improper_ctypes_definitions, internal_features)] #![feature(asm_experimental_arch)] #![no_std] @@ -40,7 +40,12 @@ impl LegacyReceiver for &mut T {} pub trait Copy: Sized {} impl_marker_trait!( - Copy => [ bool, char, isize, usize, i8, i16, i32, i64, u8, u16, u32, u64, f32, f64 ] + Copy => [ + bool, char, + isize, i8, i16, i32, i64, i128, + usize, u8, u16, u32, u64, u128, + f16, f32, f64, f128, + ] ); impl<'a, T: ?Sized> Copy for &'a T {} impl Copy for *const T {} @@ -88,3 +93,18 @@ pub macro naked_asm("assembly template", $(operands,)* $(options($(option),*))?) pub macro global_asm("assembly template", $(operands,)* $(options($(option),*))?) { /* compiler built-in */ } + +#[rustc_builtin_macro] +#[macro_export] +macro_rules! concat { + ($($e:expr),* $(,)?) => { + /* compiler built-in */ + }; +} +#[rustc_builtin_macro] +#[macro_export] +macro_rules! stringify { + ($($t:tt)*) => { + /* compiler built-in */ + }; +} From a676872e0ff6d00d72f322807e6214daec9f5112 Mon Sep 17 00:00:00 2001 From: dianne Date: Mon, 16 Dec 2024 09:51:15 -0800 Subject: [PATCH 21/92] Clarify the match ergonomics 2024 migration lint's output --- compiler/rustc_hir_typeck/src/pat.rs | 69 +++++-- .../rustc_middle/src/ty/typeck_results.rs | 13 +- compiler/rustc_mir_build/messages.ftl | 2 +- compiler/rustc_mir_build/src/errors.rs | 28 ++- .../rustc_mir_build/src/thir/pattern/mod.rs | 25 ++- .../migration_lint.fixed | 32 +-- .../migration_lint.rs | 32 +-- .../migration_lint.stderr | 184 ++++++++++-------- .../min_match_ergonomics_fail.rs | 14 +- .../min_match_ergonomics_fail.stderr | 91 +++++---- 10 files changed, 301 insertions(+), 189 deletions(-) diff --git a/compiler/rustc_hir_typeck/src/pat.rs b/compiler/rustc_hir_typeck/src/pat.rs index e7726845652f..f20db5c65019 100644 --- a/compiler/rustc_hir_typeck/src/pat.rs +++ b/compiler/rustc_hir_typeck/src/pat.rs @@ -718,12 +718,12 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { BindingMode(def_br, Mutability::Mut) } else { // `mut` resets the binding mode on edition <= 2021 - *self - .typeck_results - .borrow_mut() - .rust_2024_migration_desugared_pats_mut() - .entry(pat_info.top_info.hir_id) - .or_default() |= pat.span.at_least_rust_2024(); + self.add_rust_2024_migration_desugared_pat( + pat_info.top_info.hir_id, + pat.span, + ident.span, + "requires binding by-value, but the implicit default is by-reference", + ); BindingMode(ByRef::No, Mutability::Mut) } } @@ -731,12 +731,12 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { BindingMode(ByRef::Yes(_), _) => { if matches!(def_br, ByRef::Yes(_)) { // `ref`/`ref mut` overrides the binding mode on edition <= 2021 - *self - .typeck_results - .borrow_mut() - .rust_2024_migration_desugared_pats_mut() - .entry(pat_info.top_info.hir_id) - .or_default() |= pat.span.at_least_rust_2024(); + self.add_rust_2024_migration_desugared_pat( + pat_info.top_info.hir_id, + pat.span, + ident.span, + "cannot override to bind by-reference when that is the implicit default", + ); } user_bind_annot } @@ -2266,12 +2266,12 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { // Reset binding mode on old editions if pat_info.binding_mode != ByRef::No { pat_info.binding_mode = ByRef::No; - *self - .typeck_results - .borrow_mut() - .rust_2024_migration_desugared_pats_mut() - .entry(pat_info.top_info.hir_id) - .or_default() |= pat.span.at_least_rust_2024(); + self.add_rust_2024_migration_desugared_pat( + pat_info.top_info.hir_id, + pat.span, + inner.span, + "cannot implicitly match against multiple layers of reference", + ) } } @@ -2630,4 +2630,37 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { _ => (false, ty), } } + + /// Record a pattern that's invalid under Rust 2024 match ergonomics, along with a problematic + /// span, so that the pattern migration lint can desugar it during THIR construction. + fn add_rust_2024_migration_desugared_pat( + &self, + pat_id: HirId, + subpat_span: Span, + cutoff_span: Span, + detailed_label: &str, + ) { + // Try to trim the span we're labeling to just the `&` or binding mode that's an issue. + // If the subpattern span is a macro call site, no trimming will be done. + let source_map = self.tcx.sess.source_map(); + let cutoff_span = source_map + .span_extend_prev_while(cutoff_span, char::is_whitespace) + .unwrap_or(cutoff_span); + let trimmed_span = subpat_span.until(cutoff_span); + + // Only provide a detailed label if the problematic subpattern isn't from an expansion. + // In the case that it's from a macro, we'll add a more detailed note in the emitter. + let desc = if subpat_span.from_expansion() { + "default binding mode is reset within expansion" + } else { + detailed_label + }; + + self.typeck_results + .borrow_mut() + .rust_2024_migration_desugared_pats_mut() + .entry(pat_id) + .or_default() + .push((trimmed_span, desc.to_owned())); + } } diff --git a/compiler/rustc_middle/src/ty/typeck_results.rs b/compiler/rustc_middle/src/ty/typeck_results.rs index 551c113aa592..f94f52e4f618 100644 --- a/compiler/rustc_middle/src/ty/typeck_results.rs +++ b/compiler/rustc_middle/src/ty/typeck_results.rs @@ -74,9 +74,8 @@ pub struct TypeckResults<'tcx> { pat_binding_modes: ItemLocalMap, /// Top-level patterns whose match ergonomics need to be desugared by the Rust 2021 -> 2024 - /// migration lint. The boolean indicates whether the emitted diagnostic should be a hard error - /// (if any of the incompatible pattern elements are in edition 2024). - rust_2024_migration_desugared_pats: ItemLocalMap, + /// migration lint. Problematic subpatterns are stored in the `Vec` for the lint to highlight. + rust_2024_migration_desugared_pats: ItemLocalMap>, /// Stores the types which were implicitly dereferenced in pattern binding modes /// for later usage in THIR lowering. For example, @@ -419,14 +418,18 @@ impl<'tcx> TypeckResults<'tcx> { LocalTableInContextMut { hir_owner: self.hir_owner, data: &mut self.pat_adjustments } } - pub fn rust_2024_migration_desugared_pats(&self) -> LocalTableInContext<'_, bool> { + pub fn rust_2024_migration_desugared_pats( + &self, + ) -> LocalTableInContext<'_, Vec<(Span, String)>> { LocalTableInContext { hir_owner: self.hir_owner, data: &self.rust_2024_migration_desugared_pats, } } - pub fn rust_2024_migration_desugared_pats_mut(&mut self) -> LocalTableInContextMut<'_, bool> { + pub fn rust_2024_migration_desugared_pats_mut( + &mut self, + ) -> LocalTableInContextMut<'_, Vec<(Span, String)>> { LocalTableInContextMut { hir_owner: self.hir_owner, data: &mut self.rust_2024_migration_desugared_pats, diff --git a/compiler/rustc_mir_build/messages.ftl b/compiler/rustc_mir_build/messages.ftl index f647486f62ad..f7f55821d4b6 100644 --- a/compiler/rustc_mir_build/messages.ftl +++ b/compiler/rustc_mir_build/messages.ftl @@ -285,7 +285,7 @@ mir_build_pointer_pattern = function pointers and raw pointers not derived from mir_build_privately_uninhabited = pattern `{$witness_1}` is currently uninhabited, but this variant contains private fields which may become inhabited in the future -mir_build_rust_2024_incompatible_pat = patterns are not allowed to reset the default binding mode in edition 2024 +mir_build_rust_2024_incompatible_pat = pattern uses features incompatible with edition 2024 mir_build_rustc_box_attribute_error = `#[rustc_box]` attribute used incorrectly .attributes = no other attributes may be applied diff --git a/compiler/rustc_mir_build/src/errors.rs b/compiler/rustc_mir_build/src/errors.rs index 3632da943e18..fac0db7d2f7f 100644 --- a/compiler/rustc_mir_build/src/errors.rs +++ b/compiler/rustc_mir_build/src/errors.rs @@ -1,7 +1,7 @@ use rustc_errors::codes::*; use rustc_errors::{ Applicability, Diag, DiagArgValue, DiagCtxtHandle, Diagnostic, EmissionGuarantee, Level, - MultiSpan, SubdiagMessageOp, Subdiagnostic, + MultiSpan, SubdiagMessageOp, Subdiagnostic, pluralize, }; use rustc_macros::{Diagnostic, LintDiagnostic, Subdiagnostic}; use rustc_middle::ty::{self, Ty}; @@ -1089,18 +1089,20 @@ pub(crate) enum RustcBoxAttrReason { #[derive(LintDiagnostic)] #[diag(mir_build_rust_2024_incompatible_pat)] -pub(crate) struct Rust2024IncompatiblePat { +pub(crate) struct Rust2024IncompatiblePat<'a> { #[subdiagnostic] - pub(crate) sugg: Rust2024IncompatiblePatSugg, + pub(crate) sugg: Rust2024IncompatiblePatSugg<'a>, } -pub(crate) struct Rust2024IncompatiblePatSugg { +pub(crate) struct Rust2024IncompatiblePatSugg<'a> { pub(crate) suggestion: Vec<(Span, String)>, - /// Whether the incompatibility is a hard error because a relevant span is in edition 2024. - pub(crate) is_hard_error: bool, + pub(crate) ref_pattern_count: usize, + pub(crate) binding_mode_count: usize, + /// Labeled spans for subpatterns invalid in Rust 2024. + pub(crate) labels: &'a [(Span, String)], } -impl Subdiagnostic for Rust2024IncompatiblePatSugg { +impl<'a> Subdiagnostic for Rust2024IncompatiblePatSugg<'a> { fn add_to_diag_with>( self, diag: &mut Diag<'_, G>, @@ -1112,6 +1114,16 @@ impl Subdiagnostic for Rust2024IncompatiblePatSugg { } else { Applicability::MaybeIncorrect }; - diag.multipart_suggestion("desugar the match ergonomics", self.suggestion, applicability); + let plural_derefs = pluralize!(self.ref_pattern_count); + let and_modes = if self.binding_mode_count > 0 { + format!(" and variable binding mode{}", pluralize!(self.binding_mode_count)) + } else { + String::new() + }; + diag.multipart_suggestion_verbose( + format!("make the implied reference pattern{plural_derefs}{and_modes} explicit"), + self.suggestion, + applicability, + ); } } diff --git a/compiler/rustc_mir_build/src/thir/pattern/mod.rs b/compiler/rustc_mir_build/src/thir/pattern/mod.rs index 2dbc8b7b5738..62bbb31440f8 100644 --- a/compiler/rustc_mir_build/src/thir/pattern/mod.rs +++ b/compiler/rustc_mir_build/src/thir/pattern/mod.rs @@ -6,6 +6,7 @@ mod const_to_pat; use std::cmp::Ordering; use rustc_abi::{FieldIdx, Integer}; +use rustc_errors::MultiSpan; use rustc_errors::codes::*; use rustc_hir::def::{CtorOf, DefKind, Res}; use rustc_hir::pat_util::EnumerateAndAdjustIterator; @@ -34,7 +35,7 @@ struct PatCtxt<'a, 'tcx> { typeck_results: &'a ty::TypeckResults<'tcx>, /// Used by the Rust 2024 migration lint. - rust_2024_migration_suggestion: Option, + rust_2024_migration_suggestion: Option>, } pub(super) fn pat_from_hir<'a, 'tcx>( @@ -50,24 +51,32 @@ pub(super) fn pat_from_hir<'a, 'tcx>( rust_2024_migration_suggestion: typeck_results .rust_2024_migration_desugared_pats() .get(pat.hir_id) - .map(|&is_hard_error| Rust2024IncompatiblePatSugg { + .map(|labels| Rust2024IncompatiblePatSugg { suggestion: Vec::new(), - is_hard_error, + ref_pattern_count: 0, + binding_mode_count: 0, + labels: labels.as_slice(), }), }; let result = pcx.lower_pattern(pat); debug!("pat_from_hir({:?}) = {:?}", pat, result); if let Some(sugg) = pcx.rust_2024_migration_suggestion { - if sugg.is_hard_error { + let mut spans = MultiSpan::from_spans(sugg.labels.iter().map(|(span, _)| *span).collect()); + for (span, label) in sugg.labels { + spans.push_span_label(*span, label.clone()); + } + // If a relevant span is from at least edition 2024, this is a hard error. + let is_hard_error = spans.primary_spans().iter().any(|span| span.at_least_rust_2024()); + if is_hard_error { let mut err = - tcx.dcx().struct_span_err(pat.span, fluent::mir_build_rust_2024_incompatible_pat); + tcx.dcx().struct_span_err(spans, fluent::mir_build_rust_2024_incompatible_pat); err.subdiagnostic(sugg); err.emit(); } else { tcx.emit_node_span_lint( lint::builtin::RUST_2024_INCOMPATIBLE_PAT, pat.hir_id, - pat.span, + spans, Rust2024IncompatiblePat { sugg }, ); } @@ -133,6 +142,7 @@ impl<'a, 'tcx> PatCtxt<'a, 'tcx> { }) .collect(); s.suggestion.push((pat.span.shrink_to_lo(), suggestion_str)); + s.ref_pattern_count += adjustments.len(); }; adjusted_pat @@ -371,7 +381,8 @@ impl<'a, 'tcx> PatCtxt<'a, 'tcx> { s.suggestion.push(( pat.span.with_lo(ident.span.lo()).shrink_to_lo(), sugg_str.to_owned(), - )) + )); + s.binding_mode_count += 1; } // A ref x pattern is the same node used for x, and as such it has diff --git a/tests/ui/pattern/rfc-3627-match-ergonomics-2024/migration_lint.fixed b/tests/ui/pattern/rfc-3627-match-ergonomics-2024/migration_lint.fixed index 086671e69cba..63e82eab8fb3 100644 --- a/tests/ui/pattern/rfc-3627-match-ergonomics-2024/migration_lint.fixed +++ b/tests/ui/pattern/rfc-3627-match-ergonomics-2024/migration_lint.fixed @@ -23,22 +23,22 @@ fn main() { assert_type_eq(x, &mut 0u8); let &Foo(mut x) = &Foo(0); - //~^ ERROR: patterns are not allowed to reset the default binding mode + //~^ ERROR: pattern uses features incompatible with edition 2024 //~| WARN: this changes meaning in Rust 2024 assert_type_eq(x, 0u8); let &mut Foo(mut x) = &mut Foo(0); - //~^ ERROR: patterns are not allowed to reset the default binding mode + //~^ ERROR: pattern uses features incompatible with edition 2024 //~| WARN: this changes meaning in Rust 2024 assert_type_eq(x, 0u8); let &Foo(ref x) = &Foo(0); - //~^ ERROR: patterns are not allowed to reset the default binding mode + //~^ ERROR: pattern uses features incompatible with edition 2024 //~| WARN: this changes meaning in Rust 2024 assert_type_eq(x, &0u8); let &mut Foo(ref x) = &mut Foo(0); - //~^ ERROR: patterns are not allowed to reset the default binding mode + //~^ ERROR: pattern uses features incompatible with edition 2024 //~| WARN: this changes meaning in Rust 2024 assert_type_eq(x, &0u8); @@ -55,22 +55,22 @@ fn main() { assert_type_eq(x, &0u8); let &Foo(&x) = &Foo(&0); - //~^ ERROR: patterns are not allowed to reset the default binding mode + //~^ ERROR: pattern uses features incompatible with edition 2024 //~| WARN: this changes meaning in Rust 2024 assert_type_eq(x, 0u8); let &Foo(&mut x) = &Foo(&mut 0); - //~^ ERROR: patterns are not allowed to reset the default binding mode + //~^ ERROR: pattern uses features incompatible with edition 2024 //~| WARN: this changes meaning in Rust 2024 assert_type_eq(x, 0u8); let &mut Foo(&x) = &mut Foo(&0); - //~^ ERROR: patterns are not allowed to reset the default binding mode + //~^ ERROR: pattern uses features incompatible with edition 2024 //~| WARN: this changes meaning in Rust 2024 assert_type_eq(x, 0u8); let &mut Foo(&mut x) = &mut Foo(&mut 0); - //~^ ERROR: patterns are not allowed to reset the default binding mode + //~^ ERROR: pattern uses features incompatible with edition 2024 //~| WARN: this changes meaning in Rust 2024 assert_type_eq(x, 0u8); @@ -79,25 +79,25 @@ fn main() { } if let &&&&&Some(&x) = &&&&&Some(&0u8) { - //~^ ERROR: patterns are not allowed to reset the default binding mode + //~^ ERROR: pattern uses features incompatible with edition 2024 //~| WARN: this changes meaning in Rust 2024 assert_type_eq(x, 0u8); } if let &&&&&Some(&mut x) = &&&&&Some(&mut 0u8) { - //~^ ERROR: patterns are not allowed to reset the default binding mode + //~^ ERROR: pattern uses features incompatible with edition 2024 //~| WARN: this changes meaning in Rust 2024 assert_type_eq(x, 0u8); } if let &&&&&mut Some(&x) = &&&&&mut Some(&0u8) { - //~^ ERROR: patterns are not allowed to reset the default binding mode + //~^ ERROR: pattern uses features incompatible with edition 2024 //~| WARN: this changes meaning in Rust 2024 assert_type_eq(x, 0u8); } if let &mut Some(&mut Some(&mut Some(ref mut x))) = &mut Some(&mut Some(&mut Some(0u8))) { - //~^ ERROR: patterns are not allowed to reset the default binding mode + //~^ ERROR: pattern uses features incompatible with edition 2024 //~| WARN: this changes meaning in Rust 2024 assert_type_eq(x, &mut 0u8); } @@ -109,20 +109,20 @@ fn main() { } let &Struct { ref a, mut b, ref c } = &Struct { a: 0, b: 0, c: 0 }; - //~^ ERROR: patterns are not allowed to reset the default binding mode + //~^ ERROR: pattern uses features incompatible with edition 2024 //~| WARN: this changes meaning in Rust 2024 assert_type_eq(a, &0u32); assert_type_eq(b, 0u32); let &Struct { a: &a, ref b, ref c } = &Struct { a: &0, b: &0, c: &0 }; - //~^ ERROR: patterns are not allowed to reset the default binding mode + //~^ ERROR: pattern uses features incompatible with edition 2024 //~| WARN: this changes meaning in Rust 2024 assert_type_eq(a, 0u32); assert_type_eq(b, &&0u32); assert_type_eq(c, &&0u32); if let &Struct { a: &Some(a), b: &Some(&b), c: &Some(ref c) } = - //~^ ERROR: patterns are not allowed to reset the default binding mode + //~^ ERROR: pattern uses features incompatible with edition 2024 //~| WARN: this changes meaning in Rust 2024 &(Struct { a: &Some(&0), b: &Some(&0), c: &Some(&0) }) { @@ -135,7 +135,7 @@ fn main() { // The two patterns are the same syntactically, but because they're defined in different // editions they don't mean the same thing. &(Some(mut x), migration_lint_macros::mixed_edition_pat!(y)) => { - //~^ ERROR: patterns are not allowed to reset the default binding mode + //~^ ERROR: pattern uses features incompatible with edition 2024 assert_type_eq(x, 0u32); assert_type_eq(y, 0u32); } diff --git a/tests/ui/pattern/rfc-3627-match-ergonomics-2024/migration_lint.rs b/tests/ui/pattern/rfc-3627-match-ergonomics-2024/migration_lint.rs index acceafdb7ec0..4234192da519 100644 --- a/tests/ui/pattern/rfc-3627-match-ergonomics-2024/migration_lint.rs +++ b/tests/ui/pattern/rfc-3627-match-ergonomics-2024/migration_lint.rs @@ -23,22 +23,22 @@ fn main() { assert_type_eq(x, &mut 0u8); let Foo(mut x) = &Foo(0); - //~^ ERROR: patterns are not allowed to reset the default binding mode + //~^ ERROR: pattern uses features incompatible with edition 2024 //~| WARN: this changes meaning in Rust 2024 assert_type_eq(x, 0u8); let Foo(mut x) = &mut Foo(0); - //~^ ERROR: patterns are not allowed to reset the default binding mode + //~^ ERROR: pattern uses features incompatible with edition 2024 //~| WARN: this changes meaning in Rust 2024 assert_type_eq(x, 0u8); let Foo(ref x) = &Foo(0); - //~^ ERROR: patterns are not allowed to reset the default binding mode + //~^ ERROR: pattern uses features incompatible with edition 2024 //~| WARN: this changes meaning in Rust 2024 assert_type_eq(x, &0u8); let Foo(ref x) = &mut Foo(0); - //~^ ERROR: patterns are not allowed to reset the default binding mode + //~^ ERROR: pattern uses features incompatible with edition 2024 //~| WARN: this changes meaning in Rust 2024 assert_type_eq(x, &0u8); @@ -55,22 +55,22 @@ fn main() { assert_type_eq(x, &0u8); let Foo(&x) = &Foo(&0); - //~^ ERROR: patterns are not allowed to reset the default binding mode + //~^ ERROR: pattern uses features incompatible with edition 2024 //~| WARN: this changes meaning in Rust 2024 assert_type_eq(x, 0u8); let Foo(&mut x) = &Foo(&mut 0); - //~^ ERROR: patterns are not allowed to reset the default binding mode + //~^ ERROR: pattern uses features incompatible with edition 2024 //~| WARN: this changes meaning in Rust 2024 assert_type_eq(x, 0u8); let Foo(&x) = &mut Foo(&0); - //~^ ERROR: patterns are not allowed to reset the default binding mode + //~^ ERROR: pattern uses features incompatible with edition 2024 //~| WARN: this changes meaning in Rust 2024 assert_type_eq(x, 0u8); let Foo(&mut x) = &mut Foo(&mut 0); - //~^ ERROR: patterns are not allowed to reset the default binding mode + //~^ ERROR: pattern uses features incompatible with edition 2024 //~| WARN: this changes meaning in Rust 2024 assert_type_eq(x, 0u8); @@ -79,25 +79,25 @@ fn main() { } if let Some(&x) = &&&&&Some(&0u8) { - //~^ ERROR: patterns are not allowed to reset the default binding mode + //~^ ERROR: pattern uses features incompatible with edition 2024 //~| WARN: this changes meaning in Rust 2024 assert_type_eq(x, 0u8); } if let Some(&mut x) = &&&&&Some(&mut 0u8) { - //~^ ERROR: patterns are not allowed to reset the default binding mode + //~^ ERROR: pattern uses features incompatible with edition 2024 //~| WARN: this changes meaning in Rust 2024 assert_type_eq(x, 0u8); } if let Some(&x) = &&&&&mut Some(&0u8) { - //~^ ERROR: patterns are not allowed to reset the default binding mode + //~^ ERROR: pattern uses features incompatible with edition 2024 //~| WARN: this changes meaning in Rust 2024 assert_type_eq(x, 0u8); } if let Some(&mut Some(Some(x))) = &mut Some(&mut Some(&mut Some(0u8))) { - //~^ ERROR: patterns are not allowed to reset the default binding mode + //~^ ERROR: pattern uses features incompatible with edition 2024 //~| WARN: this changes meaning in Rust 2024 assert_type_eq(x, &mut 0u8); } @@ -109,20 +109,20 @@ fn main() { } let Struct { a, mut b, c } = &Struct { a: 0, b: 0, c: 0 }; - //~^ ERROR: patterns are not allowed to reset the default binding mode + //~^ ERROR: pattern uses features incompatible with edition 2024 //~| WARN: this changes meaning in Rust 2024 assert_type_eq(a, &0u32); assert_type_eq(b, 0u32); let Struct { a: &a, b, ref c } = &Struct { a: &0, b: &0, c: &0 }; - //~^ ERROR: patterns are not allowed to reset the default binding mode + //~^ ERROR: pattern uses features incompatible with edition 2024 //~| WARN: this changes meaning in Rust 2024 assert_type_eq(a, 0u32); assert_type_eq(b, &&0u32); assert_type_eq(c, &&0u32); if let Struct { a: &Some(a), b: Some(&b), c: Some(c) } = - //~^ ERROR: patterns are not allowed to reset the default binding mode + //~^ ERROR: pattern uses features incompatible with edition 2024 //~| WARN: this changes meaning in Rust 2024 &(Struct { a: &Some(&0), b: &Some(&0), c: &Some(&0) }) { @@ -135,7 +135,7 @@ fn main() { // The two patterns are the same syntactically, but because they're defined in different // editions they don't mean the same thing. (Some(mut x), migration_lint_macros::mixed_edition_pat!(y)) => { - //~^ ERROR: patterns are not allowed to reset the default binding mode + //~^ ERROR: pattern uses features incompatible with edition 2024 assert_type_eq(x, 0u32); assert_type_eq(y, 0u32); } diff --git a/tests/ui/pattern/rfc-3627-match-ergonomics-2024/migration_lint.stderr b/tests/ui/pattern/rfc-3627-match-ergonomics-2024/migration_lint.stderr index 91aa987c7371..20c88d79e96b 100644 --- a/tests/ui/pattern/rfc-3627-match-ergonomics-2024/migration_lint.stderr +++ b/tests/ui/pattern/rfc-3627-match-ergonomics-2024/migration_lint.stderr @@ -1,10 +1,8 @@ -error: patterns are not allowed to reset the default binding mode in edition 2024 - --> $DIR/migration_lint.rs:25:9 +error: pattern uses features incompatible with edition 2024 + --> $DIR/migration_lint.rs:25:13 | LL | let Foo(mut x) = &Foo(0); - | -^^^^^^^^^ - | | - | help: desugar the match ergonomics: `&` + | ^^^ requires binding by-value, but the implicit default is by-reference | = warning: this changes meaning in Rust 2024 = note: for more information, see @@ -13,176 +11,210 @@ note: the lint level is defined here | LL | #![deny(rust_2024_incompatible_pat)] | ^^^^^^^^^^^^^^^^^^^^^^^^^^ +help: make the implied reference pattern explicit + | +LL | let &Foo(mut x) = &Foo(0); + | + -error: patterns are not allowed to reset the default binding mode in edition 2024 - --> $DIR/migration_lint.rs:30:9 +error: pattern uses features incompatible with edition 2024 + --> $DIR/migration_lint.rs:30:13 | LL | let Foo(mut x) = &mut Foo(0); - | -^^^^^^^^^ - | | - | help: desugar the match ergonomics: `&mut` + | ^^^ requires binding by-value, but the implicit default is by-reference | = warning: this changes meaning in Rust 2024 = note: for more information, see +help: make the implied reference pattern explicit + | +LL | let &mut Foo(mut x) = &mut Foo(0); + | ++++ -error: patterns are not allowed to reset the default binding mode in edition 2024 - --> $DIR/migration_lint.rs:35:9 +error: pattern uses features incompatible with edition 2024 + --> $DIR/migration_lint.rs:35:13 | LL | let Foo(ref x) = &Foo(0); - | -^^^^^^^^^ - | | - | help: desugar the match ergonomics: `&` + | ^^^ cannot override to bind by-reference when that is the implicit default | = warning: this changes meaning in Rust 2024 = note: for more information, see +help: make the implied reference pattern explicit + | +LL | let &Foo(ref x) = &Foo(0); + | + -error: patterns are not allowed to reset the default binding mode in edition 2024 - --> $DIR/migration_lint.rs:40:9 +error: pattern uses features incompatible with edition 2024 + --> $DIR/migration_lint.rs:40:13 | LL | let Foo(ref x) = &mut Foo(0); - | -^^^^^^^^^ - | | - | help: desugar the match ergonomics: `&mut` + | ^^^ cannot override to bind by-reference when that is the implicit default | = warning: this changes meaning in Rust 2024 = note: for more information, see +help: make the implied reference pattern explicit + | +LL | let &mut Foo(ref x) = &mut Foo(0); + | ++++ -error: patterns are not allowed to reset the default binding mode in edition 2024 - --> $DIR/migration_lint.rs:57:9 +error: pattern uses features incompatible with edition 2024 + --> $DIR/migration_lint.rs:57:13 | LL | let Foo(&x) = &Foo(&0); - | -^^^^^^ - | | - | help: desugar the match ergonomics: `&` + | ^ cannot implicitly match against multiple layers of reference | = warning: this changes meaning in Rust 2024 = note: for more information, see +help: make the implied reference pattern explicit + | +LL | let &Foo(&x) = &Foo(&0); + | + -error: patterns are not allowed to reset the default binding mode in edition 2024 - --> $DIR/migration_lint.rs:62:9 +error: pattern uses features incompatible with edition 2024 + --> $DIR/migration_lint.rs:62:13 | LL | let Foo(&mut x) = &Foo(&mut 0); - | -^^^^^^^^^^ - | | - | help: desugar the match ergonomics: `&` + | ^^^^ cannot implicitly match against multiple layers of reference | = warning: this changes meaning in Rust 2024 = note: for more information, see +help: make the implied reference pattern explicit + | +LL | let &Foo(&mut x) = &Foo(&mut 0); + | + -error: patterns are not allowed to reset the default binding mode in edition 2024 - --> $DIR/migration_lint.rs:67:9 +error: pattern uses features incompatible with edition 2024 + --> $DIR/migration_lint.rs:67:13 | LL | let Foo(&x) = &mut Foo(&0); - | -^^^^^^ - | | - | help: desugar the match ergonomics: `&mut` + | ^ cannot implicitly match against multiple layers of reference | = warning: this changes meaning in Rust 2024 = note: for more information, see +help: make the implied reference pattern explicit + | +LL | let &mut Foo(&x) = &mut Foo(&0); + | ++++ -error: patterns are not allowed to reset the default binding mode in edition 2024 - --> $DIR/migration_lint.rs:72:9 +error: pattern uses features incompatible with edition 2024 + --> $DIR/migration_lint.rs:72:13 | LL | let Foo(&mut x) = &mut Foo(&mut 0); - | -^^^^^^^^^^ - | | - | help: desugar the match ergonomics: `&mut` + | ^^^^ cannot implicitly match against multiple layers of reference | = warning: this changes meaning in Rust 2024 = note: for more information, see +help: make the implied reference pattern explicit + | +LL | let &mut Foo(&mut x) = &mut Foo(&mut 0); + | ++++ -error: patterns are not allowed to reset the default binding mode in edition 2024 - --> $DIR/migration_lint.rs:81:12 +error: pattern uses features incompatible with edition 2024 + --> $DIR/migration_lint.rs:81:17 | LL | if let Some(&x) = &&&&&Some(&0u8) { - | -^^^^^^^ - | | - | help: desugar the match ergonomics: `&&&&&` + | ^ cannot implicitly match against multiple layers of reference | = warning: this changes meaning in Rust 2024 = note: for more information, see +help: make the implied reference patterns explicit + | +LL | if let &&&&&Some(&x) = &&&&&Some(&0u8) { + | +++++ -error: patterns are not allowed to reset the default binding mode in edition 2024 - --> $DIR/migration_lint.rs:87:12 +error: pattern uses features incompatible with edition 2024 + --> $DIR/migration_lint.rs:87:17 | LL | if let Some(&mut x) = &&&&&Some(&mut 0u8) { - | -^^^^^^^^^^^ - | | - | help: desugar the match ergonomics: `&&&&&` + | ^^^^ cannot implicitly match against multiple layers of reference | = warning: this changes meaning in Rust 2024 = note: for more information, see +help: make the implied reference patterns explicit + | +LL | if let &&&&&Some(&mut x) = &&&&&Some(&mut 0u8) { + | +++++ -error: patterns are not allowed to reset the default binding mode in edition 2024 - --> $DIR/migration_lint.rs:93:12 +error: pattern uses features incompatible with edition 2024 + --> $DIR/migration_lint.rs:93:17 | LL | if let Some(&x) = &&&&&mut Some(&0u8) { - | -^^^^^^^ - | | - | help: desugar the match ergonomics: `&&&&&mut` + | ^ cannot implicitly match against multiple layers of reference | = warning: this changes meaning in Rust 2024 = note: for more information, see +help: make the implied reference patterns explicit + | +LL | if let &&&&&mut Some(&x) = &&&&&mut Some(&0u8) { + | ++++++++ -error: patterns are not allowed to reset the default binding mode in edition 2024 - --> $DIR/migration_lint.rs:99:12 +error: pattern uses features incompatible with edition 2024 + --> $DIR/migration_lint.rs:99:17 | LL | if let Some(&mut Some(Some(x))) = &mut Some(&mut Some(&mut Some(0u8))) { - | ^^^^^^^^^^^^^^^^^^^^^^^^ + | ^^^^ cannot implicitly match against multiple layers of reference | = warning: this changes meaning in Rust 2024 = note: for more information, see -help: desugar the match ergonomics +help: make the implied reference patterns and variable binding mode explicit | LL | if let &mut Some(&mut Some(&mut Some(ref mut x))) = &mut Some(&mut Some(&mut Some(0u8))) { | ++++ ++++ +++++++ -error: patterns are not allowed to reset the default binding mode in edition 2024 - --> $DIR/migration_lint.rs:111:9 +error: pattern uses features incompatible with edition 2024 + --> $DIR/migration_lint.rs:111:21 | LL | let Struct { a, mut b, c } = &Struct { a: 0, b: 0, c: 0 }; - | ^^^^^^^^^^^^^^^^^^^^^^ + | ^^^ requires binding by-value, but the implicit default is by-reference | = warning: this changes meaning in Rust 2024 = note: for more information, see -help: desugar the match ergonomics +help: make the implied reference pattern and variable binding modes explicit | LL | let &Struct { ref a, mut b, ref c } = &Struct { a: 0, b: 0, c: 0 }; | + +++ +++ -error: patterns are not allowed to reset the default binding mode in edition 2024 - --> $DIR/migration_lint.rs:117:9 +error: pattern uses features incompatible with edition 2024 + --> $DIR/migration_lint.rs:117:21 | LL | let Struct { a: &a, b, ref c } = &Struct { a: &0, b: &0, c: &0 }; - | ^^^^^^^^^^^^^^^^^^^^^^^^^^ + | ^ ^^^ cannot override to bind by-reference when that is the implicit default + | | + | cannot implicitly match against multiple layers of reference | = warning: this changes meaning in Rust 2024 = note: for more information, see -help: desugar the match ergonomics +help: make the implied reference pattern and variable binding mode explicit | LL | let &Struct { a: &a, ref b, ref c } = &Struct { a: &0, b: &0, c: &0 }; | + +++ -error: patterns are not allowed to reset the default binding mode in edition 2024 - --> $DIR/migration_lint.rs:124:12 +error: pattern uses features incompatible with edition 2024 + --> $DIR/migration_lint.rs:124:24 | LL | if let Struct { a: &Some(a), b: Some(&b), c: Some(c) } = - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | ^ ^ cannot implicitly match against multiple layers of reference + | | + | cannot implicitly match against multiple layers of reference | = warning: this changes meaning in Rust 2024 = note: for more information, see -help: desugar the match ergonomics +help: make the implied reference patterns and variable binding mode explicit | LL | if let &Struct { a: &Some(a), b: &Some(&b), c: &Some(ref c) } = | + + + +++ -error: patterns are not allowed to reset the default binding mode in edition 2024 - --> $DIR/migration_lint.rs:137:9 +error: pattern uses features incompatible with edition 2024 + --> $DIR/migration_lint.rs:137:15 | LL | (Some(mut x), migration_lint_macros::mixed_edition_pat!(y)) => { - | -^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ - | | - | help: desugar the match ergonomics: `&` + | ^^^ ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ default binding mode is reset within expansion + | | + | requires binding by-value, but the implicit default is by-reference + | + = note: this error originates in the macro `migration_lint_macros::mixed_edition_pat` (in Nightly builds, run with -Z macro-backtrace for more info) +help: make the implied reference pattern explicit + | +LL | &(Some(mut x), migration_lint_macros::mixed_edition_pat!(y)) => { + | + error: aborting due to 16 previous errors diff --git a/tests/ui/pattern/rfc-3627-match-ergonomics-2024/min_match_ergonomics_fail.rs b/tests/ui/pattern/rfc-3627-match-ergonomics-2024/min_match_ergonomics_fail.rs index 50b716a11113..dbb2e2420505 100644 --- a/tests/ui/pattern/rfc-3627-match-ergonomics-2024/min_match_ergonomics_fail.rs +++ b/tests/ui/pattern/rfc-3627-match-ergonomics-2024/min_match_ergonomics_fail.rs @@ -21,17 +21,17 @@ macro_rules! test_pat_on_type { } test_pat_on_type![(&x,): &(T,)]; //~ ERROR mismatched types -test_pat_on_type![(&x,): &(&T,)]; //~ ERROR patterns are not allowed to reset the default binding mode +test_pat_on_type![(&x,): &(&T,)]; //~ ERROR pattern uses features incompatible with edition 2024 test_pat_on_type![(&x,): &(&mut T,)]; //~ ERROR mismatched types test_pat_on_type![(&mut x,): &(&T,)]; //~ ERROR mismatched types -test_pat_on_type![(&mut x,): &(&mut T,)]; //~ ERROR patterns are not allowed to reset the default binding mode +test_pat_on_type![(&mut x,): &(&mut T,)]; //~ ERROR pattern uses features incompatible with edition 2024 test_pat_on_type![(&x,): &&mut &(T,)]; //~ ERROR mismatched types test_pat_on_type![Foo { f: (&x,) }: Foo]; //~ ERROR mismatched types test_pat_on_type![Foo { f: (&x,) }: &mut Foo]; //~ ERROR mismatched types -test_pat_on_type![Foo { f: &(x,) }: &Foo]; //~ ERROR patterns are not allowed to reset the default binding mode -test_pat_on_type![(mut x,): &(T,)]; //~ ERROR patterns are not allowed to reset the default binding mode -test_pat_on_type![(ref x,): &(T,)]; //~ ERROR patterns are not allowed to reset the default binding mode -test_pat_on_type![(ref mut x,): &mut (T,)]; //~ ERROR patterns are not allowed to reset the default binding mode +test_pat_on_type![Foo { f: &(x,) }: &Foo]; //~ ERROR pattern uses features incompatible with edition 2024 +test_pat_on_type![(mut x,): &(T,)]; //~ ERROR pattern uses features incompatible with edition 2024 +test_pat_on_type![(ref x,): &(T,)]; //~ ERROR pattern uses features incompatible with edition 2024 +test_pat_on_type![(ref mut x,): &mut (T,)]; //~ ERROR pattern uses features incompatible with edition 2024 fn get() -> X { unimplemented!() @@ -40,6 +40,6 @@ fn get() -> X { // Make sure this works even when the underlying type is inferred. This test passes on rust stable. fn infer() -> X { match &get() { - (&x,) => x, //~ ERROR patterns are not allowed to reset the default binding mode + (&x,) => x, //~ ERROR pattern uses features incompatible with edition 2024 } } diff --git a/tests/ui/pattern/rfc-3627-match-ergonomics-2024/min_match_ergonomics_fail.stderr b/tests/ui/pattern/rfc-3627-match-ergonomics-2024/min_match_ergonomics_fail.stderr index 92058095f84a..e99c77213f2a 100644 --- a/tests/ui/pattern/rfc-3627-match-ergonomics-2024/min_match_ergonomics_fail.stderr +++ b/tests/ui/pattern/rfc-3627-match-ergonomics-2024/min_match_ergonomics_fail.stderr @@ -99,61 +99,82 @@ LL - test_pat_on_type![Foo { f: (&x,) }: &mut Foo]; LL + test_pat_on_type![Foo { f: (x,) }: &mut Foo]; | -error: patterns are not allowed to reset the default binding mode in edition 2024 - --> $DIR/min_match_ergonomics_fail.rs:24:19 +error: pattern uses features incompatible with edition 2024 + --> $DIR/min_match_ergonomics_fail.rs:24:20 | LL | test_pat_on_type![(&x,): &(&T,)]; - | -^^^^ - | | - | help: desugar the match ergonomics: `&` + | ^ cannot implicitly match against multiple layers of reference + | +help: make the implied reference pattern explicit + | +LL | test_pat_on_type![&(&x,): &(&T,)]; + | + -error: patterns are not allowed to reset the default binding mode in edition 2024 - --> $DIR/min_match_ergonomics_fail.rs:27:19 +error: pattern uses features incompatible with edition 2024 + --> $DIR/min_match_ergonomics_fail.rs:27:20 | LL | test_pat_on_type![(&mut x,): &(&mut T,)]; - | -^^^^^^^^ - | | - | help: desugar the match ergonomics: `&` + | ^^^^ cannot implicitly match against multiple layers of reference + | +help: make the implied reference pattern explicit + | +LL | test_pat_on_type![&(&mut x,): &(&mut T,)]; + | + -error: patterns are not allowed to reset the default binding mode in edition 2024 - --> $DIR/min_match_ergonomics_fail.rs:31:19 +error: pattern uses features incompatible with edition 2024 + --> $DIR/min_match_ergonomics_fail.rs:31:28 | LL | test_pat_on_type![Foo { f: &(x,) }: &Foo]; - | -^^^^^^^^^^^^^^^ - | | - | help: desugar the match ergonomics: `&` + | ^ cannot implicitly match against multiple layers of reference + | +help: make the implied reference pattern explicit + | +LL | test_pat_on_type![&Foo { f: &(x,) }: &Foo]; + | + -error: patterns are not allowed to reset the default binding mode in edition 2024 - --> $DIR/min_match_ergonomics_fail.rs:32:19 +error: pattern uses features incompatible with edition 2024 + --> $DIR/min_match_ergonomics_fail.rs:32:20 | LL | test_pat_on_type![(mut x,): &(T,)]; - | -^^^^^^^ - | | - | help: desugar the match ergonomics: `&` + | ^^^ requires binding by-value, but the implicit default is by-reference + | +help: make the implied reference pattern explicit + | +LL | test_pat_on_type![&(mut x,): &(T,)]; + | + -error: patterns are not allowed to reset the default binding mode in edition 2024 - --> $DIR/min_match_ergonomics_fail.rs:33:19 +error: pattern uses features incompatible with edition 2024 + --> $DIR/min_match_ergonomics_fail.rs:33:20 | LL | test_pat_on_type![(ref x,): &(T,)]; - | -^^^^^^^ - | | - | help: desugar the match ergonomics: `&` + | ^^^ cannot override to bind by-reference when that is the implicit default + | +help: make the implied reference pattern explicit + | +LL | test_pat_on_type![&(ref x,): &(T,)]; + | + -error: patterns are not allowed to reset the default binding mode in edition 2024 - --> $DIR/min_match_ergonomics_fail.rs:34:19 +error: pattern uses features incompatible with edition 2024 + --> $DIR/min_match_ergonomics_fail.rs:34:20 | LL | test_pat_on_type![(ref mut x,): &mut (T,)]; - | -^^^^^^^^^^^ - | | - | help: desugar the match ergonomics: `&mut` + | ^^^^^^^ cannot override to bind by-reference when that is the implicit default + | +help: make the implied reference pattern explicit + | +LL | test_pat_on_type![&mut (ref mut x,): &mut (T,)]; + | ++++ -error: patterns are not allowed to reset the default binding mode in edition 2024 - --> $DIR/min_match_ergonomics_fail.rs:43:9 +error: pattern uses features incompatible with edition 2024 + --> $DIR/min_match_ergonomics_fail.rs:43:10 | LL | (&x,) => x, - | -^^^^ - | | - | help: desugar the match ergonomics: `&` + | ^ cannot implicitly match against multiple layers of reference + | +help: make the implied reference pattern explicit + | +LL | &(&x,) => x, + | + error: aborting due to 13 previous errors From 70b852737795fb6757893495a4f886756b8a7b4e Mon Sep 17 00:00:00 2001 From: dianne Date: Tue, 17 Dec 2024 09:49:20 -0800 Subject: [PATCH 22/92] Correctly check the edition of subpatterns in the pattern migration 2024 lint --- compiler/rustc_hir_typeck/src/pat.rs | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/compiler/rustc_hir_typeck/src/pat.rs b/compiler/rustc_hir_typeck/src/pat.rs index f20db5c65019..e27a555eab53 100644 --- a/compiler/rustc_hir_typeck/src/pat.rs +++ b/compiler/rustc_hir_typeck/src/pat.rs @@ -2641,12 +2641,14 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { detailed_label: &str, ) { // Try to trim the span we're labeling to just the `&` or binding mode that's an issue. - // If the subpattern span is a macro call site, no trimming will be done. + // If the subpattern's span is is from an expansion, the emitted label will not be trimmed. let source_map = self.tcx.sess.source_map(); let cutoff_span = source_map .span_extend_prev_while(cutoff_span, char::is_whitespace) .unwrap_or(cutoff_span); - let trimmed_span = subpat_span.until(cutoff_span); + // Ensure we use the syntax context and thus edition of `subpat_span`; this will be a hard + // error if the subpattern is of edition >= 2024. + let trimmed_span = subpat_span.until(cutoff_span).with_ctxt(subpat_span.ctxt()); // Only provide a detailed label if the problematic subpattern isn't from an expansion. // In the case that it's from a macro, we'll add a more detailed note in the emitter. From 77e9051e22c89585f0e96f3476edbe664a80ccc0 Mon Sep 17 00:00:00 2001 From: dianne Date: Tue, 17 Dec 2024 10:00:15 -0800 Subject: [PATCH 23/92] Improve the pattern migration 2024 migration lint's message --- compiler/rustc_mir_build/messages.ftl | 2 +- .../migration_lint.fixed | 32 +++++++++---------- .../migration_lint.rs | 32 +++++++++---------- .../migration_lint.stderr | 32 +++++++++---------- .../min_match_ergonomics_fail.rs | 14 ++++---- .../min_match_ergonomics_fail.stderr | 14 ++++---- 6 files changed, 63 insertions(+), 63 deletions(-) diff --git a/compiler/rustc_mir_build/messages.ftl b/compiler/rustc_mir_build/messages.ftl index f7f55821d4b6..edba247c7b0d 100644 --- a/compiler/rustc_mir_build/messages.ftl +++ b/compiler/rustc_mir_build/messages.ftl @@ -285,7 +285,7 @@ mir_build_pointer_pattern = function pointers and raw pointers not derived from mir_build_privately_uninhabited = pattern `{$witness_1}` is currently uninhabited, but this variant contains private fields which may become inhabited in the future -mir_build_rust_2024_incompatible_pat = pattern uses features incompatible with edition 2024 +mir_build_rust_2024_incompatible_pat = this pattern relies on behavior which may change in edition 2024 mir_build_rustc_box_attribute_error = `#[rustc_box]` attribute used incorrectly .attributes = no other attributes may be applied diff --git a/tests/ui/pattern/rfc-3627-match-ergonomics-2024/migration_lint.fixed b/tests/ui/pattern/rfc-3627-match-ergonomics-2024/migration_lint.fixed index 63e82eab8fb3..e2b2c9876104 100644 --- a/tests/ui/pattern/rfc-3627-match-ergonomics-2024/migration_lint.fixed +++ b/tests/ui/pattern/rfc-3627-match-ergonomics-2024/migration_lint.fixed @@ -23,22 +23,22 @@ fn main() { assert_type_eq(x, &mut 0u8); let &Foo(mut x) = &Foo(0); - //~^ ERROR: pattern uses features incompatible with edition 2024 + //~^ ERROR: this pattern relies on behavior which may change in edition 2024 //~| WARN: this changes meaning in Rust 2024 assert_type_eq(x, 0u8); let &mut Foo(mut x) = &mut Foo(0); - //~^ ERROR: pattern uses features incompatible with edition 2024 + //~^ ERROR: this pattern relies on behavior which may change in edition 2024 //~| WARN: this changes meaning in Rust 2024 assert_type_eq(x, 0u8); let &Foo(ref x) = &Foo(0); - //~^ ERROR: pattern uses features incompatible with edition 2024 + //~^ ERROR: this pattern relies on behavior which may change in edition 2024 //~| WARN: this changes meaning in Rust 2024 assert_type_eq(x, &0u8); let &mut Foo(ref x) = &mut Foo(0); - //~^ ERROR: pattern uses features incompatible with edition 2024 + //~^ ERROR: this pattern relies on behavior which may change in edition 2024 //~| WARN: this changes meaning in Rust 2024 assert_type_eq(x, &0u8); @@ -55,22 +55,22 @@ fn main() { assert_type_eq(x, &0u8); let &Foo(&x) = &Foo(&0); - //~^ ERROR: pattern uses features incompatible with edition 2024 + //~^ ERROR: this pattern relies on behavior which may change in edition 2024 //~| WARN: this changes meaning in Rust 2024 assert_type_eq(x, 0u8); let &Foo(&mut x) = &Foo(&mut 0); - //~^ ERROR: pattern uses features incompatible with edition 2024 + //~^ ERROR: this pattern relies on behavior which may change in edition 2024 //~| WARN: this changes meaning in Rust 2024 assert_type_eq(x, 0u8); let &mut Foo(&x) = &mut Foo(&0); - //~^ ERROR: pattern uses features incompatible with edition 2024 + //~^ ERROR: this pattern relies on behavior which may change in edition 2024 //~| WARN: this changes meaning in Rust 2024 assert_type_eq(x, 0u8); let &mut Foo(&mut x) = &mut Foo(&mut 0); - //~^ ERROR: pattern uses features incompatible with edition 2024 + //~^ ERROR: this pattern relies on behavior which may change in edition 2024 //~| WARN: this changes meaning in Rust 2024 assert_type_eq(x, 0u8); @@ -79,25 +79,25 @@ fn main() { } if let &&&&&Some(&x) = &&&&&Some(&0u8) { - //~^ ERROR: pattern uses features incompatible with edition 2024 + //~^ ERROR: this pattern relies on behavior which may change in edition 2024 //~| WARN: this changes meaning in Rust 2024 assert_type_eq(x, 0u8); } if let &&&&&Some(&mut x) = &&&&&Some(&mut 0u8) { - //~^ ERROR: pattern uses features incompatible with edition 2024 + //~^ ERROR: this pattern relies on behavior which may change in edition 2024 //~| WARN: this changes meaning in Rust 2024 assert_type_eq(x, 0u8); } if let &&&&&mut Some(&x) = &&&&&mut Some(&0u8) { - //~^ ERROR: pattern uses features incompatible with edition 2024 + //~^ ERROR: this pattern relies on behavior which may change in edition 2024 //~| WARN: this changes meaning in Rust 2024 assert_type_eq(x, 0u8); } if let &mut Some(&mut Some(&mut Some(ref mut x))) = &mut Some(&mut Some(&mut Some(0u8))) { - //~^ ERROR: pattern uses features incompatible with edition 2024 + //~^ ERROR: this pattern relies on behavior which may change in edition 2024 //~| WARN: this changes meaning in Rust 2024 assert_type_eq(x, &mut 0u8); } @@ -109,20 +109,20 @@ fn main() { } let &Struct { ref a, mut b, ref c } = &Struct { a: 0, b: 0, c: 0 }; - //~^ ERROR: pattern uses features incompatible with edition 2024 + //~^ ERROR: this pattern relies on behavior which may change in edition 2024 //~| WARN: this changes meaning in Rust 2024 assert_type_eq(a, &0u32); assert_type_eq(b, 0u32); let &Struct { a: &a, ref b, ref c } = &Struct { a: &0, b: &0, c: &0 }; - //~^ ERROR: pattern uses features incompatible with edition 2024 + //~^ ERROR: this pattern relies on behavior which may change in edition 2024 //~| WARN: this changes meaning in Rust 2024 assert_type_eq(a, 0u32); assert_type_eq(b, &&0u32); assert_type_eq(c, &&0u32); if let &Struct { a: &Some(a), b: &Some(&b), c: &Some(ref c) } = - //~^ ERROR: pattern uses features incompatible with edition 2024 + //~^ ERROR: this pattern relies on behavior which may change in edition 2024 //~| WARN: this changes meaning in Rust 2024 &(Struct { a: &Some(&0), b: &Some(&0), c: &Some(&0) }) { @@ -135,7 +135,7 @@ fn main() { // The two patterns are the same syntactically, but because they're defined in different // editions they don't mean the same thing. &(Some(mut x), migration_lint_macros::mixed_edition_pat!(y)) => { - //~^ ERROR: pattern uses features incompatible with edition 2024 + //~^ ERROR: this pattern relies on behavior which may change in edition 2024 assert_type_eq(x, 0u32); assert_type_eq(y, 0u32); } diff --git a/tests/ui/pattern/rfc-3627-match-ergonomics-2024/migration_lint.rs b/tests/ui/pattern/rfc-3627-match-ergonomics-2024/migration_lint.rs index 4234192da519..098540adfa2c 100644 --- a/tests/ui/pattern/rfc-3627-match-ergonomics-2024/migration_lint.rs +++ b/tests/ui/pattern/rfc-3627-match-ergonomics-2024/migration_lint.rs @@ -23,22 +23,22 @@ fn main() { assert_type_eq(x, &mut 0u8); let Foo(mut x) = &Foo(0); - //~^ ERROR: pattern uses features incompatible with edition 2024 + //~^ ERROR: this pattern relies on behavior which may change in edition 2024 //~| WARN: this changes meaning in Rust 2024 assert_type_eq(x, 0u8); let Foo(mut x) = &mut Foo(0); - //~^ ERROR: pattern uses features incompatible with edition 2024 + //~^ ERROR: this pattern relies on behavior which may change in edition 2024 //~| WARN: this changes meaning in Rust 2024 assert_type_eq(x, 0u8); let Foo(ref x) = &Foo(0); - //~^ ERROR: pattern uses features incompatible with edition 2024 + //~^ ERROR: this pattern relies on behavior which may change in edition 2024 //~| WARN: this changes meaning in Rust 2024 assert_type_eq(x, &0u8); let Foo(ref x) = &mut Foo(0); - //~^ ERROR: pattern uses features incompatible with edition 2024 + //~^ ERROR: this pattern relies on behavior which may change in edition 2024 //~| WARN: this changes meaning in Rust 2024 assert_type_eq(x, &0u8); @@ -55,22 +55,22 @@ fn main() { assert_type_eq(x, &0u8); let Foo(&x) = &Foo(&0); - //~^ ERROR: pattern uses features incompatible with edition 2024 + //~^ ERROR: this pattern relies on behavior which may change in edition 2024 //~| WARN: this changes meaning in Rust 2024 assert_type_eq(x, 0u8); let Foo(&mut x) = &Foo(&mut 0); - //~^ ERROR: pattern uses features incompatible with edition 2024 + //~^ ERROR: this pattern relies on behavior which may change in edition 2024 //~| WARN: this changes meaning in Rust 2024 assert_type_eq(x, 0u8); let Foo(&x) = &mut Foo(&0); - //~^ ERROR: pattern uses features incompatible with edition 2024 + //~^ ERROR: this pattern relies on behavior which may change in edition 2024 //~| WARN: this changes meaning in Rust 2024 assert_type_eq(x, 0u8); let Foo(&mut x) = &mut Foo(&mut 0); - //~^ ERROR: pattern uses features incompatible with edition 2024 + //~^ ERROR: this pattern relies on behavior which may change in edition 2024 //~| WARN: this changes meaning in Rust 2024 assert_type_eq(x, 0u8); @@ -79,25 +79,25 @@ fn main() { } if let Some(&x) = &&&&&Some(&0u8) { - //~^ ERROR: pattern uses features incompatible with edition 2024 + //~^ ERROR: this pattern relies on behavior which may change in edition 2024 //~| WARN: this changes meaning in Rust 2024 assert_type_eq(x, 0u8); } if let Some(&mut x) = &&&&&Some(&mut 0u8) { - //~^ ERROR: pattern uses features incompatible with edition 2024 + //~^ ERROR: this pattern relies on behavior which may change in edition 2024 //~| WARN: this changes meaning in Rust 2024 assert_type_eq(x, 0u8); } if let Some(&x) = &&&&&mut Some(&0u8) { - //~^ ERROR: pattern uses features incompatible with edition 2024 + //~^ ERROR: this pattern relies on behavior which may change in edition 2024 //~| WARN: this changes meaning in Rust 2024 assert_type_eq(x, 0u8); } if let Some(&mut Some(Some(x))) = &mut Some(&mut Some(&mut Some(0u8))) { - //~^ ERROR: pattern uses features incompatible with edition 2024 + //~^ ERROR: this pattern relies on behavior which may change in edition 2024 //~| WARN: this changes meaning in Rust 2024 assert_type_eq(x, &mut 0u8); } @@ -109,20 +109,20 @@ fn main() { } let Struct { a, mut b, c } = &Struct { a: 0, b: 0, c: 0 }; - //~^ ERROR: pattern uses features incompatible with edition 2024 + //~^ ERROR: this pattern relies on behavior which may change in edition 2024 //~| WARN: this changes meaning in Rust 2024 assert_type_eq(a, &0u32); assert_type_eq(b, 0u32); let Struct { a: &a, b, ref c } = &Struct { a: &0, b: &0, c: &0 }; - //~^ ERROR: pattern uses features incompatible with edition 2024 + //~^ ERROR: this pattern relies on behavior which may change in edition 2024 //~| WARN: this changes meaning in Rust 2024 assert_type_eq(a, 0u32); assert_type_eq(b, &&0u32); assert_type_eq(c, &&0u32); if let Struct { a: &Some(a), b: Some(&b), c: Some(c) } = - //~^ ERROR: pattern uses features incompatible with edition 2024 + //~^ ERROR: this pattern relies on behavior which may change in edition 2024 //~| WARN: this changes meaning in Rust 2024 &(Struct { a: &Some(&0), b: &Some(&0), c: &Some(&0) }) { @@ -135,7 +135,7 @@ fn main() { // The two patterns are the same syntactically, but because they're defined in different // editions they don't mean the same thing. (Some(mut x), migration_lint_macros::mixed_edition_pat!(y)) => { - //~^ ERROR: pattern uses features incompatible with edition 2024 + //~^ ERROR: this pattern relies on behavior which may change in edition 2024 assert_type_eq(x, 0u32); assert_type_eq(y, 0u32); } diff --git a/tests/ui/pattern/rfc-3627-match-ergonomics-2024/migration_lint.stderr b/tests/ui/pattern/rfc-3627-match-ergonomics-2024/migration_lint.stderr index 20c88d79e96b..73b0e4b67d91 100644 --- a/tests/ui/pattern/rfc-3627-match-ergonomics-2024/migration_lint.stderr +++ b/tests/ui/pattern/rfc-3627-match-ergonomics-2024/migration_lint.stderr @@ -1,4 +1,4 @@ -error: pattern uses features incompatible with edition 2024 +error: this pattern relies on behavior which may change in edition 2024 --> $DIR/migration_lint.rs:25:13 | LL | let Foo(mut x) = &Foo(0); @@ -16,7 +16,7 @@ help: make the implied reference pattern explicit LL | let &Foo(mut x) = &Foo(0); | + -error: pattern uses features incompatible with edition 2024 +error: this pattern relies on behavior which may change in edition 2024 --> $DIR/migration_lint.rs:30:13 | LL | let Foo(mut x) = &mut Foo(0); @@ -29,7 +29,7 @@ help: make the implied reference pattern explicit LL | let &mut Foo(mut x) = &mut Foo(0); | ++++ -error: pattern uses features incompatible with edition 2024 +error: this pattern relies on behavior which may change in edition 2024 --> $DIR/migration_lint.rs:35:13 | LL | let Foo(ref x) = &Foo(0); @@ -42,7 +42,7 @@ help: make the implied reference pattern explicit LL | let &Foo(ref x) = &Foo(0); | + -error: pattern uses features incompatible with edition 2024 +error: this pattern relies on behavior which may change in edition 2024 --> $DIR/migration_lint.rs:40:13 | LL | let Foo(ref x) = &mut Foo(0); @@ -55,7 +55,7 @@ help: make the implied reference pattern explicit LL | let &mut Foo(ref x) = &mut Foo(0); | ++++ -error: pattern uses features incompatible with edition 2024 +error: this pattern relies on behavior which may change in edition 2024 --> $DIR/migration_lint.rs:57:13 | LL | let Foo(&x) = &Foo(&0); @@ -68,7 +68,7 @@ help: make the implied reference pattern explicit LL | let &Foo(&x) = &Foo(&0); | + -error: pattern uses features incompatible with edition 2024 +error: this pattern relies on behavior which may change in edition 2024 --> $DIR/migration_lint.rs:62:13 | LL | let Foo(&mut x) = &Foo(&mut 0); @@ -81,7 +81,7 @@ help: make the implied reference pattern explicit LL | let &Foo(&mut x) = &Foo(&mut 0); | + -error: pattern uses features incompatible with edition 2024 +error: this pattern relies on behavior which may change in edition 2024 --> $DIR/migration_lint.rs:67:13 | LL | let Foo(&x) = &mut Foo(&0); @@ -94,7 +94,7 @@ help: make the implied reference pattern explicit LL | let &mut Foo(&x) = &mut Foo(&0); | ++++ -error: pattern uses features incompatible with edition 2024 +error: this pattern relies on behavior which may change in edition 2024 --> $DIR/migration_lint.rs:72:13 | LL | let Foo(&mut x) = &mut Foo(&mut 0); @@ -107,7 +107,7 @@ help: make the implied reference pattern explicit LL | let &mut Foo(&mut x) = &mut Foo(&mut 0); | ++++ -error: pattern uses features incompatible with edition 2024 +error: this pattern relies on behavior which may change in edition 2024 --> $DIR/migration_lint.rs:81:17 | LL | if let Some(&x) = &&&&&Some(&0u8) { @@ -120,7 +120,7 @@ help: make the implied reference patterns explicit LL | if let &&&&&Some(&x) = &&&&&Some(&0u8) { | +++++ -error: pattern uses features incompatible with edition 2024 +error: this pattern relies on behavior which may change in edition 2024 --> $DIR/migration_lint.rs:87:17 | LL | if let Some(&mut x) = &&&&&Some(&mut 0u8) { @@ -133,7 +133,7 @@ help: make the implied reference patterns explicit LL | if let &&&&&Some(&mut x) = &&&&&Some(&mut 0u8) { | +++++ -error: pattern uses features incompatible with edition 2024 +error: this pattern relies on behavior which may change in edition 2024 --> $DIR/migration_lint.rs:93:17 | LL | if let Some(&x) = &&&&&mut Some(&0u8) { @@ -146,7 +146,7 @@ help: make the implied reference patterns explicit LL | if let &&&&&mut Some(&x) = &&&&&mut Some(&0u8) { | ++++++++ -error: pattern uses features incompatible with edition 2024 +error: this pattern relies on behavior which may change in edition 2024 --> $DIR/migration_lint.rs:99:17 | LL | if let Some(&mut Some(Some(x))) = &mut Some(&mut Some(&mut Some(0u8))) { @@ -159,7 +159,7 @@ help: make the implied reference patterns and variable binding mode explicit LL | if let &mut Some(&mut Some(&mut Some(ref mut x))) = &mut Some(&mut Some(&mut Some(0u8))) { | ++++ ++++ +++++++ -error: pattern uses features incompatible with edition 2024 +error: this pattern relies on behavior which may change in edition 2024 --> $DIR/migration_lint.rs:111:21 | LL | let Struct { a, mut b, c } = &Struct { a: 0, b: 0, c: 0 }; @@ -172,7 +172,7 @@ help: make the implied reference pattern and variable binding modes explicit LL | let &Struct { ref a, mut b, ref c } = &Struct { a: 0, b: 0, c: 0 }; | + +++ +++ -error: pattern uses features incompatible with edition 2024 +error: this pattern relies on behavior which may change in edition 2024 --> $DIR/migration_lint.rs:117:21 | LL | let Struct { a: &a, b, ref c } = &Struct { a: &0, b: &0, c: &0 }; @@ -187,7 +187,7 @@ help: make the implied reference pattern and variable binding mode explicit LL | let &Struct { a: &a, ref b, ref c } = &Struct { a: &0, b: &0, c: &0 }; | + +++ -error: pattern uses features incompatible with edition 2024 +error: this pattern relies on behavior which may change in edition 2024 --> $DIR/migration_lint.rs:124:24 | LL | if let Struct { a: &Some(a), b: Some(&b), c: Some(c) } = @@ -202,7 +202,7 @@ help: make the implied reference patterns and variable binding mode explicit LL | if let &Struct { a: &Some(a), b: &Some(&b), c: &Some(ref c) } = | + + + +++ -error: pattern uses features incompatible with edition 2024 +error: this pattern relies on behavior which may change in edition 2024 --> $DIR/migration_lint.rs:137:15 | LL | (Some(mut x), migration_lint_macros::mixed_edition_pat!(y)) => { diff --git a/tests/ui/pattern/rfc-3627-match-ergonomics-2024/min_match_ergonomics_fail.rs b/tests/ui/pattern/rfc-3627-match-ergonomics-2024/min_match_ergonomics_fail.rs index dbb2e2420505..5ba554fc6e5a 100644 --- a/tests/ui/pattern/rfc-3627-match-ergonomics-2024/min_match_ergonomics_fail.rs +++ b/tests/ui/pattern/rfc-3627-match-ergonomics-2024/min_match_ergonomics_fail.rs @@ -21,17 +21,17 @@ macro_rules! test_pat_on_type { } test_pat_on_type![(&x,): &(T,)]; //~ ERROR mismatched types -test_pat_on_type![(&x,): &(&T,)]; //~ ERROR pattern uses features incompatible with edition 2024 +test_pat_on_type![(&x,): &(&T,)]; //~ ERROR this pattern relies on behavior which may change in edition 2024 test_pat_on_type![(&x,): &(&mut T,)]; //~ ERROR mismatched types test_pat_on_type![(&mut x,): &(&T,)]; //~ ERROR mismatched types -test_pat_on_type![(&mut x,): &(&mut T,)]; //~ ERROR pattern uses features incompatible with edition 2024 +test_pat_on_type![(&mut x,): &(&mut T,)]; //~ ERROR this pattern relies on behavior which may change in edition 2024 test_pat_on_type![(&x,): &&mut &(T,)]; //~ ERROR mismatched types test_pat_on_type![Foo { f: (&x,) }: Foo]; //~ ERROR mismatched types test_pat_on_type![Foo { f: (&x,) }: &mut Foo]; //~ ERROR mismatched types -test_pat_on_type![Foo { f: &(x,) }: &Foo]; //~ ERROR pattern uses features incompatible with edition 2024 -test_pat_on_type![(mut x,): &(T,)]; //~ ERROR pattern uses features incompatible with edition 2024 -test_pat_on_type![(ref x,): &(T,)]; //~ ERROR pattern uses features incompatible with edition 2024 -test_pat_on_type![(ref mut x,): &mut (T,)]; //~ ERROR pattern uses features incompatible with edition 2024 +test_pat_on_type![Foo { f: &(x,) }: &Foo]; //~ ERROR this pattern relies on behavior which may change in edition 2024 +test_pat_on_type![(mut x,): &(T,)]; //~ ERROR this pattern relies on behavior which may change in edition 2024 +test_pat_on_type![(ref x,): &(T,)]; //~ ERROR this pattern relies on behavior which may change in edition 2024 +test_pat_on_type![(ref mut x,): &mut (T,)]; //~ ERROR this pattern relies on behavior which may change in edition 2024 fn get() -> X { unimplemented!() @@ -40,6 +40,6 @@ fn get() -> X { // Make sure this works even when the underlying type is inferred. This test passes on rust stable. fn infer() -> X { match &get() { - (&x,) => x, //~ ERROR pattern uses features incompatible with edition 2024 + (&x,) => x, //~ ERROR this pattern relies on behavior which may change in edition 2024 } } diff --git a/tests/ui/pattern/rfc-3627-match-ergonomics-2024/min_match_ergonomics_fail.stderr b/tests/ui/pattern/rfc-3627-match-ergonomics-2024/min_match_ergonomics_fail.stderr index e99c77213f2a..38de6e34cbcd 100644 --- a/tests/ui/pattern/rfc-3627-match-ergonomics-2024/min_match_ergonomics_fail.stderr +++ b/tests/ui/pattern/rfc-3627-match-ergonomics-2024/min_match_ergonomics_fail.stderr @@ -99,7 +99,7 @@ LL - test_pat_on_type![Foo { f: (&x,) }: &mut Foo]; LL + test_pat_on_type![Foo { f: (x,) }: &mut Foo]; | -error: pattern uses features incompatible with edition 2024 +error: this pattern relies on behavior which may change in edition 2024 --> $DIR/min_match_ergonomics_fail.rs:24:20 | LL | test_pat_on_type![(&x,): &(&T,)]; @@ -110,7 +110,7 @@ help: make the implied reference pattern explicit LL | test_pat_on_type![&(&x,): &(&T,)]; | + -error: pattern uses features incompatible with edition 2024 +error: this pattern relies on behavior which may change in edition 2024 --> $DIR/min_match_ergonomics_fail.rs:27:20 | LL | test_pat_on_type![(&mut x,): &(&mut T,)]; @@ -121,7 +121,7 @@ help: make the implied reference pattern explicit LL | test_pat_on_type![&(&mut x,): &(&mut T,)]; | + -error: pattern uses features incompatible with edition 2024 +error: this pattern relies on behavior which may change in edition 2024 --> $DIR/min_match_ergonomics_fail.rs:31:28 | LL | test_pat_on_type![Foo { f: &(x,) }: &Foo]; @@ -132,7 +132,7 @@ help: make the implied reference pattern explicit LL | test_pat_on_type![&Foo { f: &(x,) }: &Foo]; | + -error: pattern uses features incompatible with edition 2024 +error: this pattern relies on behavior which may change in edition 2024 --> $DIR/min_match_ergonomics_fail.rs:32:20 | LL | test_pat_on_type![(mut x,): &(T,)]; @@ -143,7 +143,7 @@ help: make the implied reference pattern explicit LL | test_pat_on_type![&(mut x,): &(T,)]; | + -error: pattern uses features incompatible with edition 2024 +error: this pattern relies on behavior which may change in edition 2024 --> $DIR/min_match_ergonomics_fail.rs:33:20 | LL | test_pat_on_type![(ref x,): &(T,)]; @@ -154,7 +154,7 @@ help: make the implied reference pattern explicit LL | test_pat_on_type![&(ref x,): &(T,)]; | + -error: pattern uses features incompatible with edition 2024 +error: this pattern relies on behavior which may change in edition 2024 --> $DIR/min_match_ergonomics_fail.rs:34:20 | LL | test_pat_on_type![(ref mut x,): &mut (T,)]; @@ -165,7 +165,7 @@ help: make the implied reference pattern explicit LL | test_pat_on_type![&mut (ref mut x,): &mut (T,)]; | ++++ -error: pattern uses features incompatible with edition 2024 +error: this pattern relies on behavior which may change in edition 2024 --> $DIR/min_match_ergonomics_fail.rs:43:10 | LL | (&x,) => x, From a105cd606628b07e79ab343cc183a176e278c809 Mon Sep 17 00:00:00 2001 From: Josh Triplett Date: Tue, 17 Dec 2024 14:33:10 -0800 Subject: [PATCH 24/92] Use field init shorthand where possible Field init shorthand allows writing initializers like `tcx: tcx` as `tcx`. The compiler already uses it extensively. Fix the last few places where it isn't yet used. --- compiler/rustc_const_eval/src/interpret/projection.rs | 2 +- compiler/rustc_lint/src/impl_trait_overcaptures.rs | 2 +- compiler/rustc_parse/src/parser/pat.rs | 2 +- compiler/rustc_type_ir/src/elaborate.rs | 2 +- library/alloc/src/rc.rs | 2 +- library/alloc/src/sync.rs | 2 +- library/core/src/task/wake.rs | 2 +- library/std/src/sys/pal/hermit/fs.rs | 2 +- library/std/src/sys/pal/hermit/thread.rs | 2 +- library/std/src/sys/pal/hermit/time.rs | 2 +- library/std/src/sys/pal/sgx/fd.rs | 2 +- rustfmt.toml | 1 + src/tools/compiletest/src/read2.rs | 2 +- tests/codegen-units/item-collection/generic-impl.rs | 2 +- tests/codegen/issues/issue-15953.rs | 2 +- tests/run-make/extern-fn-struct-passing-abi/test.rs | 2 +- tests/run-make/symbols-include-type-name/lib.rs | 2 +- 17 files changed, 17 insertions(+), 16 deletions(-) diff --git a/compiler/rustc_const_eval/src/interpret/projection.rs b/compiler/rustc_const_eval/src/interpret/projection.rs index 65a93784e2cc..996142d7b03b 100644 --- a/compiler/rustc_const_eval/src/interpret/projection.rs +++ b/compiler/rustc_const_eval/src/interpret/projection.rs @@ -325,7 +325,7 @@ where let actual_to = if from_end { if from.checked_add(to).is_none_or(|to| to > len) { // This can only be reached in ConstProp and non-rustc-MIR. - throw_ub!(BoundsCheckFailed { len: len, index: from.saturating_add(to) }); + throw_ub!(BoundsCheckFailed { len, index: from.saturating_add(to) }); } len.checked_sub(to).unwrap() } else { diff --git a/compiler/rustc_lint/src/impl_trait_overcaptures.rs b/compiler/rustc_lint/src/impl_trait_overcaptures.rs index 1aacdbd448cc..eba62c39339d 100644 --- a/compiler/rustc_lint/src/impl_trait_overcaptures.rs +++ b/compiler/rustc_lint/src/impl_trait_overcaptures.rs @@ -177,7 +177,7 @@ fn check_fn(tcx: TyCtxt<'_>, parent_def_id: LocalDefId) { // Lazily compute these two, since they're likely a bit expensive. variances: LazyCell::new(|| { let mut functional_variances = FunctionalVariances { - tcx: tcx, + tcx, variances: FxHashMap::default(), ambient_variance: ty::Covariant, generics: tcx.generics_of(parent_def_id), diff --git a/compiler/rustc_parse/src/parser/pat.rs b/compiler/rustc_parse/src/parser/pat.rs index 255be721525c..8706ae4a4267 100644 --- a/compiler/rustc_parse/src/parser/pat.rs +++ b/compiler/rustc_parse/src/parser/pat.rs @@ -1648,7 +1648,7 @@ impl<'a> Parser<'a> { ident: prev_field, }) } else { - self.dcx().create_err(AtInStructPattern { span: span }) + self.dcx().create_err(AtInStructPattern { span }) } } diff --git a/compiler/rustc_type_ir/src/elaborate.rs b/compiler/rustc_type_ir/src/elaborate.rs index 0d574445df80..923b74abdfd2 100644 --- a/compiler/rustc_type_ir/src/elaborate.rs +++ b/compiler/rustc_type_ir/src/elaborate.rs @@ -72,7 +72,7 @@ impl Elaboratable for ClauseWithSupertraitSpan { _parent_trait_pred: crate::Binder>, _index: usize, ) -> Self { - ClauseWithSupertraitSpan { pred: clause.as_predicate(), supertrait_span: supertrait_span } + ClauseWithSupertraitSpan { pred: clause.as_predicate(), supertrait_span } } } diff --git a/library/alloc/src/rc.rs b/library/alloc/src/rc.rs index bb27fe3c62dc..b7ec3af9818a 100644 --- a/library/alloc/src/rc.rs +++ b/library/alloc/src/rc.rs @@ -795,7 +795,7 @@ impl Rc { let uninit_ptr: NonNull<_> = (unsafe { &mut *uninit_raw_ptr }).into(); let init_ptr: NonNull> = uninit_ptr.cast(); - let weak = Weak { ptr: init_ptr, alloc: alloc }; + let weak = Weak { ptr: init_ptr, alloc }; // It's important we don't give up ownership of the weak pointer, or // else the memory might be freed by the time `data_fn` returns. If diff --git a/library/alloc/src/sync.rs b/library/alloc/src/sync.rs index 6cf41a3fa4e1..9be0b3e3e880 100644 --- a/library/alloc/src/sync.rs +++ b/library/alloc/src/sync.rs @@ -784,7 +784,7 @@ impl Arc { let uninit_ptr: NonNull<_> = (unsafe { &mut *uninit_raw_ptr }).into(); let init_ptr: NonNull> = uninit_ptr.cast(); - let weak = Weak { ptr: init_ptr, alloc: alloc }; + let weak = Weak { ptr: init_ptr, alloc }; // It's important we don't give up ownership of the weak pointer, or // else the memory might be freed by the time `data_fn` returns. If diff --git a/library/core/src/task/wake.rs b/library/core/src/task/wake.rs index bfffcc24a46a..ba429005fab3 100644 --- a/library/core/src/task/wake.rs +++ b/library/core/src/task/wake.rs @@ -322,7 +322,7 @@ impl<'a> ContextBuilder<'a> { // SAFETY: LocalWaker is just Waker without thread safety let local_waker = unsafe { transmute(waker) }; Self { - waker: waker, + waker, local_waker, ext: ExtData::None(()), _marker: PhantomData, diff --git a/library/std/src/sys/pal/hermit/fs.rs b/library/std/src/sys/pal/hermit/fs.rs index 88fc40687195..783623552bb1 100644 --- a/library/std/src/sys/pal/hermit/fs.rs +++ b/library/std/src/sys/pal/hermit/fs.rs @@ -135,7 +135,7 @@ impl FileAttr { S_IFREG => DT_REG, _ => DT_UNKNOWN, }; - FileType { mode: mode } + FileType { mode } } } diff --git a/library/std/src/sys/pal/hermit/thread.rs b/library/std/src/sys/pal/hermit/thread.rs index 2a0b8dcb4ed6..4a7afddbec10 100644 --- a/library/std/src/sys/pal/hermit/thread.rs +++ b/library/std/src/sys/pal/hermit/thread.rs @@ -43,7 +43,7 @@ impl Thread { } Err(io::const_error!(io::ErrorKind::Uncategorized, "Unable to create thread!")) } else { - Ok(Thread { tid: tid }) + Ok(Thread { tid }) }; extern "C" fn thread_start(main: usize) { diff --git a/library/std/src/sys/pal/hermit/time.rs b/library/std/src/sys/pal/hermit/time.rs index e0b6eb76b03a..f76a5f96c875 100644 --- a/library/std/src/sys/pal/hermit/time.rs +++ b/library/std/src/sys/pal/hermit/time.rs @@ -22,7 +22,7 @@ impl Timespec { const fn new(tv_sec: i64, tv_nsec: i32) -> Timespec { assert!(tv_nsec >= 0 && tv_nsec < NSEC_PER_SEC); // SAFETY: The assert above checks tv_nsec is within the valid range - Timespec { t: timespec { tv_sec: tv_sec, tv_nsec: tv_nsec } } + Timespec { t: timespec { tv_sec, tv_nsec } } } fn sub_timespec(&self, other: &Timespec) -> Result { diff --git a/library/std/src/sys/pal/sgx/fd.rs b/library/std/src/sys/pal/sgx/fd.rs index c41b527cff79..3bb3189a1d12 100644 --- a/library/std/src/sys/pal/sgx/fd.rs +++ b/library/std/src/sys/pal/sgx/fd.rs @@ -12,7 +12,7 @@ pub struct FileDesc { impl FileDesc { pub fn new(fd: Fd) -> FileDesc { - FileDesc { fd: fd } + FileDesc { fd } } pub fn raw(&self) -> Fd { diff --git a/rustfmt.toml b/rustfmt.toml index 16a0d67ab527..8feeb60ca12c 100644 --- a/rustfmt.toml +++ b/rustfmt.toml @@ -4,6 +4,7 @@ use_small_heuristics = "Max" merge_derives = false group_imports = "StdExternalCrate" imports_granularity = "Module" +use_field_init_shorthand = true # Files to ignore. Each entry uses gitignore syntax, but `!` prefixes aren't allowed. ignore = [ diff --git a/src/tools/compiletest/src/read2.rs b/src/tools/compiletest/src/read2.rs index 2375f391d03d..62e675c77ae5 100644 --- a/src/tools/compiletest/src/read2.rs +++ b/src/tools/compiletest/src/read2.rs @@ -286,7 +286,7 @@ mod imp { impl<'a> Pipe<'a> { unsafe fn new(p: P, dst: &'a mut Vec) -> Pipe<'a> { Pipe { - dst: dst, + dst, pipe: NamedPipe::from_raw_handle(p.into_raw_handle()), overlapped: Overlapped::zero(), done: false, diff --git a/tests/codegen-units/item-collection/generic-impl.rs b/tests/codegen-units/item-collection/generic-impl.rs index 23d09e0d8af3..f6e49f6e6dfc 100644 --- a/tests/codegen-units/item-collection/generic-impl.rs +++ b/tests/codegen-units/item-collection/generic-impl.rs @@ -14,7 +14,7 @@ fn id(x: T) -> T { impl Struct { fn new(x: T) -> Struct { - Struct { x: x, f: id } + Struct { x, f: id } } fn get(self, x: T2) -> (T, T2) { diff --git a/tests/codegen/issues/issue-15953.rs b/tests/codegen/issues/issue-15953.rs index 28d28428904f..70e597ac1dd7 100644 --- a/tests/codegen/issues/issue-15953.rs +++ b/tests/codegen/issues/issue-15953.rs @@ -9,7 +9,7 @@ struct Foo { #[no_mangle] // CHECK: memcpy fn interior(x: Vec) -> Vec { - let Foo { x } = Foo { x: x }; + let Foo { x } = Foo { x }; x } diff --git a/tests/run-make/extern-fn-struct-passing-abi/test.rs b/tests/run-make/extern-fn-struct-passing-abi/test.rs index f898592fce98..928b1d4a9310 100644 --- a/tests/run-make/extern-fn-struct-passing-abi/test.rs +++ b/tests/run-make/extern-fn-struct-passing-abi/test.rs @@ -126,7 +126,7 @@ extern "C" { fn main() { let s = Rect { a: 553, b: 554, c: 555, d: 556 }; - let t = BiggerRect { s: s, a: 27834, b: 7657 }; + let t = BiggerRect { s, a: 27834, b: 7657 }; let u = FloatRect { a: 3489, b: 3490, c: 8. }; let v = Huge { a: 5647, b: 5648, c: 5649, d: 5650, e: 5651 }; let w = Huge64 { a: 1234, b: 1335, c: 1436, d: 1537, e: 1638 }; diff --git a/tests/run-make/symbols-include-type-name/lib.rs b/tests/run-make/symbols-include-type-name/lib.rs index 37d445917674..7fd42c8b4b47 100644 --- a/tests/run-make/symbols-include-type-name/lib.rs +++ b/tests/run-make/symbols-include-type-name/lib.rs @@ -4,7 +4,7 @@ pub struct Def { impl Def { pub fn new(id: i32) -> Def { - Def { id: id } + Def { id } } } From 28c6d0b55ba4369ea8e1073228c1b9821ea231d2 Mon Sep 17 00:00:00 2001 From: dianne Date: Tue, 17 Dec 2024 12:35:45 -0800 Subject: [PATCH 25/92] Add the edition guide link from the match 2024 migration lint to the error as well --- compiler/rustc_mir_build/src/thir/pattern/mod.rs | 4 ++++ .../rfc-3627-match-ergonomics-2024/migration_lint.stderr | 1 + .../min_match_ergonomics_fail.stderr | 7 +++++++ 3 files changed, 12 insertions(+) diff --git a/compiler/rustc_mir_build/src/thir/pattern/mod.rs b/compiler/rustc_mir_build/src/thir/pattern/mod.rs index 62bbb31440f8..bdf243c87b6f 100644 --- a/compiler/rustc_mir_build/src/thir/pattern/mod.rs +++ b/compiler/rustc_mir_build/src/thir/pattern/mod.rs @@ -70,6 +70,10 @@ pub(super) fn pat_from_hir<'a, 'tcx>( if is_hard_error { let mut err = tcx.dcx().struct_span_err(spans, fluent::mir_build_rust_2024_incompatible_pat); + if let Some(info) = lint::builtin::RUST_2024_INCOMPATIBLE_PAT.future_incompatible { + // provide the same reference link as the lint + err.note(format!("for more information, see {}", info.reference)); + } err.subdiagnostic(sugg); err.emit(); } else { diff --git a/tests/ui/pattern/rfc-3627-match-ergonomics-2024/migration_lint.stderr b/tests/ui/pattern/rfc-3627-match-ergonomics-2024/migration_lint.stderr index 73b0e4b67d91..83346b9dd4a8 100644 --- a/tests/ui/pattern/rfc-3627-match-ergonomics-2024/migration_lint.stderr +++ b/tests/ui/pattern/rfc-3627-match-ergonomics-2024/migration_lint.stderr @@ -210,6 +210,7 @@ LL | (Some(mut x), migration_lint_macros::mixed_edition_pat!(y)) => { | | | requires binding by-value, but the implicit default is by-reference | + = note: for more information, see = note: this error originates in the macro `migration_lint_macros::mixed_edition_pat` (in Nightly builds, run with -Z macro-backtrace for more info) help: make the implied reference pattern explicit | diff --git a/tests/ui/pattern/rfc-3627-match-ergonomics-2024/min_match_ergonomics_fail.stderr b/tests/ui/pattern/rfc-3627-match-ergonomics-2024/min_match_ergonomics_fail.stderr index 38de6e34cbcd..affdca1d4490 100644 --- a/tests/ui/pattern/rfc-3627-match-ergonomics-2024/min_match_ergonomics_fail.stderr +++ b/tests/ui/pattern/rfc-3627-match-ergonomics-2024/min_match_ergonomics_fail.stderr @@ -105,6 +105,7 @@ error: this pattern relies on behavior which may change in edition 2024 LL | test_pat_on_type![(&x,): &(&T,)]; | ^ cannot implicitly match against multiple layers of reference | + = note: for more information, see help: make the implied reference pattern explicit | LL | test_pat_on_type![&(&x,): &(&T,)]; @@ -116,6 +117,7 @@ error: this pattern relies on behavior which may change in edition 2024 LL | test_pat_on_type![(&mut x,): &(&mut T,)]; | ^^^^ cannot implicitly match against multiple layers of reference | + = note: for more information, see help: make the implied reference pattern explicit | LL | test_pat_on_type![&(&mut x,): &(&mut T,)]; @@ -127,6 +129,7 @@ error: this pattern relies on behavior which may change in edition 2024 LL | test_pat_on_type![Foo { f: &(x,) }: &Foo]; | ^ cannot implicitly match against multiple layers of reference | + = note: for more information, see help: make the implied reference pattern explicit | LL | test_pat_on_type![&Foo { f: &(x,) }: &Foo]; @@ -138,6 +141,7 @@ error: this pattern relies on behavior which may change in edition 2024 LL | test_pat_on_type![(mut x,): &(T,)]; | ^^^ requires binding by-value, but the implicit default is by-reference | + = note: for more information, see help: make the implied reference pattern explicit | LL | test_pat_on_type![&(mut x,): &(T,)]; @@ -149,6 +153,7 @@ error: this pattern relies on behavior which may change in edition 2024 LL | test_pat_on_type![(ref x,): &(T,)]; | ^^^ cannot override to bind by-reference when that is the implicit default | + = note: for more information, see help: make the implied reference pattern explicit | LL | test_pat_on_type![&(ref x,): &(T,)]; @@ -160,6 +165,7 @@ error: this pattern relies on behavior which may change in edition 2024 LL | test_pat_on_type![(ref mut x,): &mut (T,)]; | ^^^^^^^ cannot override to bind by-reference when that is the implicit default | + = note: for more information, see help: make the implied reference pattern explicit | LL | test_pat_on_type![&mut (ref mut x,): &mut (T,)]; @@ -171,6 +177,7 @@ error: this pattern relies on behavior which may change in edition 2024 LL | (&x,) => x, | ^ cannot implicitly match against multiple layers of reference | + = note: for more information, see help: make the implied reference pattern explicit | LL | &(&x,) => x, From 0bf6e82c540c838c277ef3ae54c2ac125391dde9 Mon Sep 17 00:00:00 2001 From: Nicholas Nethercote Date: Wed, 11 Dec 2024 14:13:04 +1100 Subject: [PATCH 26/92] Change the lookahead in `MacroParser::new`. As it happens, lookahead values of 0, 1, and 2 all work fine here, due to the structure of the code. (Values or 3 or greater cause test failures.) This commit changes the lookahead to zero because that will facilitate cleanups in subsequent commits. --- src/tools/rustfmt/src/macros.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/tools/rustfmt/src/macros.rs b/src/tools/rustfmt/src/macros.rs index 4083d9398f6b..fa281cab7241 100644 --- a/src/tools/rustfmt/src/macros.rs +++ b/src/tools/rustfmt/src/macros.rs @@ -1190,7 +1190,7 @@ impl<'a> MacroParser<'a> { // (`(` ... `)` `=>` `{` ... `}`)* fn parse(&mut self) -> Option { let mut branches = vec![]; - while self.toks.look_ahead(1).is_some() { + while self.toks.look_ahead(0).is_some() { branches.push(self.parse_branch()?); } From 3575e7943b4d4a47c30716c50884d4ceee1b7dcd Mon Sep 17 00:00:00 2001 From: Nicholas Nethercote Date: Wed, 11 Dec 2024 12:29:04 +1100 Subject: [PATCH 27/92] Simplify `RefTokenTreeCursor::look_ahead`. It's only ever used with a lookahead of 0, so this commit removes the lookahead and renames it `peek`. --- compiler/rustc_ast/src/tokenstream.rs | 4 ++-- compiler/rustc_expand/src/mbe/metavar_expr.rs | 10 +++++----- .../clippy/clippy_lints/src/crate_in_macro_def.rs | 2 +- src/tools/rustfmt/src/macros.rs | 4 ++-- 4 files changed, 10 insertions(+), 10 deletions(-) diff --git a/compiler/rustc_ast/src/tokenstream.rs b/compiler/rustc_ast/src/tokenstream.rs index c6b6addc946e..59e5ff9f7a5d 100644 --- a/compiler/rustc_ast/src/tokenstream.rs +++ b/compiler/rustc_ast/src/tokenstream.rs @@ -678,8 +678,8 @@ impl<'t> RefTokenTreeCursor<'t> { RefTokenTreeCursor { stream, index: 0 } } - pub fn look_ahead(&self, n: usize) -> Option<&TokenTree> { - self.stream.0.get(self.index + n) + pub fn peek(&self) -> Option<&TokenTree> { + self.stream.0.get(self.index) } } diff --git a/compiler/rustc_expand/src/mbe/metavar_expr.rs b/compiler/rustc_expand/src/mbe/metavar_expr.rs index 810a5d30c7ec..105e59bceceb 100644 --- a/compiler/rustc_expand/src/mbe/metavar_expr.rs +++ b/compiler/rustc_expand/src/mbe/metavar_expr.rs @@ -74,7 +74,7 @@ impl MetaVarExpr { } }; result.push(element); - if iter.look_ahead(0).is_none() { + if iter.peek().is_none() { break; } if !try_eat_comma(&mut iter) { @@ -166,7 +166,7 @@ fn parse_count<'psess>( eat_dollar(iter, psess, span)?; let ident = parse_ident(iter, psess, span)?; let depth = if try_eat_comma(iter) { - if iter.look_ahead(0).is_none() { + if iter.peek().is_none() { return Err(psess.dcx().struct_span_err( span, "`count` followed by a comma must have an associated index indicating its depth", @@ -252,7 +252,7 @@ fn parse_token<'psess, 't>( /// Tries to move the iterator forward returning `true` if there is a comma. If not, then the /// iterator is not modified and the result is `false`. fn try_eat_comma(iter: &mut RefTokenTreeCursor<'_>) -> bool { - if let Some(TokenTree::Token(Token { kind: token::Comma, .. }, _)) = iter.look_ahead(0) { + if let Some(TokenTree::Token(Token { kind: token::Comma, .. }, _)) = iter.peek() { let _ = iter.next(); return true; } @@ -262,7 +262,7 @@ fn try_eat_comma(iter: &mut RefTokenTreeCursor<'_>) -> bool { /// Tries to move the iterator forward returning `true` if there is a dollar sign. If not, then the /// iterator is not modified and the result is `false`. fn try_eat_dollar(iter: &mut RefTokenTreeCursor<'_>) -> bool { - if let Some(TokenTree::Token(Token { kind: token::Dollar, .. }, _)) = iter.look_ahead(0) { + if let Some(TokenTree::Token(Token { kind: token::Dollar, .. }, _)) = iter.peek() { let _ = iter.next(); return true; } @@ -275,7 +275,7 @@ fn eat_dollar<'psess>( psess: &'psess ParseSess, span: Span, ) -> PResult<'psess, ()> { - if let Some(TokenTree::Token(Token { kind: token::Dollar, .. }, _)) = iter.look_ahead(0) { + if let Some(TokenTree::Token(Token { kind: token::Dollar, .. }, _)) = iter.peek() { let _ = iter.next(); return Ok(()); } diff --git a/src/tools/clippy/clippy_lints/src/crate_in_macro_def.rs b/src/tools/clippy/clippy_lints/src/crate_in_macro_def.rs index c8f814137289..76b88b746cb4 100644 --- a/src/tools/clippy/clippy_lints/src/crate_in_macro_def.rs +++ b/src/tools/clippy/clippy_lints/src/crate_in_macro_def.rs @@ -86,7 +86,7 @@ fn contains_unhygienic_crate_reference(tts: &TokenStream) -> Option { while let Some(curr) = cursor.next() { if !prev_is_dollar && let Some(span) = is_crate_keyword(curr) - && let Some(next) = cursor.look_ahead(0) + && let Some(next) = cursor.peek() && is_token(next, &TokenKind::PathSep) { return Some(span); diff --git a/src/tools/rustfmt/src/macros.rs b/src/tools/rustfmt/src/macros.rs index fa281cab7241..dad074440b48 100644 --- a/src/tools/rustfmt/src/macros.rs +++ b/src/tools/rustfmt/src/macros.rs @@ -1190,7 +1190,7 @@ impl<'a> MacroParser<'a> { // (`(` ... `)` `=>` `{` ... `}`)* fn parse(&mut self) -> Option { let mut branches = vec![]; - while self.toks.look_ahead(0).is_some() { + while self.toks.peek().is_some() { branches.push(self.parse_branch()?); } @@ -1237,7 +1237,7 @@ impl<'a> MacroParser<'a> { span, }, _, - )) = self.toks.look_ahead(0) + )) = self.toks.peek() { hi = span.hi(); self.toks.next(); From 809975c94aa8dd69775a0caff819ebb0c81d1966 Mon Sep 17 00:00:00 2001 From: Nicholas Nethercote Date: Wed, 11 Dec 2024 14:38:09 +1100 Subject: [PATCH 28/92] Rename `RefTokenTreeCursor`. Because `TokenStreamIter` is a much better name for a `TokenStream` iterator. Also rename the `TokenStream::trees` method as `TokenStream::iter`, and some local variables. --- compiler/rustc_ast/src/attr/mod.rs | 54 +++++++++---------- compiler/rustc_ast/src/tokenstream.rs | 34 ++++++------ compiler/rustc_ast_pretty/src/pprust/state.rs | 2 +- .../rustc_builtin_macros/src/concat_idents.rs | 2 +- .../rustc_builtin_macros/src/trace_macros.rs | 6 +-- compiler/rustc_expand/src/mbe/metavar_expr.rs | 28 +++++----- compiler/rustc_expand/src/mbe/quoted.rs | 42 +++++++-------- .../rustc_expand/src/proc_macro_server.rs | 4 +- compiler/rustc_lint/src/builtin.rs | 2 +- ..._expr_fragment_specifier_2024_migration.rs | 2 +- compiler/rustc_parse/src/parser/tests.rs | 10 ++-- .../src/parser/tokenstream/tests.rs | 8 +-- src/librustdoc/clean/mod.rs | 2 +- src/librustdoc/clean/render_macro_matchers.rs | 2 +- .../src/attrs/should_panic_without_expect.rs | 2 +- .../clippy_lints/src/crate_in_macro_def.rs | 6 +-- src/tools/rustfmt/src/macros.rs | 30 +++++------ 17 files changed, 117 insertions(+), 119 deletions(-) diff --git a/compiler/rustc_ast/src/attr/mod.rs b/compiler/rustc_ast/src/attr/mod.rs index 8ee3d4d590cd..2f757f75166d 100644 --- a/compiler/rustc_ast/src/attr/mod.rs +++ b/compiler/rustc_ast/src/attr/mod.rs @@ -366,12 +366,12 @@ impl MetaItem { } } - fn from_tokens<'a, I>(tokens: &mut iter::Peekable) -> Option + fn from_tokens<'a, I>(iter: &mut iter::Peekable) -> Option where I: Iterator, { // FIXME: Share code with `parse_path`. - let tt = tokens.next().map(|tt| TokenTree::uninterpolate(tt)); + let tt = iter.next().map(|tt| TokenTree::uninterpolate(tt)); let path = match tt.as_deref() { Some(&TokenTree::Token( Token { kind: ref kind @ (token::Ident(..) | token::PathSep), span }, @@ -379,9 +379,9 @@ impl MetaItem { )) => 'arm: { let mut segments = if let &token::Ident(name, _) = kind { if let Some(TokenTree::Token(Token { kind: token::PathSep, .. }, _)) = - tokens.peek() + iter.peek() { - tokens.next(); + iter.next(); thin_vec![PathSegment::from_ident(Ident::new(name, span))] } else { break 'arm Path::from_ident(Ident::new(name, span)); @@ -391,16 +391,16 @@ impl MetaItem { }; loop { if let Some(&TokenTree::Token(Token { kind: token::Ident(name, _), span }, _)) = - tokens.next().map(|tt| TokenTree::uninterpolate(tt)).as_deref() + iter.next().map(|tt| TokenTree::uninterpolate(tt)).as_deref() { segments.push(PathSegment::from_ident(Ident::new(name, span))); } else { return None; } if let Some(TokenTree::Token(Token { kind: token::PathSep, .. }, _)) = - tokens.peek() + iter.peek() { - tokens.next(); + iter.next(); } else { break; } @@ -421,8 +421,8 @@ impl MetaItem { } _ => return None, }; - let list_closing_paren_pos = tokens.peek().map(|tt| tt.span().hi()); - let kind = MetaItemKind::from_tokens(tokens)?; + let list_closing_paren_pos = iter.peek().map(|tt| tt.span().hi()); + let kind = MetaItemKind::from_tokens(iter)?; let hi = match &kind { MetaItemKind::NameValue(lit) => lit.span.hi(), MetaItemKind::List(..) => list_closing_paren_pos.unwrap_or(path.span.hi()), @@ -439,12 +439,12 @@ impl MetaItem { impl MetaItemKind { // public because it can be called in the hir pub fn list_from_tokens(tokens: TokenStream) -> Option> { - let mut tokens = tokens.trees().peekable(); + let mut iter = tokens.iter().peekable(); let mut result = ThinVec::new(); - while tokens.peek().is_some() { - let item = MetaItemInner::from_tokens(&mut tokens)?; + while iter.peek().is_some() { + let item = MetaItemInner::from_tokens(&mut iter)?; result.push(item); - match tokens.next() { + match iter.next() { None | Some(TokenTree::Token(Token { kind: token::Comma, .. }, _)) => {} _ => return None, } @@ -453,11 +453,11 @@ impl MetaItemKind { } fn name_value_from_tokens<'a>( - tokens: &mut impl Iterator, + iter: &mut impl Iterator, ) -> Option { - match tokens.next() { + match iter.next() { Some(TokenTree::Delimited(.., Delimiter::Invisible(_), inner_tokens)) => { - MetaItemKind::name_value_from_tokens(&mut inner_tokens.trees()) + MetaItemKind::name_value_from_tokens(&mut inner_tokens.iter()) } Some(TokenTree::Token(token, _)) => { MetaItemLit::from_token(token).map(MetaItemKind::NameValue) @@ -467,18 +467,18 @@ impl MetaItemKind { } fn from_tokens<'a>( - tokens: &mut iter::Peekable>, + iter: &mut iter::Peekable>, ) -> Option { - match tokens.peek() { + match iter.peek() { Some(TokenTree::Delimited(.., Delimiter::Parenthesis, inner_tokens)) => { let inner_tokens = inner_tokens.clone(); - tokens.next(); + iter.next(); MetaItemKind::list_from_tokens(inner_tokens).map(MetaItemKind::List) } Some(TokenTree::Delimited(..)) => None, Some(TokenTree::Token(Token { kind: token::Eq, .. }, _)) => { - tokens.next(); - MetaItemKind::name_value_from_tokens(tokens) + iter.next(); + MetaItemKind::name_value_from_tokens(iter) } _ => Some(MetaItemKind::Word), } @@ -594,22 +594,22 @@ impl MetaItemInner { self.meta_item().is_some() } - fn from_tokens<'a, I>(tokens: &mut iter::Peekable) -> Option + fn from_tokens<'a, I>(iter: &mut iter::Peekable) -> Option where I: Iterator, { - match tokens.peek() { + match iter.peek() { Some(TokenTree::Token(token, _)) if let Some(lit) = MetaItemLit::from_token(token) => { - tokens.next(); + iter.next(); return Some(MetaItemInner::Lit(lit)); } Some(TokenTree::Delimited(.., Delimiter::Invisible(_), inner_tokens)) => { - tokens.next(); - return MetaItemInner::from_tokens(&mut inner_tokens.trees().peekable()); + iter.next(); + return MetaItemInner::from_tokens(&mut inner_tokens.iter().peekable()); } _ => {} } - MetaItem::from_tokens(tokens).map(MetaItemInner::MetaItem) + MetaItem::from_tokens(iter).map(MetaItemInner::MetaItem) } } diff --git a/compiler/rustc_ast/src/tokenstream.rs b/compiler/rustc_ast/src/tokenstream.rs index 59e5ff9f7a5d..9f7ba9286922 100644 --- a/compiler/rustc_ast/src/tokenstream.rs +++ b/compiler/rustc_ast/src/tokenstream.rs @@ -99,7 +99,7 @@ where CTX: crate::HashStableContext, { fn hash_stable(&self, hcx: &mut CTX, hasher: &mut StableHasher) { - for sub_tt in self.trees() { + for sub_tt in self.iter() { sub_tt.hash_stable(hcx, hasher); } } @@ -406,7 +406,7 @@ impl Eq for TokenStream {} impl PartialEq for TokenStream { fn eq(&self, other: &TokenStream) -> bool { - self.trees().eq(other.trees()) + self.iter().eq(other.iter()) } } @@ -423,8 +423,8 @@ impl TokenStream { self.0.len() } - pub fn trees(&self) -> RefTokenTreeCursor<'_> { - RefTokenTreeCursor::new(self) + pub fn iter(&self) -> TokenStreamIter<'_> { + TokenStreamIter::new(self) } pub fn into_trees(self) -> TokenTreeCursor { @@ -433,14 +433,14 @@ impl TokenStream { /// Compares two `TokenStream`s, checking equality without regarding span information. pub fn eq_unspanned(&self, other: &TokenStream) -> bool { - let mut t1 = self.trees(); - let mut t2 = other.trees(); - for (t1, t2) in iter::zip(&mut t1, &mut t2) { - if !t1.eq_unspanned(t2) { + let mut iter1 = self.iter(); + let mut iter2 = other.iter(); + for (tt1, tt2) in iter::zip(&mut iter1, &mut iter2) { + if !tt1.eq_unspanned(tt2) { return false; } } - t1.next().is_none() && t2.next().is_none() + iter1.next().is_none() && iter2.next().is_none() } /// Create a token stream containing a single token with alone spacing. The @@ -509,7 +509,7 @@ impl TokenStream { #[must_use] pub fn flattened(&self) -> TokenStream { fn can_skip(stream: &TokenStream) -> bool { - stream.trees().all(|tree| match tree { + stream.iter().all(|tree| match tree { TokenTree::Token(token, _) => !matches!( token.kind, token::NtIdent(..) | token::NtLifetime(..) | token::Interpolated(..) @@ -522,7 +522,7 @@ impl TokenStream { return self.clone(); } - self.trees().map(|tree| TokenStream::flatten_token_tree(tree)).collect() + self.iter().map(|tree| TokenStream::flatten_token_tree(tree)).collect() } // If `vec` is not empty, try to glue `tt` onto its last token. The return @@ -665,17 +665,15 @@ impl TokenStream { } } -/// By-reference iterator over a [`TokenStream`], that produces `&TokenTree` -/// items. #[derive(Clone)] -pub struct RefTokenTreeCursor<'t> { +pub struct TokenStreamIter<'t> { stream: &'t TokenStream, index: usize, } -impl<'t> RefTokenTreeCursor<'t> { +impl<'t> TokenStreamIter<'t> { fn new(stream: &'t TokenStream) -> Self { - RefTokenTreeCursor { stream, index: 0 } + TokenStreamIter { stream, index: 0 } } pub fn peek(&self) -> Option<&TokenTree> { @@ -683,7 +681,7 @@ impl<'t> RefTokenTreeCursor<'t> { } } -impl<'t> Iterator for RefTokenTreeCursor<'t> { +impl<'t> Iterator for TokenStreamIter<'t> { type Item = &'t TokenTree; fn next(&mut self) -> Option<&'t TokenTree> { @@ -701,7 +699,7 @@ impl<'t> Iterator for RefTokenTreeCursor<'t> { /// return `&T` from `next`; the need for an explicit lifetime in the `Item` /// associated type gets in the way. Instead, use `next_ref` (which doesn't /// involve associated types) for getting individual elements, or -/// `RefTokenTreeCursor` if you really want an `Iterator`, e.g. in a `for` +/// `TokenStreamIter` if you really want an `Iterator`, e.g. in a `for` /// loop. #[derive(Clone, Debug)] pub struct TokenTreeCursor { diff --git a/compiler/rustc_ast_pretty/src/pprust/state.rs b/compiler/rustc_ast_pretty/src/pprust/state.rs index cbb92c8c30f0..aa551d2f07d4 100644 --- a/compiler/rustc_ast_pretty/src/pprust/state.rs +++ b/compiler/rustc_ast_pretty/src/pprust/state.rs @@ -725,7 +725,7 @@ pub trait PrintState<'a>: std::ops::Deref + std::ops::Dere // E.g. we have seen cases where a proc macro can handle `a :: b` but not // `a::b`. See #117433 for some examples. fn print_tts(&mut self, tts: &TokenStream, convert_dollar_crate: bool) { - let mut iter = tts.trees().peekable(); + let mut iter = tts.iter().peekable(); while let Some(tt) = iter.next() { let spacing = self.print_tt(tt, convert_dollar_crate); if let Some(next) = iter.peek() { diff --git a/compiler/rustc_builtin_macros/src/concat_idents.rs b/compiler/rustc_builtin_macros/src/concat_idents.rs index b459cc3007d3..532f62596271 100644 --- a/compiler/rustc_builtin_macros/src/concat_idents.rs +++ b/compiler/rustc_builtin_macros/src/concat_idents.rs @@ -19,7 +19,7 @@ pub(crate) fn expand_concat_idents<'cx>( } let mut res_str = String::new(); - for (i, e) in tts.trees().enumerate() { + for (i, e) in tts.iter().enumerate() { if i & 1 == 1 { match e { TokenTree::Token(Token { kind: token::Comma, .. }, _) => {} diff --git a/compiler/rustc_builtin_macros/src/trace_macros.rs b/compiler/rustc_builtin_macros/src/trace_macros.rs index e624d1da66bd..01e4c403203b 100644 --- a/compiler/rustc_builtin_macros/src/trace_macros.rs +++ b/compiler/rustc_builtin_macros/src/trace_macros.rs @@ -10,9 +10,9 @@ pub(crate) fn expand_trace_macros( sp: Span, tt: TokenStream, ) -> MacroExpanderResult<'static> { - let mut cursor = tt.trees(); + let mut iter = tt.iter(); let mut err = false; - let value = match &cursor.next() { + let value = match iter.next() { Some(TokenTree::Token(token, _)) if token.is_keyword(kw::True) => true, Some(TokenTree::Token(token, _)) if token.is_keyword(kw::False) => false, _ => { @@ -20,7 +20,7 @@ pub(crate) fn expand_trace_macros( false } }; - err |= cursor.next().is_some(); + err |= iter.next().is_some(); if err { cx.dcx().emit_err(errors::TraceMacros { span: sp }); } else { diff --git a/compiler/rustc_expand/src/mbe/metavar_expr.rs b/compiler/rustc_expand/src/mbe/metavar_expr.rs index 105e59bceceb..cc1ae4b6f6cc 100644 --- a/compiler/rustc_expand/src/mbe/metavar_expr.rs +++ b/compiler/rustc_expand/src/mbe/metavar_expr.rs @@ -1,5 +1,5 @@ use rustc_ast::token::{self, Delimiter, IdentIsRaw, Lit, Token, TokenKind}; -use rustc_ast::tokenstream::{RefTokenTreeCursor, TokenStream, TokenTree}; +use rustc_ast::tokenstream::{TokenStream, TokenStreamIter, TokenTree}; use rustc_ast::{LitIntType, LitKind}; use rustc_ast_pretty::pprust; use rustc_errors::{Applicability, PResult}; @@ -39,14 +39,14 @@ impl MetaVarExpr { outer_span: Span, psess: &'psess ParseSess, ) -> PResult<'psess, MetaVarExpr> { - let mut tts = input.trees(); - let ident = parse_ident(&mut tts, psess, outer_span)?; - let Some(TokenTree::Delimited(.., Delimiter::Parenthesis, args)) = tts.next() else { + let mut iter = input.iter(); + let ident = parse_ident(&mut iter, psess, outer_span)?; + let Some(TokenTree::Delimited(.., Delimiter::Parenthesis, args)) = iter.next() else { let msg = "meta-variable expression parameter must be wrapped in parentheses"; return Err(psess.dcx().struct_span_err(ident.span, msg)); }; - check_trailing_token(&mut tts, psess)?; - let mut iter = args.trees(); + check_trailing_token(&mut iter, psess)?; + let mut iter = args.iter(); let rslt = match ident.as_str() { "concat" => { let mut result = Vec::new(); @@ -143,7 +143,7 @@ pub(crate) enum MetaVarExprConcatElem { // Checks if there are any remaining tokens. For example, `${ignore(ident ... a b c ...)}` fn check_trailing_token<'psess>( - iter: &mut RefTokenTreeCursor<'_>, + iter: &mut TokenStreamIter<'_>, psess: &'psess ParseSess, ) -> PResult<'psess, ()> { if let Some(tt) = iter.next() { @@ -159,7 +159,7 @@ fn check_trailing_token<'psess>( /// Parse a meta-variable `count` expression: `count(ident[, depth])` fn parse_count<'psess>( - iter: &mut RefTokenTreeCursor<'_>, + iter: &mut TokenStreamIter<'_>, psess: &'psess ParseSess, span: Span, ) -> PResult<'psess, MetaVarExpr> { @@ -181,7 +181,7 @@ fn parse_count<'psess>( /// Parses the depth used by index(depth) and len(depth). fn parse_depth<'psess>( - iter: &mut RefTokenTreeCursor<'_>, + iter: &mut TokenStreamIter<'_>, psess: &'psess ParseSess, span: Span, ) -> PResult<'psess, usize> { @@ -204,7 +204,7 @@ fn parse_depth<'psess>( /// Parses an generic ident fn parse_ident<'psess>( - iter: &mut RefTokenTreeCursor<'_>, + iter: &mut TokenStreamIter<'_>, psess: &'psess ParseSess, fallback_span: Span, ) -> PResult<'psess, Ident> { @@ -236,7 +236,7 @@ fn parse_ident_from_token<'psess>( } fn parse_token<'psess, 't>( - iter: &mut RefTokenTreeCursor<'t>, + iter: &mut TokenStreamIter<'t>, psess: &'psess ParseSess, fallback_span: Span, ) -> PResult<'psess, &'t Token> { @@ -251,7 +251,7 @@ fn parse_token<'psess, 't>( /// Tries to move the iterator forward returning `true` if there is a comma. If not, then the /// iterator is not modified and the result is `false`. -fn try_eat_comma(iter: &mut RefTokenTreeCursor<'_>) -> bool { +fn try_eat_comma(iter: &mut TokenStreamIter<'_>) -> bool { if let Some(TokenTree::Token(Token { kind: token::Comma, .. }, _)) = iter.peek() { let _ = iter.next(); return true; @@ -261,7 +261,7 @@ fn try_eat_comma(iter: &mut RefTokenTreeCursor<'_>) -> bool { /// Tries to move the iterator forward returning `true` if there is a dollar sign. If not, then the /// iterator is not modified and the result is `false`. -fn try_eat_dollar(iter: &mut RefTokenTreeCursor<'_>) -> bool { +fn try_eat_dollar(iter: &mut TokenStreamIter<'_>) -> bool { if let Some(TokenTree::Token(Token { kind: token::Dollar, .. }, _)) = iter.peek() { let _ = iter.next(); return true; @@ -271,7 +271,7 @@ fn try_eat_dollar(iter: &mut RefTokenTreeCursor<'_>) -> bool { /// Expects that the next item is a dollar sign. fn eat_dollar<'psess>( - iter: &mut RefTokenTreeCursor<'_>, + iter: &mut TokenStreamIter<'_>, psess: &'psess ParseSess, span: Span, ) -> PResult<'psess, ()> { diff --git a/compiler/rustc_expand/src/mbe/quoted.rs b/compiler/rustc_expand/src/mbe/quoted.rs index 36094707face..f8975aff1c3b 100644 --- a/compiler/rustc_expand/src/mbe/quoted.rs +++ b/compiler/rustc_expand/src/mbe/quoted.rs @@ -49,25 +49,25 @@ pub(super) fn parse( // For each token tree in `input`, parse the token into a `self::TokenTree`, consuming // additional trees if need be. - let mut trees = input.trees().peekable(); - while let Some(tree) = trees.next() { + let mut iter = input.iter().peekable(); + while let Some(tree) = iter.next() { // Given the parsed tree, if there is a metavar and we are expecting matchers, actually // parse out the matcher (i.e., in `$id:ident` this would parse the `:` and `ident`). - let tree = parse_tree(tree, &mut trees, parsing_patterns, sess, node_id, features, edition); + let tree = parse_tree(tree, &mut iter, parsing_patterns, sess, node_id, features, edition); match tree { TokenTree::MetaVar(start_sp, ident) if parsing_patterns => { // Not consuming the next token immediately, as it may not be a colon - let span = match trees.peek() { + let span = match iter.peek() { Some(&tokenstream::TokenTree::Token( Token { kind: token::Colon, span: colon_span }, _, )) => { // Consume the colon first - trees.next(); + iter.next(); // It's ok to consume the next tree no matter how, // since if it's not a token then it will be an invalid declaration. - match trees.next() { + match iter.next() { Some(tokenstream::TokenTree::Token(token, _)) => match token.ident() { Some((fragment, _)) => { let span = token.span.with_lo(start_sp.lo()); @@ -143,14 +143,14 @@ fn maybe_emit_macro_metavar_expr_concat_feature(features: &Features, sess: &Sess /// # Parameters /// /// - `tree`: the tree we wish to convert. -/// - `outer_trees`: an iterator over trees. We may need to read more tokens from it in order to finish +/// - `outer_iter`: an iterator over trees. We may need to read more tokens from it in order to finish /// converting `tree` /// - `parsing_patterns`: same as [parse]. /// - `sess`: the parsing session. Any errors will be emitted to this session. /// - `features`: language features so we can do feature gating. fn parse_tree<'a>( tree: &'a tokenstream::TokenTree, - outer_trees: &mut impl Iterator, + outer_iter: &mut impl Iterator, parsing_patterns: bool, sess: &Session, node_id: NodeId, @@ -163,14 +163,14 @@ fn parse_tree<'a>( &tokenstream::TokenTree::Token(Token { kind: token::Dollar, span: dollar_span }, _) => { // FIXME: Handle `Invisible`-delimited groups in a more systematic way // during parsing. - let mut next = outer_trees.next(); - let mut trees: Box>; + let mut next = outer_iter.next(); + let mut iter: Box>; match next { Some(tokenstream::TokenTree::Delimited(.., delim, tts)) if delim.skip() => { - trees = Box::new(tts.trees()); - next = trees.next(); + iter = Box::new(tts.iter()); + next = iter.next(); } - _ => trees = Box::new(outer_trees), + _ => iter = Box::new(outer_iter), } match next { @@ -230,7 +230,7 @@ fn parse_tree<'a>( let sequence = parse(tts, parsing_patterns, sess, node_id, features, edition); // Get the Kleene operator and optional separator let (separator, kleene) = - parse_sep_and_kleene_op(&mut trees, delim_span.entire(), sess); + parse_sep_and_kleene_op(&mut iter, delim_span.entire(), sess); // Count the number of captured "names" (i.e., named metavars) let num_captures = if parsing_patterns { count_metavar_decls(&sequence) } else { 0 }; @@ -314,10 +314,10 @@ fn kleene_op(token: &Token) -> Option { /// - Ok(Err(tok, span)) if the next token tree is a token but not a KleeneOp /// - Err(span) if the next token tree is not a token fn parse_kleene_op<'a>( - input: &mut impl Iterator, + iter: &mut impl Iterator, span: Span, ) -> Result, Span> { - match input.next() { + match iter.next() { Some(tokenstream::TokenTree::Token(token, _)) => match kleene_op(token) { Some(op) => Ok(Ok((op, token.span))), None => Ok(Err(token.clone())), @@ -334,22 +334,22 @@ fn parse_kleene_op<'a>( /// itself. Note that here we are parsing the _macro_ itself, rather than trying to match some /// stream of tokens in an invocation of a macro. /// -/// This function will take some input iterator `input` corresponding to `span` and a parsing -/// session `sess`. If the next one (or possibly two) tokens in `input` correspond to a Kleene +/// This function will take some input iterator `iter` corresponding to `span` and a parsing +/// session `sess`. If the next one (or possibly two) tokens in `iter` correspond to a Kleene /// operator and separator, then a tuple with `(separator, KleeneOp)` is returned. Otherwise, an /// error with the appropriate span is emitted to `sess` and a dummy value is returned. fn parse_sep_and_kleene_op<'a>( - input: &mut impl Iterator, + iter: &mut impl Iterator, span: Span, sess: &Session, ) -> (Option, KleeneToken) { // We basically look at two token trees here, denoted as #1 and #2 below - let span = match parse_kleene_op(input, span) { + let span = match parse_kleene_op(iter, span) { // #1 is a `?`, `+`, or `*` KleeneOp Ok(Ok((op, span))) => return (None, KleeneToken::new(op, span)), // #1 is a separator followed by #2, a KleeneOp - Ok(Err(token)) => match parse_kleene_op(input, token.span) { + Ok(Err(token)) => match parse_kleene_op(iter, token.span) { // #2 is the `?` Kleene op, which does not take a separator (error) Ok(Ok((KleeneOp::ZeroOrOne, span))) => { // Error! diff --git a/compiler/rustc_expand/src/proc_macro_server.rs b/compiler/rustc_expand/src/proc_macro_server.rs index 263df235b3ec..bb201089fa54 100644 --- a/compiler/rustc_expand/src/proc_macro_server.rs +++ b/compiler/rustc_expand/src/proc_macro_server.rs @@ -112,9 +112,9 @@ impl FromInternal<(TokenStream, &mut Rustc<'_, '_>)> for Vec { let delimiter = pm::Delimiter::from_internal(delim); diff --git a/compiler/rustc_lint/src/builtin.rs b/compiler/rustc_lint/src/builtin.rs index d43fe27aa036..3b8bc66bab7d 100644 --- a/compiler/rustc_lint/src/builtin.rs +++ b/compiler/rustc_lint/src/builtin.rs @@ -1829,7 +1829,7 @@ impl KeywordIdents { fn check_tokens(&mut self, cx: &EarlyContext<'_>, tokens: &TokenStream) { // Check if the preceding token is `$`, because we want to allow `$async`, etc. let mut prev_dollar = false; - for tt in tokens.trees() { + for tt in tokens.iter() { match tt { // Only report non-raw idents. TokenTree::Token(token, _) => { diff --git a/compiler/rustc_lint/src/macro_expr_fragment_specifier_2024_migration.rs b/compiler/rustc_lint/src/macro_expr_fragment_specifier_2024_migration.rs index 23f4f7289067..ce280fef8b62 100644 --- a/compiler/rustc_lint/src/macro_expr_fragment_specifier_2024_migration.rs +++ b/compiler/rustc_lint/src/macro_expr_fragment_specifier_2024_migration.rs @@ -84,7 +84,7 @@ impl Expr2024 { let mut prev_colon = false; let mut prev_identifier = false; let mut prev_dollar = false; - for tt in tokens.trees() { + for tt in tokens.iter() { debug!( "check_tokens: {:?} - colon {prev_dollar} - ident {prev_identifier} - colon {prev_colon}", tt diff --git a/compiler/rustc_parse/src/parser/tests.rs b/compiler/rustc_parse/src/parser/tests.rs index 1813960dad05..da1ff8f1273c 100644 --- a/compiler/rustc_parse/src/parser/tests.rs +++ b/compiler/rustc_parse/src/parser/tests.rs @@ -2285,7 +2285,7 @@ fn bad_path_expr_1() { fn string_to_tts_macro() { create_default_session_globals_then(|| { let stream = string_to_stream("macro_rules! zip (($a)=>($a))".to_string()); - let tts = &stream.trees().collect::>()[..]; + let tts = &stream.iter().collect::>()[..]; match tts { [ @@ -2297,14 +2297,14 @@ fn string_to_tts_macro() { TokenTree::Token(Token { kind: token::Ident(name_zip, IdentIsRaw::No), .. }, _), TokenTree::Delimited(.., macro_delim, macro_tts), ] if name_macro_rules == &kw::MacroRules && name_zip.as_str() == "zip" => { - let tts = ¯o_tts.trees().collect::>(); + let tts = ¯o_tts.iter().collect::>(); match &tts[..] { [ TokenTree::Delimited(.., first_delim, first_tts), TokenTree::Token(Token { kind: token::FatArrow, .. }, _), TokenTree::Delimited(.., second_delim, second_tts), ] if macro_delim == &Delimiter::Parenthesis => { - let tts = &first_tts.trees().collect::>(); + let tts = &first_tts.iter().collect::>(); match &tts[..] { [ TokenTree::Token(Token { kind: token::Dollar, .. }, _), @@ -2316,7 +2316,7 @@ fn string_to_tts_macro() { } _ => panic!("value 3: {:?} {:?}", first_delim, first_tts), } - let tts = &second_tts.trees().collect::>(); + let tts = &second_tts.iter().collect::>(); match &tts[..] { [ TokenTree::Token(Token { kind: token::Dollar, .. }, _), @@ -2544,7 +2544,7 @@ fn ttdelim_span() { .unwrap(); let ast::ExprKind::MacCall(mac) = &expr.kind else { panic!("not a macro") }; - let span = mac.args.tokens.trees().last().unwrap().span(); + let span = mac.args.tokens.iter().last().unwrap().span(); match psess.source_map().span_to_snippet(span) { Ok(s) => assert_eq!(&s[..], "{ body }"), diff --git a/compiler/rustc_parse/src/parser/tokenstream/tests.rs b/compiler/rustc_parse/src/parser/tokenstream/tests.rs index b13b68c266a0..037b5b1a9de5 100644 --- a/compiler/rustc_parse/src/parser/tokenstream/tests.rs +++ b/compiler/rustc_parse/src/parser/tokenstream/tests.rs @@ -23,8 +23,8 @@ fn test_concat() { let mut eq_res = TokenStream::default(); eq_res.push_stream(test_fst); eq_res.push_stream(test_snd); - assert_eq!(test_res.trees().count(), 5); - assert_eq!(eq_res.trees().count(), 5); + assert_eq!(test_res.iter().count(), 5); + assert_eq!(eq_res.iter().count(), 5); assert_eq!(test_res.eq_unspanned(&eq_res), true); }) } @@ -33,7 +33,7 @@ fn test_concat() { fn test_to_from_bijection() { create_default_session_globals_then(|| { let test_start = string_to_ts("foo::bar(baz)"); - let test_end = test_start.trees().cloned().collect(); + let test_end = test_start.iter().cloned().collect(); assert_eq!(test_start, test_end) }) } @@ -105,6 +105,6 @@ fn test_dotdotdot() { stream.push_tree(TokenTree::token_joint(token::Dot, sp(1, 2))); stream.push_tree(TokenTree::token_alone(token::Dot, sp(2, 3))); assert!(stream.eq_unspanned(&string_to_ts("..."))); - assert_eq!(stream.trees().count(), 1); + assert_eq!(stream.iter().count(), 1); }) } diff --git a/src/librustdoc/clean/mod.rs b/src/librustdoc/clean/mod.rs index 9903d0faf438..e6cb1165c063 100644 --- a/src/librustdoc/clean/mod.rs +++ b/src/librustdoc/clean/mod.rs @@ -2604,7 +2604,7 @@ fn filter_tokens_from_list( ) -> Vec { let mut tokens = Vec::with_capacity(args_tokens.len()); let mut skip_next_comma = false; - for token in args_tokens.trees() { + for token in args_tokens.iter() { match token { TokenTree::Token(Token { kind: TokenKind::Comma, .. }, _) if skip_next_comma => { skip_next_comma = false; diff --git a/src/librustdoc/clean/render_macro_matchers.rs b/src/librustdoc/clean/render_macro_matchers.rs index d39ecf83ac01..3cc5f8d615a4 100644 --- a/src/librustdoc/clean/render_macro_matchers.rs +++ b/src/librustdoc/clean/render_macro_matchers.rs @@ -131,7 +131,7 @@ fn print_tts(printer: &mut Printer<'_>, tts: &TokenStream) { use State::*; let mut state = Start; - for tt in tts.trees() { + for tt in tts.iter() { let (needs_space, next_state) = match &tt { TokenTree::Token(tt, _) => match (state, &tt.kind) { (Dollar, token::Ident(..)) => (false, DollarIdent), diff --git a/src/tools/clippy/clippy_lints/src/attrs/should_panic_without_expect.rs b/src/tools/clippy/clippy_lints/src/attrs/should_panic_without_expect.rs index b4ed8a68a325..fd27e30a67f3 100644 --- a/src/tools/clippy/clippy_lints/src/attrs/should_panic_without_expect.rs +++ b/src/tools/clippy/clippy_lints/src/attrs/should_panic_without_expect.rs @@ -15,7 +15,7 @@ pub(super) fn check(cx: &EarlyContext<'_>, attr: &Attribute) { } if let AttrArgs::Delimited(args) = &normal_attr.item.args - && let mut tt_iter = args.tokens.trees() + && let mut tt_iter = args.tokens.iter() && let Some(TokenTree::Token( Token { kind: TokenKind::Ident(sym::expected, _), diff --git a/src/tools/clippy/clippy_lints/src/crate_in_macro_def.rs b/src/tools/clippy/clippy_lints/src/crate_in_macro_def.rs index 76b88b746cb4..7d86bd3e540a 100644 --- a/src/tools/clippy/clippy_lints/src/crate_in_macro_def.rs +++ b/src/tools/clippy/clippy_lints/src/crate_in_macro_def.rs @@ -82,11 +82,11 @@ fn is_macro_export(attr: &Attribute) -> bool { fn contains_unhygienic_crate_reference(tts: &TokenStream) -> Option { let mut prev_is_dollar = false; - let mut cursor = tts.trees(); - while let Some(curr) = cursor.next() { + let mut iter = tts.iter(); + while let Some(curr) = iter.next() { if !prev_is_dollar && let Some(span) = is_crate_keyword(curr) - && let Some(next) = cursor.peek() + && let Some(next) = iter.peek() && is_token(next, &TokenKind::PathSep) { return Some(span); diff --git a/src/tools/rustfmt/src/macros.rs b/src/tools/rustfmt/src/macros.rs index dad074440b48..ea8ca38cb772 100644 --- a/src/tools/rustfmt/src/macros.rs +++ b/src/tools/rustfmt/src/macros.rs @@ -13,7 +13,7 @@ use std::collections::HashMap; use std::panic::{AssertUnwindSafe, catch_unwind}; use rustc_ast::token::{BinOpToken, Delimiter, Token, TokenKind}; -use rustc_ast::tokenstream::{RefTokenTreeCursor, TokenStream, TokenTree}; +use rustc_ast::tokenstream::{TokenStream, TokenStreamIter, TokenTree}; use rustc_ast::{ast, ptr}; use rustc_ast_pretty::pprust; use rustc_span::{ @@ -443,7 +443,7 @@ pub(crate) fn rewrite_macro_def( } let ts = def.body.tokens.clone(); - let mut parser = MacroParser::new(ts.trees()); + let mut parser = MacroParser::new(ts.iter()); let parsed_def = match parser.parse() { Some(def) => def, None => return snippet, @@ -794,7 +794,7 @@ impl MacroArgParser { self.buf.clear(); } - fn add_meta_variable(&mut self, iter: &mut RefTokenTreeCursor<'_>) -> Option<()> { + fn add_meta_variable(&mut self, iter: &mut TokenStreamIter<'_>) -> Option<()> { match iter.next() { Some(&TokenTree::Token( Token { @@ -826,7 +826,7 @@ impl MacroArgParser { &mut self, inner: Vec, delim: Delimiter, - iter: &mut RefTokenTreeCursor<'_>, + iter: &mut TokenStreamIter<'_>, ) -> Option<()> { let mut buffer = String::new(); let mut first = true; @@ -926,7 +926,7 @@ impl MacroArgParser { /// Returns a collection of parsed macro def's arguments. fn parse(mut self, tokens: TokenStream) -> Option> { - let mut iter = tokens.trees(); + let mut iter = tokens.iter(); while let Some(tok) = iter.next() { match tok { @@ -1063,7 +1063,7 @@ fn format_macro_args( } fn span_for_token_stream(token_stream: &TokenStream) -> Option { - token_stream.trees().next().map(|tt| tt.span()) + token_stream.iter().next().map(|tt| tt.span()) } // We should insert a space if the next token is a: @@ -1179,18 +1179,18 @@ pub(crate) fn macro_style(mac: &ast::MacCall, context: &RewriteContext<'_>) -> D // A very simple parser that just parses a macros 2.0 definition into its branches. // Currently we do not attempt to parse any further than that. struct MacroParser<'a> { - toks: RefTokenTreeCursor<'a>, + iter: TokenStreamIter<'a>, } impl<'a> MacroParser<'a> { - const fn new(toks: RefTokenTreeCursor<'a>) -> Self { - Self { toks } + const fn new(iter: TokenStreamIter<'a>) -> Self { + Self { iter } } // (`(` ... `)` `=>` `{` ... `}`)* fn parse(&mut self) -> Option { let mut branches = vec![]; - while self.toks.peek().is_some() { + while self.iter.peek().is_some() { branches.push(self.parse_branch()?); } @@ -1199,13 +1199,13 @@ impl<'a> MacroParser<'a> { // `(` ... `)` `=>` `{` ... `}` fn parse_branch(&mut self) -> Option { - let tok = self.toks.next()?; + let tok = self.iter.next()?; let (lo, args_paren_kind) = match tok { TokenTree::Token(..) => return None, &TokenTree::Delimited(delimited_span, _, d, _) => (delimited_span.open.lo(), d), }; let args = TokenStream::new(vec![tok.clone()]); - match self.toks.next()? { + match self.iter.next()? { TokenTree::Token( Token { kind: TokenKind::FatArrow, @@ -1215,7 +1215,7 @@ impl<'a> MacroParser<'a> { ) => {} _ => return None, } - let (mut hi, body, whole_body) = match self.toks.next()? { + let (mut hi, body, whole_body) = match self.iter.next()? { TokenTree::Token(..) => return None, TokenTree::Delimited(delimited_span, ..) => { let data = delimited_span.entire().data(); @@ -1237,10 +1237,10 @@ impl<'a> MacroParser<'a> { span, }, _, - )) = self.toks.peek() + )) = self.iter.peek() { hi = span.hi(); - self.toks.next(); + self.iter.next(); } Some(MacroBranch { span: mk_sp(lo, hi), From c82d5865f2f556464a14951686897989223a8d0a Mon Sep 17 00:00:00 2001 From: Nicholas Nethercote Date: Wed, 11 Dec 2024 14:58:19 +1100 Subject: [PATCH 29/92] Remove `Peekable` uses. Currently there are two ways to peek at a `TokenStreamIter`. - Wrap it in a `Peekable` and use that traits `peek` method. - Use `TokenStreamIter`'s inherent `peek` method. Some code uses one, some use the other. This commit converts all places to the inherent method. This eliminates mixing of `TokenStreamIter` and `Peekable` and some use of `impl Iterator` and `dyn Iterator`. --- compiler/rustc_ast/src/attr/mod.rs | 27 +++++++++---------------- compiler/rustc_ast/src/tokenstream.rs | 5 ++++- compiler/rustc_expand/src/mbe/quoted.rs | 26 +++++++++++++----------- 3 files changed, 27 insertions(+), 31 deletions(-) diff --git a/compiler/rustc_ast/src/attr/mod.rs b/compiler/rustc_ast/src/attr/mod.rs index 2f757f75166d..ec207118c098 100644 --- a/compiler/rustc_ast/src/attr/mod.rs +++ b/compiler/rustc_ast/src/attr/mod.rs @@ -1,7 +1,6 @@ //! Functions dealing with attributes and meta items. use std::fmt::Debug; -use std::iter; use std::sync::atomic::{AtomicU32, Ordering}; use rustc_index::bit_set::GrowableBitSet; @@ -17,7 +16,9 @@ use crate::ast::{ }; use crate::ptr::P; use crate::token::{self, CommentKind, Delimiter, Token}; -use crate::tokenstream::{DelimSpan, LazyAttrTokenStream, Spacing, TokenStream, TokenTree}; +use crate::tokenstream::{ + DelimSpan, LazyAttrTokenStream, Spacing, TokenStream, TokenStreamIter, TokenTree, +}; use crate::util::comments; use crate::util::literal::escape_string_symbol; @@ -366,10 +367,7 @@ impl MetaItem { } } - fn from_tokens<'a, I>(iter: &mut iter::Peekable) -> Option - where - I: Iterator, - { + fn from_tokens(iter: &mut TokenStreamIter<'_>) -> Option { // FIXME: Share code with `parse_path`. let tt = iter.next().map(|tt| TokenTree::uninterpolate(tt)); let path = match tt.as_deref() { @@ -439,7 +437,7 @@ impl MetaItem { impl MetaItemKind { // public because it can be called in the hir pub fn list_from_tokens(tokens: TokenStream) -> Option> { - let mut iter = tokens.iter().peekable(); + let mut iter = tokens.iter(); let mut result = ThinVec::new(); while iter.peek().is_some() { let item = MetaItemInner::from_tokens(&mut iter)?; @@ -452,9 +450,7 @@ impl MetaItemKind { Some(result) } - fn name_value_from_tokens<'a>( - iter: &mut impl Iterator, - ) -> Option { + fn name_value_from_tokens(iter: &mut TokenStreamIter<'_>) -> Option { match iter.next() { Some(TokenTree::Delimited(.., Delimiter::Invisible(_), inner_tokens)) => { MetaItemKind::name_value_from_tokens(&mut inner_tokens.iter()) @@ -466,9 +462,7 @@ impl MetaItemKind { } } - fn from_tokens<'a>( - iter: &mut iter::Peekable>, - ) -> Option { + fn from_tokens(iter: &mut TokenStreamIter<'_>) -> Option { match iter.peek() { Some(TokenTree::Delimited(.., Delimiter::Parenthesis, inner_tokens)) => { let inner_tokens = inner_tokens.clone(); @@ -594,10 +588,7 @@ impl MetaItemInner { self.meta_item().is_some() } - fn from_tokens<'a, I>(iter: &mut iter::Peekable) -> Option - where - I: Iterator, - { + fn from_tokens(iter: &mut TokenStreamIter<'_>) -> Option { match iter.peek() { Some(TokenTree::Token(token, _)) if let Some(lit) = MetaItemLit::from_token(token) => { iter.next(); @@ -605,7 +596,7 @@ impl MetaItemInner { } Some(TokenTree::Delimited(.., Delimiter::Invisible(_), inner_tokens)) => { iter.next(); - return MetaItemInner::from_tokens(&mut inner_tokens.iter().peekable()); + return MetaItemInner::from_tokens(&mut inner_tokens.iter()); } _ => {} } diff --git a/compiler/rustc_ast/src/tokenstream.rs b/compiler/rustc_ast/src/tokenstream.rs index 9f7ba9286922..9f7a583af097 100644 --- a/compiler/rustc_ast/src/tokenstream.rs +++ b/compiler/rustc_ast/src/tokenstream.rs @@ -676,7 +676,10 @@ impl<'t> TokenStreamIter<'t> { TokenStreamIter { stream, index: 0 } } - pub fn peek(&self) -> Option<&TokenTree> { + // Peeking could be done via `Peekable`, but most iterators need peeking, + // and this is simple and avoids the need to use `peekable` and `Peekable` + // at all the use sites. + pub fn peek(&self) -> Option<&'t TokenTree> { self.stream.0.get(self.index) } } diff --git a/compiler/rustc_expand/src/mbe/quoted.rs b/compiler/rustc_expand/src/mbe/quoted.rs index f8975aff1c3b..82f2dd33883a 100644 --- a/compiler/rustc_expand/src/mbe/quoted.rs +++ b/compiler/rustc_expand/src/mbe/quoted.rs @@ -1,4 +1,5 @@ use rustc_ast::token::{self, Delimiter, IdentIsRaw, NonterminalKind, Token}; +use rustc_ast::tokenstream::TokenStreamIter; use rustc_ast::{NodeId, tokenstream}; use rustc_ast_pretty::pprust; use rustc_feature::Features; @@ -49,7 +50,7 @@ pub(super) fn parse( // For each token tree in `input`, parse the token into a `self::TokenTree`, consuming // additional trees if need be. - let mut iter = input.iter().peekable(); + let mut iter = input.iter(); while let Some(tree) = iter.next() { // Given the parsed tree, if there is a metavar and we are expecting matchers, actually // parse out the matcher (i.e., in `$id:ident` this would parse the `:` and `ident`). @@ -150,7 +151,7 @@ fn maybe_emit_macro_metavar_expr_concat_feature(features: &Features, sess: &Sess /// - `features`: language features so we can do feature gating. fn parse_tree<'a>( tree: &'a tokenstream::TokenTree, - outer_iter: &mut impl Iterator, + outer_iter: &mut TokenStreamIter<'a>, parsing_patterns: bool, sess: &Session, node_id: NodeId, @@ -164,14 +165,15 @@ fn parse_tree<'a>( // FIXME: Handle `Invisible`-delimited groups in a more systematic way // during parsing. let mut next = outer_iter.next(); - let mut iter: Box>; - match next { + let mut iter_storage; + let mut iter: &mut TokenStreamIter<'_> = match next { Some(tokenstream::TokenTree::Delimited(.., delim, tts)) if delim.skip() => { - iter = Box::new(tts.iter()); - next = iter.next(); + iter_storage = tts.iter(); + next = iter_storage.next(); + &mut iter_storage } - _ => iter = Box::new(outer_iter), - } + _ => outer_iter, + }; match next { // `tree` is followed by a delimited set of token trees. @@ -313,8 +315,8 @@ fn kleene_op(token: &Token) -> Option { /// - Ok(Ok((op, span))) if the next token tree is a KleeneOp /// - Ok(Err(tok, span)) if the next token tree is a token but not a KleeneOp /// - Err(span) if the next token tree is not a token -fn parse_kleene_op<'a>( - iter: &mut impl Iterator, +fn parse_kleene_op( + iter: &mut TokenStreamIter<'_>, span: Span, ) -> Result, Span> { match iter.next() { @@ -338,8 +340,8 @@ fn parse_kleene_op<'a>( /// session `sess`. If the next one (or possibly two) tokens in `iter` correspond to a Kleene /// operator and separator, then a tuple with `(separator, KleeneOp)` is returned. Otherwise, an /// error with the appropriate span is emitted to `sess` and a dummy value is returned. -fn parse_sep_and_kleene_op<'a>( - iter: &mut impl Iterator, +fn parse_sep_and_kleene_op( + iter: &mut TokenStreamIter<'_>, span: Span, sess: &Session, ) -> (Option, KleeneToken) { From fd83954d66411d0ecc0cdac9e78923c01749eb0f Mon Sep 17 00:00:00 2001 From: Nicholas Nethercote Date: Wed, 11 Dec 2024 15:21:54 +1100 Subject: [PATCH 30/92] Factor out repeated code from `eat_dollar`. --- compiler/rustc_expand/src/mbe/metavar_expr.rs | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/compiler/rustc_expand/src/mbe/metavar_expr.rs b/compiler/rustc_expand/src/mbe/metavar_expr.rs index cc1ae4b6f6cc..b4453c3cd262 100644 --- a/compiler/rustc_expand/src/mbe/metavar_expr.rs +++ b/compiler/rustc_expand/src/mbe/metavar_expr.rs @@ -275,8 +275,7 @@ fn eat_dollar<'psess>( psess: &'psess ParseSess, span: Span, ) -> PResult<'psess, ()> { - if let Some(TokenTree::Token(Token { kind: token::Dollar, .. }, _)) = iter.peek() { - let _ = iter.next(); + if try_eat_dollar(iter) { return Ok(()); } Err(psess.dcx().struct_span_err( From 39305bfaf2dc893835fda0ccecc4fee544a514af Mon Sep 17 00:00:00 2001 From: jyn Date: Tue, 17 Dec 2024 18:47:19 -0500 Subject: [PATCH 31/92] Fix `x build --stage 1 std` when using cg_cranelift as the default backend Before, cg_cranelift would ICE when trying to lower f16 and f128. The library/ crates had all the infrastructure to omit using them, it just wasn't hooked up to bootstrap. --- src/bootstrap/src/core/build_steps/compile.rs | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/src/bootstrap/src/core/build_steps/compile.rs b/src/bootstrap/src/core/build_steps/compile.rs index 0cacd6e4f37a..460b86163bdf 100644 --- a/src/bootstrap/src/core/build_steps/compile.rs +++ b/src/bootstrap/src/core/build_steps/compile.rs @@ -523,6 +523,11 @@ pub fn std_cargo(builder: &Builder<'_>, target: TargetSelection, stage: u32, car let mut features = String::new(); + if stage != 0 && builder.config.default_codegen_backend(target).as_deref() == Some("cranelift") + { + features += "compiler-builtins-no-f16-f128 "; + } + if builder.no_std(target) == Some(true) { features += " compiler-builtins-mem"; if !target.starts_with("bpf") { From 2903356b2e0d73089d66e24b61bfd47d22467851 Mon Sep 17 00:00:00 2001 From: Nicholas Nethercote Date: Tue, 10 Dec 2024 19:18:44 +1100 Subject: [PATCH 32/92] Overhaul `TokenTreeCursor`. - Move it to `rustc_parse`, which is the only crate that uses it. This lets us remove all the `pub` markers from it. - Change `next_ref` and `look_ahead` to `get` and `bump`, which work better for the `rustc_parse` uses. - This requires adding a `TokenStream::get` method, which is simple. - In `TokenCursor`, we currently duplicate the `DelimSpan`/`DelimSpacing`/`Delimiter` from the surrounding `TokenTree::Delimited` in the stack. This isn't necessary so long as we don't prematurely move past the `Delimited`, and is a small perf win on a very hot code path. - In `parse_token_tree`, we clone the relevant `TokenTree::Delimited` instead of constructing an identical one from pieces. --- compiler/rustc_ast/src/tokenstream.rs | 41 ++--------- compiler/rustc_parse/src/parser/expr.rs | 4 +- compiler/rustc_parse/src/parser/mod.rs | 90 ++++++++++++++++--------- 3 files changed, 66 insertions(+), 69 deletions(-) diff --git a/compiler/rustc_ast/src/tokenstream.rs b/compiler/rustc_ast/src/tokenstream.rs index 9f7a583af097..e7b393d869d2 100644 --- a/compiler/rustc_ast/src/tokenstream.rs +++ b/compiler/rustc_ast/src/tokenstream.rs @@ -423,12 +423,12 @@ impl TokenStream { self.0.len() } - pub fn iter(&self) -> TokenStreamIter<'_> { - TokenStreamIter::new(self) + pub fn get(&self, index: usize) -> Option<&TokenTree> { + self.0.get(index) } - pub fn into_trees(self) -> TokenTreeCursor { - TokenTreeCursor::new(self) + pub fn iter(&self) -> TokenStreamIter<'_> { + TokenStreamIter::new(self) } /// Compares two `TokenStream`s, checking equality without regarding span information. @@ -695,39 +695,6 @@ impl<'t> Iterator for TokenStreamIter<'t> { } } -/// Owning by-value iterator over a [`TokenStream`], that produces `&TokenTree` -/// items. -/// -/// Doesn't impl `Iterator` because Rust doesn't permit an owning iterator to -/// return `&T` from `next`; the need for an explicit lifetime in the `Item` -/// associated type gets in the way. Instead, use `next_ref` (which doesn't -/// involve associated types) for getting individual elements, or -/// `TokenStreamIter` if you really want an `Iterator`, e.g. in a `for` -/// loop. -#[derive(Clone, Debug)] -pub struct TokenTreeCursor { - pub stream: TokenStream, - index: usize, -} - -impl TokenTreeCursor { - fn new(stream: TokenStream) -> Self { - TokenTreeCursor { stream, index: 0 } - } - - #[inline] - pub fn next_ref(&mut self) -> Option<&TokenTree> { - self.stream.0.get(self.index).map(|tree| { - self.index += 1; - tree - }) - } - - pub fn look_ahead(&self, n: usize) -> Option<&TokenTree> { - self.stream.0.get(self.index + n) - } -} - #[derive(Debug, Copy, Clone, PartialEq, Encodable, Decodable, HashStable_Generic)] pub struct DelimSpan { pub open: Span, diff --git a/compiler/rustc_parse/src/parser/expr.rs b/compiler/rustc_parse/src/parser/expr.rs index a2136399b0c8..fe5df04deeb6 100644 --- a/compiler/rustc_parse/src/parser/expr.rs +++ b/compiler/rustc_parse/src/parser/expr.rs @@ -8,6 +8,7 @@ use ast::token::IdentIsRaw; use ast::{CoroutineKind, ForLoopKind, GenBlockKind, MatchKind, Pat, Path, PathSegment, Recovered}; use rustc_ast::ptr::P; use rustc_ast::token::{self, Delimiter, Token, TokenKind}; +use rustc_ast::tokenstream::TokenTree; use rustc_ast::util::case::Case; use rustc_ast::util::classify; use rustc_ast::util::parser::{AssocOp, ExprPrecedence, Fixity, prec_let_scrutinee_needs_par}; @@ -2393,7 +2394,8 @@ impl<'a> Parser<'a> { } if self.token == TokenKind::Semi - && matches!(self.token_cursor.stack.last(), Some((.., Delimiter::Parenthesis))) + && let Some(last) = self.token_cursor.stack.last() + && let Some(TokenTree::Delimited(_, _, Delimiter::Parenthesis, _)) = last.curr() && self.may_recover() { // It is likely that the closure body is a block but where the diff --git a/compiler/rustc_parse/src/parser/mod.rs b/compiler/rustc_parse/src/parser/mod.rs index 976ffe608a2f..b85968a555d5 100644 --- a/compiler/rustc_parse/src/parser/mod.rs +++ b/compiler/rustc_parse/src/parser/mod.rs @@ -24,9 +24,7 @@ use rustc_ast::ptr::P; use rustc_ast::token::{ self, Delimiter, IdentIsRaw, InvisibleOrigin, MetaVarKind, Nonterminal, Token, TokenKind, }; -use rustc_ast::tokenstream::{ - AttrsTarget, DelimSpacing, DelimSpan, Spacing, TokenStream, TokenTree, TokenTreeCursor, -}; +use rustc_ast::tokenstream::{AttrsTarget, Spacing, TokenStream, TokenTree}; use rustc_ast::util::case::Case; use rustc_ast::{ self as ast, AnonConst, AttrArgs, AttrId, ByRef, Const, CoroutineKind, DUMMY_NODE_ID, @@ -273,21 +271,48 @@ struct CaptureState { seen_attrs: IntervalSet, } -/// Iterator over a `TokenStream` that produces `Token`s. It's a bit odd that +#[derive(Clone, Debug)] +struct TokenTreeCursor { + stream: TokenStream, + /// Points to the current token tree in the stream. In `TokenCursor::curr`, + /// this can be any token tree. In `TokenCursor::stack`, this is always a + /// `TokenTree::Delimited`. + index: usize, +} + +impl TokenTreeCursor { + #[inline] + fn new(stream: TokenStream) -> Self { + TokenTreeCursor { stream, index: 0 } + } + + #[inline] + fn curr(&self) -> Option<&TokenTree> { + self.stream.get(self.index) + } + + #[inline] + fn bump(&mut self) { + self.index += 1; + } +} + +/// A `TokenStream` cursor that produces `Token`s. It's a bit odd that /// we (a) lex tokens into a nice tree structure (`TokenStream`), and then (b) /// use this type to emit them as a linear sequence. But a linear sequence is /// what the parser expects, for the most part. #[derive(Clone, Debug)] struct TokenCursor { - // Cursor for the current (innermost) token stream. The delimiters for this - // token stream are found in `self.stack.last()`; when that is `None` then - // we are in the outermost token stream which never has delimiters. - tree_cursor: TokenTreeCursor, + // Cursor for the current (innermost) token stream. The index within the + // cursor can point to any token tree in the stream (or one past the end). + // The delimiters for this token stream are found in `self.stack.last()`; + // if that is `None` we are in the outermost token stream which never has + // delimiters. + curr: TokenTreeCursor, - // Token streams surrounding the current one. The delimiters for stack[n]'s - // tokens are in `stack[n-1]`. `stack[0]` (when present) has no delimiters - // because it's the outermost token stream which never has delimiters. - stack: Vec<(TokenTreeCursor, DelimSpan, DelimSpacing, Delimiter)>, + // Token streams surrounding the current one. The index within each cursor + // always points to a `TokenTree::Delimited`. + stack: Vec, } impl TokenCursor { @@ -302,32 +327,33 @@ impl TokenCursor { // FIXME: we currently don't return `Delimiter::Invisible` open/close delims. To fix // #67062 we will need to, whereupon the `delim != Delimiter::Invisible` conditions // below can be removed. - if let Some(tree) = self.tree_cursor.next_ref() { + if let Some(tree) = self.curr.curr() { match tree { &TokenTree::Token(ref token, spacing) => { debug_assert!(!matches!( token.kind, token::OpenDelim(_) | token::CloseDelim(_) )); - return (token.clone(), spacing); + let res = (token.clone(), spacing); + self.curr.bump(); + return res; } &TokenTree::Delimited(sp, spacing, delim, ref tts) => { - let trees = tts.clone().into_trees(); - self.stack.push(( - mem::replace(&mut self.tree_cursor, trees), - sp, - spacing, - delim, - )); + let trees = TokenTreeCursor::new(tts.clone()); + self.stack.push(mem::replace(&mut self.curr, trees)); if !delim.skip() { return (Token::new(token::OpenDelim(delim), sp.open), spacing.open); } // No open delimiter to return; continue on to the next iteration. } }; - } else if let Some((tree_cursor, span, spacing, delim)) = self.stack.pop() { + } else if let Some(parent) = self.stack.pop() { // We have exhausted this token stream. Move back to its parent token stream. - self.tree_cursor = tree_cursor; + let Some(&TokenTree::Delimited(span, spacing, delim, _)) = parent.curr() else { + panic!("parent should be Delimited") + }; + self.curr = parent; + self.curr.bump(); // move past the `Delimited` if !delim.skip() { return (Token::new(token::CloseDelim(delim), span.close), spacing.close); } @@ -466,7 +492,7 @@ impl<'a> Parser<'a> { capture_cfg: false, restrictions: Restrictions::empty(), expected_tokens: Vec::new(), - token_cursor: TokenCursor { tree_cursor: stream.into_trees(), stack: Vec::new() }, + token_cursor: TokenCursor { curr: TokenTreeCursor::new(stream), stack: Vec::new() }, num_bump_calls: 0, break_last_token: 0, unmatched_angle_bracket_count: 0, @@ -1192,7 +1218,7 @@ impl<'a> Parser<'a> { if dist == 1 { // The index is zero because the tree cursor's index always points // to the next token to be gotten. - match self.token_cursor.tree_cursor.look_ahead(0) { + match self.token_cursor.curr.curr() { Some(tree) => { // Indexing stayed within the current token tree. match tree { @@ -1202,12 +1228,13 @@ impl<'a> Parser<'a> { return looker(&Token::new(token::OpenDelim(delim), dspan.open)); } } - }; + } } None => { // The tree cursor lookahead went (one) past the end of the // current token tree. Try to return a close delimiter. - if let Some(&(_, span, _, delim)) = self.token_cursor.stack.last() + if let Some(last) = self.token_cursor.stack.last() + && let Some(&TokenTree::Delimited(span, _, delim, _)) = last.curr() && !delim.skip() { // We are not in the outermost token stream, so we have @@ -1399,9 +1426,10 @@ impl<'a> Parser<'a> { pub fn parse_token_tree(&mut self) -> TokenTree { match self.token.kind { token::OpenDelim(..) => { - // Grab the tokens within the delimiters. - let stream = self.token_cursor.tree_cursor.stream.clone(); - let (_, span, spacing, delim) = *self.token_cursor.stack.last().unwrap(); + // Clone the `TokenTree::Delimited` that we are currently + // within. That's what we are going to return. + let tree = self.token_cursor.stack.last().unwrap().curr().unwrap().clone(); + debug_assert_matches!(tree, TokenTree::Delimited(..)); // Advance the token cursor through the entire delimited // sequence. After getting the `OpenDelim` we are *within* the @@ -1421,7 +1449,7 @@ impl<'a> Parser<'a> { // Consume close delimiter self.bump(); - TokenTree::Delimited(span, spacing, delim, stream) + tree } token::CloseDelim(_) | token::Eof => unreachable!(), _ => { From 4977640c7901d153e7768395b1a3f5d7eccabbf4 Mon Sep 17 00:00:00 2001 From: Michael Goulet Date: Thu, 5 Dec 2024 16:36:30 +0000 Subject: [PATCH 33/92] Fix const conditions for RPITITs --- .../src/collect/item_bounds.rs | 7 +- .../src/collect/predicates_of.rs | 41 ++-- .../const-traits/const-cond-for-rpitit.rs | 22 +++ .../traits/const-traits/const-impl-trait.rs | 25 ++- .../const-traits/const-impl-trait.stderr | 187 ++++++++++++++++++ 5 files changed, 254 insertions(+), 28 deletions(-) create mode 100644 tests/ui/traits/const-traits/const-cond-for-rpitit.rs create mode 100644 tests/ui/traits/const-traits/const-impl-trait.stderr diff --git a/compiler/rustc_hir_analysis/src/collect/item_bounds.rs b/compiler/rustc_hir_analysis/src/collect/item_bounds.rs index 0b81f4693712..d3ff1f7bebe6 100644 --- a/compiler/rustc_hir_analysis/src/collect/item_bounds.rs +++ b/compiler/rustc_hir_analysis/src/collect/item_bounds.rs @@ -371,10 +371,9 @@ pub(super) fn explicit_item_bounds_with_filter( associated_type_bounds(tcx, def_id, opaque_ty.bounds, opaque_ty.span, filter); return ty::EarlyBinder::bind(bounds); } - Some(ty::ImplTraitInTraitData::Impl { .. }) => span_bug!( - tcx.def_span(def_id), - "item bounds for RPITIT in impl to be fed on def-id creation" - ), + Some(ty::ImplTraitInTraitData::Impl { .. }) => { + span_bug!(tcx.def_span(def_id), "RPITIT in impl should not have item bounds") + } None => {} } diff --git a/compiler/rustc_hir_analysis/src/collect/predicates_of.rs b/compiler/rustc_hir_analysis/src/collect/predicates_of.rs index 1a6c0a934360..6b4a1ad00536 100644 --- a/compiler/rustc_hir_analysis/src/collect/predicates_of.rs +++ b/compiler/rustc_hir_analysis/src/collect/predicates_of.rs @@ -957,6 +957,15 @@ pub(super) fn const_conditions<'tcx>( bug!("const_conditions invoked for item that is not conditionally const: {def_id:?}"); } + match tcx.opt_rpitit_info(def_id.to_def_id()) { + // RPITITs inherit const conditions of their parent fn + Some( + ty::ImplTraitInTraitData::Impl { fn_def_id } + | ty::ImplTraitInTraitData::Trait { fn_def_id, .. }, + ) => return tcx.const_conditions(fn_def_id), + None => {} + } + let (generics, trait_def_id_and_supertraits, has_parent) = match tcx.hir_node_by_def_id(def_id) { Node::Item(item) => match item.kind { @@ -1060,19 +1069,29 @@ pub(super) fn explicit_implied_const_bounds<'tcx>( bug!("const_conditions invoked for item that is not conditionally const: {def_id:?}"); } - let bounds = match tcx.hir_node_by_def_id(def_id) { - Node::Item(hir::Item { kind: hir::ItemKind::Trait(..), .. }) => { - implied_predicates_with_filter( - tcx, - def_id.to_def_id(), - PredicateFilter::SelfConstIfConst, - ) - } - Node::TraitItem(hir::TraitItem { kind: hir::TraitItemKind::Type(..), .. }) - | Node::OpaqueTy(_) => { + let bounds = match tcx.opt_rpitit_info(def_id.to_def_id()) { + // RPITIT's bounds are the same as opaque type bounds, but with + // a projection self type. + Some(ty::ImplTraitInTraitData::Trait { .. }) => { explicit_item_bounds_with_filter(tcx, def_id, PredicateFilter::ConstIfConst) } - _ => bug!("explicit_implied_const_bounds called on wrong item: {def_id:?}"), + Some(ty::ImplTraitInTraitData::Impl { .. }) => { + span_bug!(tcx.def_span(def_id), "RPITIT in impl should not have item bounds") + } + None => match tcx.hir_node_by_def_id(def_id) { + Node::Item(hir::Item { kind: hir::ItemKind::Trait(..), .. }) => { + implied_predicates_with_filter( + tcx, + def_id.to_def_id(), + PredicateFilter::SelfConstIfConst, + ) + } + Node::TraitItem(hir::TraitItem { kind: hir::TraitItemKind::Type(..), .. }) + | Node::OpaqueTy(_) => { + explicit_item_bounds_with_filter(tcx, def_id, PredicateFilter::ConstIfConst) + } + _ => bug!("explicit_implied_const_bounds called on wrong item: {def_id:?}"), + }, }; bounds.map_bound(|bounds| { diff --git a/tests/ui/traits/const-traits/const-cond-for-rpitit.rs b/tests/ui/traits/const-traits/const-cond-for-rpitit.rs new file mode 100644 index 000000000000..50bf93f9a032 --- /dev/null +++ b/tests/ui/traits/const-traits/const-cond-for-rpitit.rs @@ -0,0 +1,22 @@ +//@ compile-flags: -Znext-solver +//@ check-pass + +#![feature(const_trait_impl)] +#![allow(refining_impl_trait)] + +#[const_trait] +pub trait Foo { + fn method(self) -> impl ~const Bar; +} + +#[const_trait] +pub trait Bar {} + +struct A(T); +impl const Foo for A where A: ~const Bar { + fn method(self) -> impl ~const Bar { + self + } +} + +fn main() {} diff --git a/tests/ui/traits/const-traits/const-impl-trait.rs b/tests/ui/traits/const-traits/const-impl-trait.rs index 61b8c9a5bff8..d7fe43ef37ce 100644 --- a/tests/ui/traits/const-traits/const-impl-trait.rs +++ b/tests/ui/traits/const-traits/const-impl-trait.rs @@ -1,15 +1,10 @@ //@ compile-flags: -Znext-solver //@ known-bug: #110395 -//@ failure-status: 101 -//@ dont-check-compiler-stderr -// Broken until we have `&T: const Deref` impl in stdlib + +// Broken until we have `const PartialEq` impl in stdlib #![allow(incomplete_features)] -#![feature( - const_trait_impl, - effects, - const_cmp, -)] +#![feature(const_trait_impl, const_cmp, const_destruct)] use std::marker::Destruct; @@ -17,9 +12,9 @@ const fn cmp(a: &impl ~const PartialEq) -> bool { a == a } -const fn wrap(x: impl ~const PartialEq + ~const Destruct) - -> impl ~const PartialEq + ~const Destruct -{ +const fn wrap( + x: impl ~const PartialEq + ~const Destruct, +) -> impl ~const PartialEq + ~const Destruct { x } @@ -48,11 +43,15 @@ trait T {} struct S; impl const T for S {} -const fn rpit() -> impl ~const T { S } +const fn rpit() -> impl ~const T { + S +} const fn apit(_: impl ~const T + ~const Destruct) {} -const fn rpit_assoc_bound() -> impl IntoIterator { Some(S) } +const fn rpit_assoc_bound() -> impl IntoIterator { + Some(S) +} const fn apit_assoc_bound(_: impl IntoIterator + ~const Destruct) {} diff --git a/tests/ui/traits/const-traits/const-impl-trait.stderr b/tests/ui/traits/const-traits/const-impl-trait.stderr new file mode 100644 index 000000000000..4e3200594485 --- /dev/null +++ b/tests/ui/traits/const-traits/const-impl-trait.stderr @@ -0,0 +1,187 @@ +error[E0635]: unknown feature `const_cmp` + --> $DIR/const-impl-trait.rs:7:30 + | +LL | #![feature(const_trait_impl, const_cmp, const_destruct)] + | ^^^^^^^^^ + +error: `~const` can only be applied to `#[const_trait]` traits + --> $DIR/const-impl-trait.rs:11:23 + | +LL | const fn cmp(a: &impl ~const PartialEq) -> bool { + | ^^^^^^ can't be applied to `PartialEq` + | +note: `PartialEq` can't be used with `~const` because it isn't annotated with `#[const_trait]` + --> $SRC_DIR/core/src/cmp.rs:LL:COL + +error: `~const` can only be applied to `#[const_trait]` traits + --> $DIR/const-impl-trait.rs:11:23 + | +LL | const fn cmp(a: &impl ~const PartialEq) -> bool { + | ^^^^^^ can't be applied to `PartialEq` + | +note: `PartialEq` can't be used with `~const` because it isn't annotated with `#[const_trait]` + --> $SRC_DIR/core/src/cmp.rs:LL:COL + = note: duplicate diagnostic emitted due to `-Z deduplicate-diagnostics=no` + +error: `~const` can only be applied to `#[const_trait]` traits + --> $DIR/const-impl-trait.rs:16:13 + | +LL | x: impl ~const PartialEq + ~const Destruct, + | ^^^^^^ can't be applied to `PartialEq` + | +note: `PartialEq` can't be used with `~const` because it isn't annotated with `#[const_trait]` + --> $SRC_DIR/core/src/cmp.rs:LL:COL + +error: `~const` can only be applied to `#[const_trait]` traits + --> $DIR/const-impl-trait.rs:17:11 + | +LL | ) -> impl ~const PartialEq + ~const Destruct { + | ^^^^^^ can't be applied to `PartialEq` + | +note: `PartialEq` can't be used with `~const` because it isn't annotated with `#[const_trait]` + --> $SRC_DIR/core/src/cmp.rs:LL:COL + +error: `~const` can only be applied to `#[const_trait]` traits + --> $DIR/const-impl-trait.rs:17:11 + | +LL | ) -> impl ~const PartialEq + ~const Destruct { + | ^^^^^^ can't be applied to `PartialEq` + | +note: `PartialEq` can't be used with `~const` because it isn't annotated with `#[const_trait]` + --> $SRC_DIR/core/src/cmp.rs:LL:COL + = note: duplicate diagnostic emitted due to `-Z deduplicate-diagnostics=no` + +error: `~const` can only be applied to `#[const_trait]` traits + --> $DIR/const-impl-trait.rs:17:11 + | +LL | ) -> impl ~const PartialEq + ~const Destruct { + | ^^^^^^ can't be applied to `PartialEq` + | +note: `PartialEq` can't be used with `~const` because it isn't annotated with `#[const_trait]` + --> $SRC_DIR/core/src/cmp.rs:LL:COL + = note: duplicate diagnostic emitted due to `-Z deduplicate-diagnostics=no` + +error: `~const` can only be applied to `#[const_trait]` traits + --> $DIR/const-impl-trait.rs:16:13 + | +LL | x: impl ~const PartialEq + ~const Destruct, + | ^^^^^^ can't be applied to `PartialEq` + | +note: `PartialEq` can't be used with `~const` because it isn't annotated with `#[const_trait]` + --> $SRC_DIR/core/src/cmp.rs:LL:COL + = note: duplicate diagnostic emitted due to `-Z deduplicate-diagnostics=no` + +error: `~const` can only be applied to `#[const_trait]` traits + --> $DIR/const-impl-trait.rs:23:22 + | +LL | fn huh() -> impl ~const PartialEq + ~const Destruct + Copy; + | ^^^^^^ can't be applied to `PartialEq` + | +note: `PartialEq` can't be used with `~const` because it isn't annotated with `#[const_trait]` + --> $SRC_DIR/core/src/cmp.rs:LL:COL + +error: `~const` can only be applied to `#[const_trait]` traits + --> $DIR/const-impl-trait.rs:27:22 + | +LL | fn huh() -> impl ~const PartialEq + ~const Destruct + Copy { + | ^^^^^^ can't be applied to `PartialEq` + | +note: `PartialEq` can't be used with `~const` because it isn't annotated with `#[const_trait]` + --> $SRC_DIR/core/src/cmp.rs:LL:COL + +error: `~const` can only be applied to `#[const_trait]` traits + --> $DIR/const-impl-trait.rs:27:22 + | +LL | fn huh() -> impl ~const PartialEq + ~const Destruct + Copy { + | ^^^^^^ can't be applied to `PartialEq` + | +note: `PartialEq` can't be used with `~const` because it isn't annotated with `#[const_trait]` + --> $SRC_DIR/core/src/cmp.rs:LL:COL + = note: duplicate diagnostic emitted due to `-Z deduplicate-diagnostics=no` + +error: `~const` can only be applied to `#[const_trait]` traits + --> $DIR/const-impl-trait.rs:23:22 + | +LL | fn huh() -> impl ~const PartialEq + ~const Destruct + Copy; + | ^^^^^^ can't be applied to `PartialEq` + | +note: `PartialEq` can't be used with `~const` because it isn't annotated with `#[const_trait]` + --> $SRC_DIR/core/src/cmp.rs:LL:COL + = note: duplicate diagnostic emitted due to `-Z deduplicate-diagnostics=no` + +error: `~const` can only be applied to `#[const_trait]` traits + --> $DIR/const-impl-trait.rs:23:22 + | +LL | fn huh() -> impl ~const PartialEq + ~const Destruct + Copy; + | ^^^^^^ can't be applied to `PartialEq` + | +note: `PartialEq` can't be used with `~const` because it isn't annotated with `#[const_trait]` + --> $SRC_DIR/core/src/cmp.rs:LL:COL + = note: duplicate diagnostic emitted due to `-Z deduplicate-diagnostics=no` + +error: `~const` can only be applied to `#[const_trait]` traits + --> $DIR/const-impl-trait.rs:27:22 + | +LL | fn huh() -> impl ~const PartialEq + ~const Destruct + Copy { + | ^^^^^^ can't be applied to `PartialEq` + | +note: `PartialEq` can't be used with `~const` because it isn't annotated with `#[const_trait]` + --> $SRC_DIR/core/src/cmp.rs:LL:COL + = note: duplicate diagnostic emitted due to `-Z deduplicate-diagnostics=no` + +error: `~const` can only be applied to `#[const_trait]` traits + --> $DIR/const-impl-trait.rs:23:22 + | +LL | fn huh() -> impl ~const PartialEq + ~const Destruct + Copy; + | ^^^^^^ can't be applied to `PartialEq` + | +note: `PartialEq` can't be used with `~const` because it isn't annotated with `#[const_trait]` + --> $SRC_DIR/core/src/cmp.rs:LL:COL + = note: duplicate diagnostic emitted due to `-Z deduplicate-diagnostics=no` + +error: `~const` can only be applied to `#[const_trait]` traits + --> $DIR/const-impl-trait.rs:23:22 + | +LL | fn huh() -> impl ~const PartialEq + ~const Destruct + Copy; + | ^^^^^^ can't be applied to `PartialEq` + | +note: `PartialEq` can't be used with `~const` because it isn't annotated with `#[const_trait]` + --> $SRC_DIR/core/src/cmp.rs:LL:COL + = note: duplicate diagnostic emitted due to `-Z deduplicate-diagnostics=no` + +error[E0015]: cannot call non-const operator in constants + --> $DIR/const-impl-trait.rs:35:13 + | +LL | assert!(wrap(123) == wrap(123)); + | ^^^^^^^^^^^^^^^^^^^^^^ + | + = note: calls in constants are limited to constant functions, tuple structs and tuple variants + +error[E0015]: cannot call non-const operator in constants + --> $DIR/const-impl-trait.rs:36:13 + | +LL | assert!(wrap(123) != wrap(456)); + | ^^^^^^^^^^^^^^^^^^^^^^ + | + = note: calls in constants are limited to constant functions, tuple structs and tuple variants + +error[E0015]: cannot call non-const operator in constants + --> $DIR/const-impl-trait.rs:38:13 + | +LL | assert!(x == x); + | ^^^^^^ + | + = note: calls in constants are limited to constant functions, tuple structs and tuple variants + +error[E0015]: cannot call non-const operator in constant functions + --> $DIR/const-impl-trait.rs:12:5 + | +LL | a == a + | ^^^^^^ + | + = note: calls in constant functions are limited to constant functions, tuple structs and tuple variants + +error: aborting due to 20 previous errors + +Some errors have detailed explanations: E0015, E0635. +For more information about an error, try `rustc --explain E0015`. From 8a85bdc9fb3ec0d5e845a1cab036aa437baa79b0 Mon Sep 17 00:00:00 2001 From: Nicholas Nethercote Date: Wed, 18 Dec 2024 15:54:17 +1100 Subject: [PATCH 34/92] Remove a comment that shouldn't have been committed. --- compiler/rustc_mir_dataflow/src/framework/visitor.rs | 1 - 1 file changed, 1 deletion(-) diff --git a/compiler/rustc_mir_dataflow/src/framework/visitor.rs b/compiler/rustc_mir_dataflow/src/framework/visitor.rs index d18e9fa33f0c..a03aecee7be1 100644 --- a/compiler/rustc_mir_dataflow/src/framework/visitor.rs +++ b/compiler/rustc_mir_dataflow/src/framework/visitor.rs @@ -35,7 +35,6 @@ where { fn visit_block_start(&mut self, _state: &A::Domain) {} - /// // njn: grep for "before", "primary", etc. /// Called after the "early" effect of the given statement is applied to `state`. fn visit_after_early_statement_effect( &mut self, From bfd02d8b36914d222b2ee6ed185cbf6bdba7d9d9 Mon Sep 17 00:00:00 2001 From: Georg Semmler Date: Tue, 22 Oct 2024 19:48:11 +0200 Subject: [PATCH 35/92] Improve testing coverage for `#[diagnostic::do_not_recommend]` This PR aims to improve the testing coverage for `#[diagnostic::do_not_recommend]`. It ensures that all tests are run for the old and new solver to verify that the behaviour is the same for both variants. It also adds two new tests: * A test with 4 traits having wild card impl for each other, with alternating `#[diagnostic::do_not_recommend]` attributse * A test with a lifetime dependend wild card impl, which is something that's not supported yet --- ...ibute_without_feature_flag.current.stderr} | 4 +- ...attribute_without_feature_flag.next.stderr | 21 ++++++++ ...ot_apply_attribute_without_feature_flag.rs | 3 ++ ...ture-gate-do_not_recommend.current.stderr} | 4 +- .../feature-gate-do_not_recommend.next.stderr | 17 ++++++ .../feature-gate-do_not_recommend.rs | 3 ++ ...err => incorrect-locations.current.stderr} | 16 +++--- .../incorrect-locations.next.stderr | 52 +++++++++++++++++++ .../do_not_recommend/incorrect-locations.rs | 3 ++ .../do_not_recommend/nested.current.stderr | 15 ++++++ .../do_not_recommend/nested.next.stderr | 15 ++++++ .../do_not_recommend/nested.rs | 25 +++++++++ ...stderr => unstable-feature.current.stderr} | 4 +- .../unstable-feature.next.stderr | 14 +++++ .../do_not_recommend/unstable-feature.rs | 3 ++ .../with_lifetime.current.stderr | 10 ++++ .../with_lifetime.next.stderr | 10 ++++ .../do_not_recommend/with_lifetime.rs | 25 +++++++++ 18 files changed, 230 insertions(+), 14 deletions(-) rename tests/ui/diagnostic_namespace/do_not_recommend/{do_not_apply_attribute_without_feature_flag.stderr => do_not_apply_attribute_without_feature_flag.current.stderr} (83%) create mode 100644 tests/ui/diagnostic_namespace/do_not_recommend/do_not_apply_attribute_without_feature_flag.next.stderr rename tests/ui/diagnostic_namespace/do_not_recommend/{feature-gate-do_not_recommend.stderr => feature-gate-do_not_recommend.current.stderr} (79%) create mode 100644 tests/ui/diagnostic_namespace/do_not_recommend/feature-gate-do_not_recommend.next.stderr rename tests/ui/diagnostic_namespace/do_not_recommend/{incorrect-locations.stderr => incorrect-locations.current.stderr} (82%) create mode 100644 tests/ui/diagnostic_namespace/do_not_recommend/incorrect-locations.next.stderr create mode 100644 tests/ui/diagnostic_namespace/do_not_recommend/nested.current.stderr create mode 100644 tests/ui/diagnostic_namespace/do_not_recommend/nested.next.stderr create mode 100644 tests/ui/diagnostic_namespace/do_not_recommend/nested.rs rename tests/ui/diagnostic_namespace/do_not_recommend/{unstable-feature.stderr => unstable-feature.current.stderr} (81%) create mode 100644 tests/ui/diagnostic_namespace/do_not_recommend/unstable-feature.next.stderr create mode 100644 tests/ui/diagnostic_namespace/do_not_recommend/with_lifetime.current.stderr create mode 100644 tests/ui/diagnostic_namespace/do_not_recommend/with_lifetime.next.stderr create mode 100644 tests/ui/diagnostic_namespace/do_not_recommend/with_lifetime.rs diff --git a/tests/ui/diagnostic_namespace/do_not_recommend/do_not_apply_attribute_without_feature_flag.stderr b/tests/ui/diagnostic_namespace/do_not_recommend/do_not_apply_attribute_without_feature_flag.current.stderr similarity index 83% rename from tests/ui/diagnostic_namespace/do_not_recommend/do_not_apply_attribute_without_feature_flag.stderr rename to tests/ui/diagnostic_namespace/do_not_recommend/do_not_apply_attribute_without_feature_flag.current.stderr index be17476524ae..660fc7d21714 100644 --- a/tests/ui/diagnostic_namespace/do_not_recommend/do_not_apply_attribute_without_feature_flag.stderr +++ b/tests/ui/diagnostic_namespace/do_not_recommend/do_not_apply_attribute_without_feature_flag.current.stderr @@ -1,5 +1,5 @@ error[E0277]: the trait bound `(): Foo` is not satisfied - --> $DIR/do_not_apply_attribute_without_feature_flag.rs:19:11 + --> $DIR/do_not_apply_attribute_without_feature_flag.rs:22:11 | LL | check(()); | ----- ^^ the trait `Foo` is not implemented for `()` @@ -11,7 +11,7 @@ LL | check(()); (A, B, C) (A,) note: required by a bound in `check` - --> $DIR/do_not_apply_attribute_without_feature_flag.rs:16:18 + --> $DIR/do_not_apply_attribute_without_feature_flag.rs:19:18 | LL | fn check(a: impl Foo) {} | ^^^ required by this bound in `check` diff --git a/tests/ui/diagnostic_namespace/do_not_recommend/do_not_apply_attribute_without_feature_flag.next.stderr b/tests/ui/diagnostic_namespace/do_not_recommend/do_not_apply_attribute_without_feature_flag.next.stderr new file mode 100644 index 000000000000..1cd148186f1e --- /dev/null +++ b/tests/ui/diagnostic_namespace/do_not_recommend/do_not_apply_attribute_without_feature_flag.next.stderr @@ -0,0 +1,21 @@ +error[E0277]: the trait bound `(): Foo` is not satisfied + --> $DIR/do_not_apply_attribute_without_feature_flag.rs:22:11 + | +LL | check(()); + | ----- ^^ the trait `Foo` is not implemented for `()` + | | + | required by a bound introduced by this call + | + = help: the following other types implement trait `Foo`: + (A, B) + (A, B, C) + (A,) +note: required by a bound in `check` + --> $DIR/do_not_apply_attribute_without_feature_flag.rs:19:18 + | +LL | fn check(a: impl Foo) {} + | ^^^ required by this bound in `check` + +error: aborting due to 1 previous error + +For more information about this error, try `rustc --explain E0277`. diff --git a/tests/ui/diagnostic_namespace/do_not_recommend/do_not_apply_attribute_without_feature_flag.rs b/tests/ui/diagnostic_namespace/do_not_recommend/do_not_apply_attribute_without_feature_flag.rs index 5548fa2f52e1..9c25069bc7d5 100644 --- a/tests/ui/diagnostic_namespace/do_not_recommend/do_not_apply_attribute_without_feature_flag.rs +++ b/tests/ui/diagnostic_namespace/do_not_recommend/do_not_apply_attribute_without_feature_flag.rs @@ -1,3 +1,6 @@ +//@ revisions: current next +//@ ignore-compare-mode-next-solver (explicit revisions) +//@[next] compile-flags: -Znext-solver #![allow(unknown_or_malformed_diagnostic_attributes)] trait Foo {} diff --git a/tests/ui/diagnostic_namespace/do_not_recommend/feature-gate-do_not_recommend.stderr b/tests/ui/diagnostic_namespace/do_not_recommend/feature-gate-do_not_recommend.current.stderr similarity index 79% rename from tests/ui/diagnostic_namespace/do_not_recommend/feature-gate-do_not_recommend.stderr rename to tests/ui/diagnostic_namespace/do_not_recommend/feature-gate-do_not_recommend.current.stderr index 3951231fa2e7..d1deaa6a0062 100644 --- a/tests/ui/diagnostic_namespace/do_not_recommend/feature-gate-do_not_recommend.stderr +++ b/tests/ui/diagnostic_namespace/do_not_recommend/feature-gate-do_not_recommend.current.stderr @@ -1,11 +1,11 @@ error[E0277]: the trait bound `u8: Bar` is not satisfied - --> $DIR/feature-gate-do_not_recommend.rs:15:11 + --> $DIR/feature-gate-do_not_recommend.rs:18:11 | LL | stuff(1u8); | ^^^ the trait `Bar` is not implemented for `u8` | note: required by a bound in `stuff` - --> $DIR/feature-gate-do_not_recommend.rs:12:13 + --> $DIR/feature-gate-do_not_recommend.rs:15:13 | LL | fn stuff(_: T) {} | ^^^ required by this bound in `stuff` diff --git a/tests/ui/diagnostic_namespace/do_not_recommend/feature-gate-do_not_recommend.next.stderr b/tests/ui/diagnostic_namespace/do_not_recommend/feature-gate-do_not_recommend.next.stderr new file mode 100644 index 000000000000..5bfcc60edc55 --- /dev/null +++ b/tests/ui/diagnostic_namespace/do_not_recommend/feature-gate-do_not_recommend.next.stderr @@ -0,0 +1,17 @@ +error[E0277]: the trait bound `u8: Bar` is not satisfied + --> $DIR/feature-gate-do_not_recommend.rs:18:11 + | +LL | stuff(1u8); + | ----- ^^^ the trait `Bar` is not implemented for `u8` + | | + | required by a bound introduced by this call + | +note: required by a bound in `stuff` + --> $DIR/feature-gate-do_not_recommend.rs:15:13 + | +LL | fn stuff(_: T) {} + | ^^^ required by this bound in `stuff` + +error: aborting due to 1 previous error + +For more information about this error, try `rustc --explain E0277`. diff --git a/tests/ui/diagnostic_namespace/do_not_recommend/feature-gate-do_not_recommend.rs b/tests/ui/diagnostic_namespace/do_not_recommend/feature-gate-do_not_recommend.rs index 5a26d28188c2..4adce112f15e 100644 --- a/tests/ui/diagnostic_namespace/do_not_recommend/feature-gate-do_not_recommend.rs +++ b/tests/ui/diagnostic_namespace/do_not_recommend/feature-gate-do_not_recommend.rs @@ -1,3 +1,6 @@ +//@ revisions: current next +//@ ignore-compare-mode-next-solver (explicit revisions) +//@[next] compile-flags: -Znext-solver #![feature(do_not_recommend)] pub trait Foo {} diff --git a/tests/ui/diagnostic_namespace/do_not_recommend/incorrect-locations.stderr b/tests/ui/diagnostic_namespace/do_not_recommend/incorrect-locations.current.stderr similarity index 82% rename from tests/ui/diagnostic_namespace/do_not_recommend/incorrect-locations.stderr rename to tests/ui/diagnostic_namespace/do_not_recommend/incorrect-locations.current.stderr index c83fd46db584..84ab0827ab68 100644 --- a/tests/ui/diagnostic_namespace/do_not_recommend/incorrect-locations.stderr +++ b/tests/ui/diagnostic_namespace/do_not_recommend/incorrect-locations.current.stderr @@ -1,5 +1,5 @@ warning: `#[diagnostic::do_not_recommend]` can only be placed on trait implementations - --> $DIR/incorrect-locations.rs:4:1 + --> $DIR/incorrect-locations.rs:7:1 | LL | #[diagnostic::do_not_recommend] | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ @@ -7,43 +7,43 @@ LL | #[diagnostic::do_not_recommend] = note: `#[warn(unknown_or_malformed_diagnostic_attributes)]` on by default warning: `#[diagnostic::do_not_recommend]` can only be placed on trait implementations - --> $DIR/incorrect-locations.rs:8:1 + --> $DIR/incorrect-locations.rs:11:1 | LL | #[diagnostic::do_not_recommend] | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ warning: `#[diagnostic::do_not_recommend]` can only be placed on trait implementations - --> $DIR/incorrect-locations.rs:12:1 + --> $DIR/incorrect-locations.rs:15:1 | LL | #[diagnostic::do_not_recommend] | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ warning: `#[diagnostic::do_not_recommend]` can only be placed on trait implementations - --> $DIR/incorrect-locations.rs:16:1 + --> $DIR/incorrect-locations.rs:19:1 | LL | #[diagnostic::do_not_recommend] | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ warning: `#[diagnostic::do_not_recommend]` can only be placed on trait implementations - --> $DIR/incorrect-locations.rs:20:1 + --> $DIR/incorrect-locations.rs:23:1 | LL | #[diagnostic::do_not_recommend] | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ warning: `#[diagnostic::do_not_recommend]` can only be placed on trait implementations - --> $DIR/incorrect-locations.rs:24:1 + --> $DIR/incorrect-locations.rs:27:1 | LL | #[diagnostic::do_not_recommend] | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ warning: `#[diagnostic::do_not_recommend]` can only be placed on trait implementations - --> $DIR/incorrect-locations.rs:28:1 + --> $DIR/incorrect-locations.rs:31:1 | LL | #[diagnostic::do_not_recommend] | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ warning: `#[diagnostic::do_not_recommend]` can only be placed on trait implementations - --> $DIR/incorrect-locations.rs:32:1 + --> $DIR/incorrect-locations.rs:35:1 | LL | #[diagnostic::do_not_recommend] | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ diff --git a/tests/ui/diagnostic_namespace/do_not_recommend/incorrect-locations.next.stderr b/tests/ui/diagnostic_namespace/do_not_recommend/incorrect-locations.next.stderr new file mode 100644 index 000000000000..84ab0827ab68 --- /dev/null +++ b/tests/ui/diagnostic_namespace/do_not_recommend/incorrect-locations.next.stderr @@ -0,0 +1,52 @@ +warning: `#[diagnostic::do_not_recommend]` can only be placed on trait implementations + --> $DIR/incorrect-locations.rs:7:1 + | +LL | #[diagnostic::do_not_recommend] + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | + = note: `#[warn(unknown_or_malformed_diagnostic_attributes)]` on by default + +warning: `#[diagnostic::do_not_recommend]` can only be placed on trait implementations + --> $DIR/incorrect-locations.rs:11:1 + | +LL | #[diagnostic::do_not_recommend] + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +warning: `#[diagnostic::do_not_recommend]` can only be placed on trait implementations + --> $DIR/incorrect-locations.rs:15:1 + | +LL | #[diagnostic::do_not_recommend] + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +warning: `#[diagnostic::do_not_recommend]` can only be placed on trait implementations + --> $DIR/incorrect-locations.rs:19:1 + | +LL | #[diagnostic::do_not_recommend] + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +warning: `#[diagnostic::do_not_recommend]` can only be placed on trait implementations + --> $DIR/incorrect-locations.rs:23:1 + | +LL | #[diagnostic::do_not_recommend] + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +warning: `#[diagnostic::do_not_recommend]` can only be placed on trait implementations + --> $DIR/incorrect-locations.rs:27:1 + | +LL | #[diagnostic::do_not_recommend] + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +warning: `#[diagnostic::do_not_recommend]` can only be placed on trait implementations + --> $DIR/incorrect-locations.rs:31:1 + | +LL | #[diagnostic::do_not_recommend] + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +warning: `#[diagnostic::do_not_recommend]` can only be placed on trait implementations + --> $DIR/incorrect-locations.rs:35:1 + | +LL | #[diagnostic::do_not_recommend] + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +warning: 8 warnings emitted + diff --git a/tests/ui/diagnostic_namespace/do_not_recommend/incorrect-locations.rs b/tests/ui/diagnostic_namespace/do_not_recommend/incorrect-locations.rs index 400ef83873e1..daacf55ea792 100644 --- a/tests/ui/diagnostic_namespace/do_not_recommend/incorrect-locations.rs +++ b/tests/ui/diagnostic_namespace/do_not_recommend/incorrect-locations.rs @@ -1,4 +1,7 @@ //@ check-pass +//@ revisions: current next +//@ ignore-compare-mode-next-solver (explicit revisions) +//@[next] compile-flags: -Znext-solver #![feature(do_not_recommend)] #[diagnostic::do_not_recommend] diff --git a/tests/ui/diagnostic_namespace/do_not_recommend/nested.current.stderr b/tests/ui/diagnostic_namespace/do_not_recommend/nested.current.stderr new file mode 100644 index 000000000000..2e08a6793602 --- /dev/null +++ b/tests/ui/diagnostic_namespace/do_not_recommend/nested.current.stderr @@ -0,0 +1,15 @@ +error[E0277]: the trait bound `(): Root` is not satisfied + --> $DIR/nested.rs:23:18 + | +LL | needs_root::<()>(); + | ^^ the trait `Root` is not implemented for `()` + | +note: required by a bound in `needs_root` + --> $DIR/nested.rs:20:18 + | +LL | fn needs_root() {} + | ^^^^ required by this bound in `needs_root` + +error: aborting due to 1 previous error + +For more information about this error, try `rustc --explain E0277`. diff --git a/tests/ui/diagnostic_namespace/do_not_recommend/nested.next.stderr b/tests/ui/diagnostic_namespace/do_not_recommend/nested.next.stderr new file mode 100644 index 000000000000..2e08a6793602 --- /dev/null +++ b/tests/ui/diagnostic_namespace/do_not_recommend/nested.next.stderr @@ -0,0 +1,15 @@ +error[E0277]: the trait bound `(): Root` is not satisfied + --> $DIR/nested.rs:23:18 + | +LL | needs_root::<()>(); + | ^^ the trait `Root` is not implemented for `()` + | +note: required by a bound in `needs_root` + --> $DIR/nested.rs:20:18 + | +LL | fn needs_root() {} + | ^^^^ required by this bound in `needs_root` + +error: aborting due to 1 previous error + +For more information about this error, try `rustc --explain E0277`. diff --git a/tests/ui/diagnostic_namespace/do_not_recommend/nested.rs b/tests/ui/diagnostic_namespace/do_not_recommend/nested.rs new file mode 100644 index 000000000000..d499cff9f56e --- /dev/null +++ b/tests/ui/diagnostic_namespace/do_not_recommend/nested.rs @@ -0,0 +1,25 @@ +//@ revisions: current next +//@ ignore-compare-mode-next-solver (explicit revisions) +//@[next] compile-flags: -Znext-solver + +#![feature(do_not_recommend)] + +trait Root {} +trait DontRecommend {} +trait Other {} +trait Child {} + +#[diagnostic::do_not_recommend] +impl Root for T where T: DontRecommend {} + +impl DontRecommend for T where T: Other {} + +#[diagnostic::do_not_recommend] +impl Other for T where T: Child {} + +fn needs_root() {} + +fn main() { + needs_root::<()>(); + //~^ ERROR the trait bound `(): Root` is not satisfied +} diff --git a/tests/ui/diagnostic_namespace/do_not_recommend/unstable-feature.stderr b/tests/ui/diagnostic_namespace/do_not_recommend/unstable-feature.current.stderr similarity index 81% rename from tests/ui/diagnostic_namespace/do_not_recommend/unstable-feature.stderr rename to tests/ui/diagnostic_namespace/do_not_recommend/unstable-feature.current.stderr index d8332229d4fc..fdea9eacae14 100644 --- a/tests/ui/diagnostic_namespace/do_not_recommend/unstable-feature.stderr +++ b/tests/ui/diagnostic_namespace/do_not_recommend/unstable-feature.current.stderr @@ -1,11 +1,11 @@ error: unknown diagnostic attribute - --> $DIR/unstable-feature.rs:4:15 + --> $DIR/unstable-feature.rs:7:15 | LL | #[diagnostic::do_not_recommend] | ^^^^^^^^^^^^^^^^ | note: the lint level is defined here - --> $DIR/unstable-feature.rs:1:9 + --> $DIR/unstable-feature.rs:4:9 | LL | #![deny(unknown_or_malformed_diagnostic_attributes)] | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ diff --git a/tests/ui/diagnostic_namespace/do_not_recommend/unstable-feature.next.stderr b/tests/ui/diagnostic_namespace/do_not_recommend/unstable-feature.next.stderr new file mode 100644 index 000000000000..fdea9eacae14 --- /dev/null +++ b/tests/ui/diagnostic_namespace/do_not_recommend/unstable-feature.next.stderr @@ -0,0 +1,14 @@ +error: unknown diagnostic attribute + --> $DIR/unstable-feature.rs:7:15 + | +LL | #[diagnostic::do_not_recommend] + | ^^^^^^^^^^^^^^^^ + | +note: the lint level is defined here + --> $DIR/unstable-feature.rs:4:9 + | +LL | #![deny(unknown_or_malformed_diagnostic_attributes)] + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +error: aborting due to 1 previous error + diff --git a/tests/ui/diagnostic_namespace/do_not_recommend/unstable-feature.rs b/tests/ui/diagnostic_namespace/do_not_recommend/unstable-feature.rs index ccc687aa5b36..7a67f67b67f2 100644 --- a/tests/ui/diagnostic_namespace/do_not_recommend/unstable-feature.rs +++ b/tests/ui/diagnostic_namespace/do_not_recommend/unstable-feature.rs @@ -1,3 +1,6 @@ +//@ revisions: current next +//@ ignore-compare-mode-next-solver (explicit revisions) +//@[next] compile-flags: -Znext-solver #![deny(unknown_or_malformed_diagnostic_attributes)] trait Foo {} diff --git a/tests/ui/diagnostic_namespace/do_not_recommend/with_lifetime.current.stderr b/tests/ui/diagnostic_namespace/do_not_recommend/with_lifetime.current.stderr new file mode 100644 index 000000000000..c2874cf45945 --- /dev/null +++ b/tests/ui/diagnostic_namespace/do_not_recommend/with_lifetime.current.stderr @@ -0,0 +1,10 @@ +error: lifetime may not live long enough + --> $DIR/with_lifetime.rs:19:5 + | +LL | fn foo<'a>(a: &'a ()) { + | -- lifetime `'a` defined here +LL | needs_root::<&'a ()>(); + | ^^^^^^^^^^^^^^^^^^^^ requires that `'a` must outlive `'static` + +error: aborting due to 1 previous error + diff --git a/tests/ui/diagnostic_namespace/do_not_recommend/with_lifetime.next.stderr b/tests/ui/diagnostic_namespace/do_not_recommend/with_lifetime.next.stderr new file mode 100644 index 000000000000..c2874cf45945 --- /dev/null +++ b/tests/ui/diagnostic_namespace/do_not_recommend/with_lifetime.next.stderr @@ -0,0 +1,10 @@ +error: lifetime may not live long enough + --> $DIR/with_lifetime.rs:19:5 + | +LL | fn foo<'a>(a: &'a ()) { + | -- lifetime `'a` defined here +LL | needs_root::<&'a ()>(); + | ^^^^^^^^^^^^^^^^^^^^ requires that `'a` must outlive `'static` + +error: aborting due to 1 previous error + diff --git a/tests/ui/diagnostic_namespace/do_not_recommend/with_lifetime.rs b/tests/ui/diagnostic_namespace/do_not_recommend/with_lifetime.rs new file mode 100644 index 000000000000..9aaf7f33ecdc --- /dev/null +++ b/tests/ui/diagnostic_namespace/do_not_recommend/with_lifetime.rs @@ -0,0 +1,25 @@ +//@ revisions: current next +//@ ignore-compare-mode-next-solver (explicit revisions) +//@[next] compile-flags: -Znext-solver + +#![feature(do_not_recommend)] + +trait Root {} +trait DontRecommend {} + +impl Root for T where T: DontRecommend {} + +// this has no effect yet for resolving the trait error below +#[diagnostic::do_not_recommend] +impl DontRecommend for &'static T {} + +fn needs_root() {} + +fn foo<'a>(a: &'a ()) { + needs_root::<&'a ()>(); + //~^ ERROR lifetime may not live long enough +} + +fn main() { + foo(&()); +} From ecb6fd8d3a98fb5d3c0347d1e15ac79032c63ef4 Mon Sep 17 00:00:00 2001 From: Georg Semmler Date: Wed, 23 Oct 2024 07:48:57 +0200 Subject: [PATCH 36/92] Check `#[diagnostic::do_not_recommend]` for arguments This commit adds a check that verifies that no arguments are passed to `#[diagnostic::do_not_recommend]`. If we detect arguments we emit a warning. --- compiler/rustc_passes/messages.ftl | 3 +++ compiler/rustc_passes/src/check_attr.rs | 18 ++++++++++++-- compiler/rustc_passes/src/errors.rs | 4 ++++ .../does_not_acccept_args.current.stderr | 22 +++++++++++++++++ .../does_not_acccept_args.next.stderr | 22 +++++++++++++++++ .../do_not_recommend/does_not_acccept_args.rs | 24 +++++++++++++++++++ 6 files changed, 91 insertions(+), 2 deletions(-) create mode 100644 tests/ui/diagnostic_namespace/do_not_recommend/does_not_acccept_args.current.stderr create mode 100644 tests/ui/diagnostic_namespace/do_not_recommend/does_not_acccept_args.next.stderr create mode 100644 tests/ui/diagnostic_namespace/do_not_recommend/does_not_acccept_args.rs diff --git a/compiler/rustc_passes/messages.ftl b/compiler/rustc_passes/messages.ftl index fd133ba878e1..9cc94b756246 100644 --- a/compiler/rustc_passes/messages.ftl +++ b/compiler/rustc_passes/messages.ftl @@ -357,6 +357,9 @@ passes_ignored_derived_impls = passes_implied_feature_not_exist = feature `{$implied_by}` implying `{$feature}` does not exist +passes_incorrect_do_not_recommend_args = + `#[diagnostic::do_not_recommend]` does not expect any arguments + passes_incorrect_do_not_recommend_location = `#[diagnostic::do_not_recommend]` can only be placed on trait implementations diff --git a/compiler/rustc_passes/src/check_attr.rs b/compiler/rustc_passes/src/check_attr.rs index ce7947ad3ec4..9879dfa9720e 100644 --- a/compiler/rustc_passes/src/check_attr.rs +++ b/compiler/rustc_passes/src/check_attr.rs @@ -115,7 +115,7 @@ impl<'tcx> CheckAttrVisitor<'tcx> { for attr in attrs { match attr.path().as_slice() { [sym::diagnostic, sym::do_not_recommend, ..] => { - self.check_do_not_recommend(attr.span, hir_id, target) + self.check_do_not_recommend(attr.span, hir_id, target, attr) } [sym::diagnostic, sym::on_unimplemented, ..] => { self.check_diagnostic_on_unimplemented(attr.span, hir_id, target) @@ -348,7 +348,13 @@ impl<'tcx> CheckAttrVisitor<'tcx> { } /// Checks if `#[diagnostic::do_not_recommend]` is applied on a trait impl. - fn check_do_not_recommend(&self, attr_span: Span, hir_id: HirId, target: Target) { + fn check_do_not_recommend( + &self, + attr_span: Span, + hir_id: HirId, + target: Target, + attr: &Attribute, + ) { if !matches!(target, Target::Impl) { self.tcx.emit_node_span_lint( UNKNOWN_OR_MALFORMED_DIAGNOSTIC_ATTRIBUTES, @@ -357,6 +363,14 @@ impl<'tcx> CheckAttrVisitor<'tcx> { errors::IncorrectDoNotRecommendLocation, ); } + if !attr.is_word() { + self.tcx.emit_node_span_lint( + UNKNOWN_OR_MALFORMED_DIAGNOSTIC_ATTRIBUTES, + hir_id, + attr_span, + errors::DoNotRecommendDoesNotExpectArgs, + ); + } } /// Checks if `#[diagnostic::on_unimplemented]` is applied to a trait definition diff --git a/compiler/rustc_passes/src/errors.rs b/compiler/rustc_passes/src/errors.rs index f71d52840526..5e7bfa5e3bb7 100644 --- a/compiler/rustc_passes/src/errors.rs +++ b/compiler/rustc_passes/src/errors.rs @@ -20,6 +20,10 @@ use crate::lang_items::Duplicate; #[diag(passes_incorrect_do_not_recommend_location)] pub(crate) struct IncorrectDoNotRecommendLocation; +#[derive(LintDiagnostic)] +#[diag(passes_incorrect_do_not_recommend_args)] +pub(crate) struct DoNotRecommendDoesNotExpectArgs; + #[derive(Diagnostic)] #[diag(passes_autodiff_attr)] pub(crate) struct AutoDiffAttr { diff --git a/tests/ui/diagnostic_namespace/do_not_recommend/does_not_acccept_args.current.stderr b/tests/ui/diagnostic_namespace/do_not_recommend/does_not_acccept_args.current.stderr new file mode 100644 index 000000000000..3d004ca559e8 --- /dev/null +++ b/tests/ui/diagnostic_namespace/do_not_recommend/does_not_acccept_args.current.stderr @@ -0,0 +1,22 @@ +warning: `#[diagnostic::do_not_recommend]` does not expect any arguments + --> $DIR/does_not_acccept_args.rs:12:1 + | +LL | #[diagnostic::do_not_recommend(not_accepted)] + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | + = note: `#[warn(unknown_or_malformed_diagnostic_attributes)]` on by default + +warning: `#[diagnostic::do_not_recommend]` does not expect any arguments + --> $DIR/does_not_acccept_args.rs:16:1 + | +LL | #[diagnostic::do_not_recommend(not_accepted = "foo")] + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +warning: `#[diagnostic::do_not_recommend]` does not expect any arguments + --> $DIR/does_not_acccept_args.rs:20:1 + | +LL | #[diagnostic::do_not_recommend(not_accepted(42))] + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +warning: 3 warnings emitted + diff --git a/tests/ui/diagnostic_namespace/do_not_recommend/does_not_acccept_args.next.stderr b/tests/ui/diagnostic_namespace/do_not_recommend/does_not_acccept_args.next.stderr new file mode 100644 index 000000000000..3d004ca559e8 --- /dev/null +++ b/tests/ui/diagnostic_namespace/do_not_recommend/does_not_acccept_args.next.stderr @@ -0,0 +1,22 @@ +warning: `#[diagnostic::do_not_recommend]` does not expect any arguments + --> $DIR/does_not_acccept_args.rs:12:1 + | +LL | #[diagnostic::do_not_recommend(not_accepted)] + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | + = note: `#[warn(unknown_or_malformed_diagnostic_attributes)]` on by default + +warning: `#[diagnostic::do_not_recommend]` does not expect any arguments + --> $DIR/does_not_acccept_args.rs:16:1 + | +LL | #[diagnostic::do_not_recommend(not_accepted = "foo")] + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +warning: `#[diagnostic::do_not_recommend]` does not expect any arguments + --> $DIR/does_not_acccept_args.rs:20:1 + | +LL | #[diagnostic::do_not_recommend(not_accepted(42))] + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +warning: 3 warnings emitted + diff --git a/tests/ui/diagnostic_namespace/do_not_recommend/does_not_acccept_args.rs b/tests/ui/diagnostic_namespace/do_not_recommend/does_not_acccept_args.rs new file mode 100644 index 000000000000..f3295546f34b --- /dev/null +++ b/tests/ui/diagnostic_namespace/do_not_recommend/does_not_acccept_args.rs @@ -0,0 +1,24 @@ +//@ check-pass +//@ revisions: current next +//@ ignore-compare-mode-next-solver (explicit revisions) +//@[next] compile-flags: -Znext-solver + +#![feature(do_not_recommend)] + +trait Foo {} +trait Bar {} +trait Baz {} + +#[diagnostic::do_not_recommend(not_accepted)] +//~^ WARNING `#[diagnostic::do_not_recommend]` does not expect any arguments +impl Foo for T where T: Send {} + +#[diagnostic::do_not_recommend(not_accepted = "foo")] +//~^ WARNING `#[diagnostic::do_not_recommend]` does not expect any arguments +impl Bar for T where T: Send {} + +#[diagnostic::do_not_recommend(not_accepted(42))] +//~^ WARNING `#[diagnostic::do_not_recommend]` does not expect any arguments +impl Baz for T where T: Send {} + +fn main() {} From dd31713c53bbd22915ecb0d43043923730726f20 Mon Sep 17 00:00:00 2001 From: Georg Semmler Date: Wed, 23 Oct 2024 08:09:15 +0200 Subject: [PATCH 37/92] Stabilize `#[diagnostic::do_not_recommend]` This commit seeks to stabilize the `#[diagnostic::do_not_recommend]` attribute. This attribute was first proposed as `#[do_not_recommend`] attribute in RFC 2397 (https://github.com/rust-lang/rfcs/pull/2397). It gives the crate authors the ability to not suggest to the compiler to not show certain traits in it's error messages. With the presence of the `#[diagnostic]` tool attribute namespace it was decided to move the attribute there, as that lowers the amount of guarantees the compiler needs to give about the exact way this influences error messages. It turns the attribute into a hint which can be ignored. In addition to the original proposed functionality this attribute now also hides the marked trait in help messages ("This trait is implemented by: "). The attribute does not accept any argument and can only be placed on trait implementations. If it is placed somewhere else a lint warning is emitted and the attribute is otherwise ignored. If an argument is detected a lint warning is emitted and the argument is ignored. This follows the rules outlined by the diagnostic namespace. This attribute allows crates like diesel to improve their error messages drastically. The most common example here is the following error message: ``` error[E0277]: the trait bound `&str: Expression` is not satisfied --> /home/weiznich/Documents/rust/rust/tests/ui/diagnostic_namespace/do_not_recommend.rs:53:15 | LL | SelectInt.check("bar"); | ^^^^^ the trait `Expression` is not implemented for `&str`, which is required by `&str: AsExpression` | = help: the following other types implement trait `Expression`: Bound SelectInt note: required for `&str` to implement `AsExpression` --> /home/weiznich/Documents/rust/rust/tests/ui/diagnostic_namespace/do_not_recommend.rs:26:13 | LL | impl AsExpression for T | ^^^^^^^^^^^^^^^^ ^ LL | where LL | T: Expression, | ------------------------ unsatisfied trait bound introduced here ``` By applying the new attribute to the wild card trait implementation of `AsExpression` for `T: Expression` the error message becomes: ``` error[E0277]: the trait bound `&str: AsExpression` is not satisfied --> $DIR/as_expression.rs:55:15 | LL | SelectInt.check("bar"); | ^^^^^ the trait `AsExpression` is not implemented for `&str` | = help: the trait `AsExpression` is implemented for `&str` = help: for that trait implementation, expected `Text`, found `Integer` ``` which makes it much easier for users to understand that they are facing a type mismatch. Other explored example usages included * This standard library error message: https://github.com/rust-lang/rust/pull/128008 * That bevy derived example: https://github.com/rust-lang/rust/blob/e1f306899514ea80abc1d1c9f6a57762afb304a3/tests/ui/diagnostic_namespace/do_not_recommend/supress_suggestions_in_help.rs (No more tuple pyramids) Fixes #51992 --- compiler/rustc_feature/src/accepted.rs | 2 ++ compiler/rustc_feature/src/builtin_attrs.rs | 5 ++-- compiler/rustc_feature/src/unstable.rs | 2 -- compiler/rustc_resolve/src/macros.rs | 3 +-- library/core/src/lib.rs | 2 +- .../as_expression.current.stderr | 2 +- .../as_expression.next.stderr | 8 +++--- .../do_not_recommend/as_expression.rs | 2 -- ...ribute_without_feature_flag.current.stderr | 25 ------------------- ...attribute_without_feature_flag.next.stderr | 21 ---------------- ...ot_apply_attribute_without_feature_flag.rs | 24 ------------------ .../does_not_acccept_args.current.stderr | 6 ++--- .../does_not_acccept_args.next.stderr | 6 ++--- .../do_not_recommend/does_not_acccept_args.rs | 2 -- ...ature-gate-do_not_recommend.current.stderr | 15 ----------- .../feature-gate-do_not_recommend.next.stderr | 17 ------------- .../feature-gate-do_not_recommend.rs | 20 --------------- .../incorrect-locations.current.stderr | 16 ++++++------ .../incorrect-locations.next.stderr | 16 ++++++------ .../do_not_recommend/incorrect-locations.rs | 1 - .../do_not_recommend/nested.current.stderr | 4 +-- .../do_not_recommend/nested.next.stderr | 4 +-- .../do_not_recommend/nested.rs | 2 -- .../do_not_recommend/simple.current.stderr | 4 +-- .../do_not_recommend/simple.next.stderr | 4 +-- .../do_not_recommend/simple.rs | 2 -- .../do_not_recommend/stacked.current.stderr | 4 +-- .../do_not_recommend/stacked.next.stderr | 4 +-- .../do_not_recommend/stacked.rs | 2 -- ...supress_suggestions_in_help.current.stderr | 4 +-- .../supress_suggestions_in_help.next.stderr | 4 +-- .../supress_suggestions_in_help.rs | 2 -- .../type_mismatch.current.stderr | 4 +-- .../type_mismatch.next.stderr | 4 +-- .../do_not_recommend/type_mismatch.rs | 2 -- .../unstable-feature.current.stderr | 14 ----------- .../unstable-feature.next.stderr | 14 ----------- .../do_not_recommend/unstable-feature.rs | 11 -------- .../with_lifetime.current.stderr | 2 +- .../with_lifetime.next.stderr | 2 +- .../do_not_recommend/with_lifetime.rs | 2 -- 41 files changed, 55 insertions(+), 235 deletions(-) delete mode 100644 tests/ui/diagnostic_namespace/do_not_recommend/do_not_apply_attribute_without_feature_flag.current.stderr delete mode 100644 tests/ui/diagnostic_namespace/do_not_recommend/do_not_apply_attribute_without_feature_flag.next.stderr delete mode 100644 tests/ui/diagnostic_namespace/do_not_recommend/do_not_apply_attribute_without_feature_flag.rs delete mode 100644 tests/ui/diagnostic_namespace/do_not_recommend/feature-gate-do_not_recommend.current.stderr delete mode 100644 tests/ui/diagnostic_namespace/do_not_recommend/feature-gate-do_not_recommend.next.stderr delete mode 100644 tests/ui/diagnostic_namespace/do_not_recommend/feature-gate-do_not_recommend.rs delete mode 100644 tests/ui/diagnostic_namespace/do_not_recommend/unstable-feature.current.stderr delete mode 100644 tests/ui/diagnostic_namespace/do_not_recommend/unstable-feature.next.stderr delete mode 100644 tests/ui/diagnostic_namespace/do_not_recommend/unstable-feature.rs diff --git a/compiler/rustc_feature/src/accepted.rs b/compiler/rustc_feature/src/accepted.rs index 21fd11c1c5da..5a9b8c43e746 100644 --- a/compiler/rustc_feature/src/accepted.rs +++ b/compiler/rustc_feature/src/accepted.rs @@ -178,6 +178,8 @@ declare_features! ( (accepted, destructuring_assignment, "1.59.0", Some(71126)), /// Allows using the `#[diagnostic]` attribute tool namespace (accepted, diagnostic_namespace, "1.78.0", Some(111996)), + /// Controls errors in trait implementations. + (accepted, do_not_recommend, "CURRENT_RUSTC_VERSION", Some(51992)), /// Allows `#[doc(alias = "...")]`. (accepted, doc_alias, "1.48.0", Some(50146)), /// Allows `..` in tuple (struct) patterns. diff --git a/compiler/rustc_feature/src/builtin_attrs.rs b/compiler/rustc_feature/src/builtin_attrs.rs index a065db7f7d0f..4b9f62fa764c 100644 --- a/compiler/rustc_feature/src/builtin_attrs.rs +++ b/compiler/rustc_feature/src/builtin_attrs.rs @@ -1187,10 +1187,9 @@ pub static BUILTIN_ATTRIBUTE_MAP: LazyLock> map }); -pub fn is_stable_diagnostic_attribute(sym: Symbol, features: &Features) -> bool { +pub fn is_stable_diagnostic_attribute(sym: Symbol, _features: &Features) -> bool { match sym { - sym::on_unimplemented => true, - sym::do_not_recommend => features.do_not_recommend(), + sym::on_unimplemented | sym::do_not_recommend => true, _ => false, } } diff --git a/compiler/rustc_feature/src/unstable.rs b/compiler/rustc_feature/src/unstable.rs index 6570f9b565ff..ebb07195a285 100644 --- a/compiler/rustc_feature/src/unstable.rs +++ b/compiler/rustc_feature/src/unstable.rs @@ -462,8 +462,6 @@ declare_features! ( (unstable, deprecated_suggestion, "1.61.0", Some(94785)), /// Allows deref patterns. (incomplete, deref_patterns, "1.79.0", Some(87121)), - /// Controls errors in trait implementations. - (unstable, do_not_recommend, "1.67.0", Some(51992)), /// Tells rustdoc to automatically generate `#[doc(cfg(...))]`. (unstable, doc_auto_cfg, "1.58.0", Some(43781)), /// Allows `#[doc(cfg(...))]`. diff --git a/compiler/rustc_resolve/src/macros.rs b/compiler/rustc_resolve/src/macros.rs index edee19c280a8..b24e343c58df 100644 --- a/compiler/rustc_resolve/src/macros.rs +++ b/compiler/rustc_resolve/src/macros.rs @@ -689,8 +689,7 @@ impl<'ra, 'tcx> Resolver<'ra, 'tcx> { && let [namespace, attribute, ..] = &*path.segments && namespace.ident.name == sym::diagnostic && !(attribute.ident.name == sym::on_unimplemented - || (attribute.ident.name == sym::do_not_recommend - && self.tcx.features().do_not_recommend())) + || attribute.ident.name == sym::do_not_recommend) { let distance = edit_distance(attribute.ident.name.as_str(), sym::on_unimplemented.as_str(), 5); diff --git a/library/core/src/lib.rs b/library/core/src/lib.rs index 922866f95dcf..18bd9bb81183 100644 --- a/library/core/src/lib.rs +++ b/library/core/src/lib.rs @@ -108,12 +108,12 @@ // Library features: // tidy-alphabetical-start #![cfg_attr(bootstrap, feature(coverage_attribute))] +#![cfg_attr(bootstrap, feature(do_not_recommend))] #![feature(array_ptr_get)] #![feature(asm_experimental_arch)] #![feature(const_eval_select)] #![feature(const_typed_swap)] #![feature(core_intrinsics)] -#![feature(do_not_recommend)] #![feature(internal_impls_macro)] #![feature(ip)] #![feature(is_ascii_octdigit)] diff --git a/tests/ui/diagnostic_namespace/do_not_recommend/as_expression.current.stderr b/tests/ui/diagnostic_namespace/do_not_recommend/as_expression.current.stderr index 5d0c18264110..28e7975c7a23 100644 --- a/tests/ui/diagnostic_namespace/do_not_recommend/as_expression.current.stderr +++ b/tests/ui/diagnostic_namespace/do_not_recommend/as_expression.current.stderr @@ -1,5 +1,5 @@ error[E0277]: the trait bound `&str: AsExpression` is not satisfied - --> $DIR/as_expression.rs:57:15 + --> $DIR/as_expression.rs:55:15 | LL | SelectInt.check("bar"); | ^^^^^ the trait `AsExpression` is not implemented for `&str` diff --git a/tests/ui/diagnostic_namespace/do_not_recommend/as_expression.next.stderr b/tests/ui/diagnostic_namespace/do_not_recommend/as_expression.next.stderr index 1e1eae852f91..1b76669ccb0d 100644 --- a/tests/ui/diagnostic_namespace/do_not_recommend/as_expression.next.stderr +++ b/tests/ui/diagnostic_namespace/do_not_recommend/as_expression.next.stderr @@ -1,5 +1,5 @@ error[E0277]: the trait bound `&str: AsExpression<::SqlType>` is not satisfied - --> $DIR/as_expression.rs:57:21 + --> $DIR/as_expression.rs:55:21 | LL | SelectInt.check("bar"); | ----- ^^^^^ the trait `AsExpression<::SqlType>` is not implemented for `&str` @@ -8,7 +8,7 @@ LL | SelectInt.check("bar"); | = help: the trait `AsExpression` is implemented for `&str` note: required by a bound in `Foo::check` - --> $DIR/as_expression.rs:48:12 + --> $DIR/as_expression.rs:46:12 | LL | fn check(&self, _: T) -> ::SqlType>>::Expression | ----- required by a bound in this associated function @@ -17,7 +17,7 @@ LL | T: AsExpression, | ^^^^^^^^^^^^^^^^^^^^^^^^^^^ required by this bound in `Foo::check` error[E0277]: the trait bound `&str: AsExpression` is not satisfied - --> $DIR/as_expression.rs:57:15 + --> $DIR/as_expression.rs:55:15 | LL | SelectInt.check("bar"); | ^^^^^ the trait `AsExpression` is not implemented for `&str` @@ -27,7 +27,7 @@ LL | SelectInt.check("bar"); = help: for that trait implementation, expected `Text`, found `Integer` error[E0271]: type mismatch resolving `::SqlType == Text` - --> $DIR/as_expression.rs:57:5 + --> $DIR/as_expression.rs:55:5 | LL | SelectInt.check("bar"); | ^^^^^^^^^^^^^^^^^^^^^^ expected `Text`, found `Integer` diff --git a/tests/ui/diagnostic_namespace/do_not_recommend/as_expression.rs b/tests/ui/diagnostic_namespace/do_not_recommend/as_expression.rs index 37b4429f694c..583b3c4675a8 100644 --- a/tests/ui/diagnostic_namespace/do_not_recommend/as_expression.rs +++ b/tests/ui/diagnostic_namespace/do_not_recommend/as_expression.rs @@ -2,8 +2,6 @@ //@ ignore-compare-mode-next-solver (explicit revisions) //@[next] compile-flags: -Znext-solver -#![feature(do_not_recommend)] - pub trait Expression { type SqlType; } diff --git a/tests/ui/diagnostic_namespace/do_not_recommend/do_not_apply_attribute_without_feature_flag.current.stderr b/tests/ui/diagnostic_namespace/do_not_recommend/do_not_apply_attribute_without_feature_flag.current.stderr deleted file mode 100644 index 660fc7d21714..000000000000 --- a/tests/ui/diagnostic_namespace/do_not_recommend/do_not_apply_attribute_without_feature_flag.current.stderr +++ /dev/null @@ -1,25 +0,0 @@ -error[E0277]: the trait bound `(): Foo` is not satisfied - --> $DIR/do_not_apply_attribute_without_feature_flag.rs:22:11 - | -LL | check(()); - | ----- ^^ the trait `Foo` is not implemented for `()` - | | - | required by a bound introduced by this call - | - = help: the following other types implement trait `Foo`: - (A, B) - (A, B, C) - (A,) -note: required by a bound in `check` - --> $DIR/do_not_apply_attribute_without_feature_flag.rs:19:18 - | -LL | fn check(a: impl Foo) {} - | ^^^ required by this bound in `check` -help: use a unary tuple instead - | -LL | check(((),)); - | + ++ - -error: aborting due to 1 previous error - -For more information about this error, try `rustc --explain E0277`. diff --git a/tests/ui/diagnostic_namespace/do_not_recommend/do_not_apply_attribute_without_feature_flag.next.stderr b/tests/ui/diagnostic_namespace/do_not_recommend/do_not_apply_attribute_without_feature_flag.next.stderr deleted file mode 100644 index 1cd148186f1e..000000000000 --- a/tests/ui/diagnostic_namespace/do_not_recommend/do_not_apply_attribute_without_feature_flag.next.stderr +++ /dev/null @@ -1,21 +0,0 @@ -error[E0277]: the trait bound `(): Foo` is not satisfied - --> $DIR/do_not_apply_attribute_without_feature_flag.rs:22:11 - | -LL | check(()); - | ----- ^^ the trait `Foo` is not implemented for `()` - | | - | required by a bound introduced by this call - | - = help: the following other types implement trait `Foo`: - (A, B) - (A, B, C) - (A,) -note: required by a bound in `check` - --> $DIR/do_not_apply_attribute_without_feature_flag.rs:19:18 - | -LL | fn check(a: impl Foo) {} - | ^^^ required by this bound in `check` - -error: aborting due to 1 previous error - -For more information about this error, try `rustc --explain E0277`. diff --git a/tests/ui/diagnostic_namespace/do_not_recommend/do_not_apply_attribute_without_feature_flag.rs b/tests/ui/diagnostic_namespace/do_not_recommend/do_not_apply_attribute_without_feature_flag.rs deleted file mode 100644 index 9c25069bc7d5..000000000000 --- a/tests/ui/diagnostic_namespace/do_not_recommend/do_not_apply_attribute_without_feature_flag.rs +++ /dev/null @@ -1,24 +0,0 @@ -//@ revisions: current next -//@ ignore-compare-mode-next-solver (explicit revisions) -//@[next] compile-flags: -Znext-solver -#![allow(unknown_or_malformed_diagnostic_attributes)] - -trait Foo {} - -#[diagnostic::do_not_recommend] -impl Foo for (A,) {} - -#[diagnostic::do_not_recommend] -impl Foo for (A, B) {} - -#[diagnostic::do_not_recommend] -impl Foo for (A, B, C) {} - -impl Foo for i32 {} - -fn check(a: impl Foo) {} - -fn main() { - check(()); - //~^ ERROR the trait bound `(): Foo` is not satisfied -} diff --git a/tests/ui/diagnostic_namespace/do_not_recommend/does_not_acccept_args.current.stderr b/tests/ui/diagnostic_namespace/do_not_recommend/does_not_acccept_args.current.stderr index 3d004ca559e8..47597a5d405e 100644 --- a/tests/ui/diagnostic_namespace/do_not_recommend/does_not_acccept_args.current.stderr +++ b/tests/ui/diagnostic_namespace/do_not_recommend/does_not_acccept_args.current.stderr @@ -1,5 +1,5 @@ warning: `#[diagnostic::do_not_recommend]` does not expect any arguments - --> $DIR/does_not_acccept_args.rs:12:1 + --> $DIR/does_not_acccept_args.rs:10:1 | LL | #[diagnostic::do_not_recommend(not_accepted)] | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ @@ -7,13 +7,13 @@ LL | #[diagnostic::do_not_recommend(not_accepted)] = note: `#[warn(unknown_or_malformed_diagnostic_attributes)]` on by default warning: `#[diagnostic::do_not_recommend]` does not expect any arguments - --> $DIR/does_not_acccept_args.rs:16:1 + --> $DIR/does_not_acccept_args.rs:14:1 | LL | #[diagnostic::do_not_recommend(not_accepted = "foo")] | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ warning: `#[diagnostic::do_not_recommend]` does not expect any arguments - --> $DIR/does_not_acccept_args.rs:20:1 + --> $DIR/does_not_acccept_args.rs:18:1 | LL | #[diagnostic::do_not_recommend(not_accepted(42))] | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ diff --git a/tests/ui/diagnostic_namespace/do_not_recommend/does_not_acccept_args.next.stderr b/tests/ui/diagnostic_namespace/do_not_recommend/does_not_acccept_args.next.stderr index 3d004ca559e8..47597a5d405e 100644 --- a/tests/ui/diagnostic_namespace/do_not_recommend/does_not_acccept_args.next.stderr +++ b/tests/ui/diagnostic_namespace/do_not_recommend/does_not_acccept_args.next.stderr @@ -1,5 +1,5 @@ warning: `#[diagnostic::do_not_recommend]` does not expect any arguments - --> $DIR/does_not_acccept_args.rs:12:1 + --> $DIR/does_not_acccept_args.rs:10:1 | LL | #[diagnostic::do_not_recommend(not_accepted)] | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ @@ -7,13 +7,13 @@ LL | #[diagnostic::do_not_recommend(not_accepted)] = note: `#[warn(unknown_or_malformed_diagnostic_attributes)]` on by default warning: `#[diagnostic::do_not_recommend]` does not expect any arguments - --> $DIR/does_not_acccept_args.rs:16:1 + --> $DIR/does_not_acccept_args.rs:14:1 | LL | #[diagnostic::do_not_recommend(not_accepted = "foo")] | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ warning: `#[diagnostic::do_not_recommend]` does not expect any arguments - --> $DIR/does_not_acccept_args.rs:20:1 + --> $DIR/does_not_acccept_args.rs:18:1 | LL | #[diagnostic::do_not_recommend(not_accepted(42))] | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ diff --git a/tests/ui/diagnostic_namespace/do_not_recommend/does_not_acccept_args.rs b/tests/ui/diagnostic_namespace/do_not_recommend/does_not_acccept_args.rs index f3295546f34b..eeff5e2e6e8f 100644 --- a/tests/ui/diagnostic_namespace/do_not_recommend/does_not_acccept_args.rs +++ b/tests/ui/diagnostic_namespace/do_not_recommend/does_not_acccept_args.rs @@ -3,8 +3,6 @@ //@ ignore-compare-mode-next-solver (explicit revisions) //@[next] compile-flags: -Znext-solver -#![feature(do_not_recommend)] - trait Foo {} trait Bar {} trait Baz {} diff --git a/tests/ui/diagnostic_namespace/do_not_recommend/feature-gate-do_not_recommend.current.stderr b/tests/ui/diagnostic_namespace/do_not_recommend/feature-gate-do_not_recommend.current.stderr deleted file mode 100644 index d1deaa6a0062..000000000000 --- a/tests/ui/diagnostic_namespace/do_not_recommend/feature-gate-do_not_recommend.current.stderr +++ /dev/null @@ -1,15 +0,0 @@ -error[E0277]: the trait bound `u8: Bar` is not satisfied - --> $DIR/feature-gate-do_not_recommend.rs:18:11 - | -LL | stuff(1u8); - | ^^^ the trait `Bar` is not implemented for `u8` - | -note: required by a bound in `stuff` - --> $DIR/feature-gate-do_not_recommend.rs:15:13 - | -LL | fn stuff(_: T) {} - | ^^^ required by this bound in `stuff` - -error: aborting due to 1 previous error - -For more information about this error, try `rustc --explain E0277`. diff --git a/tests/ui/diagnostic_namespace/do_not_recommend/feature-gate-do_not_recommend.next.stderr b/tests/ui/diagnostic_namespace/do_not_recommend/feature-gate-do_not_recommend.next.stderr deleted file mode 100644 index 5bfcc60edc55..000000000000 --- a/tests/ui/diagnostic_namespace/do_not_recommend/feature-gate-do_not_recommend.next.stderr +++ /dev/null @@ -1,17 +0,0 @@ -error[E0277]: the trait bound `u8: Bar` is not satisfied - --> $DIR/feature-gate-do_not_recommend.rs:18:11 - | -LL | stuff(1u8); - | ----- ^^^ the trait `Bar` is not implemented for `u8` - | | - | required by a bound introduced by this call - | -note: required by a bound in `stuff` - --> $DIR/feature-gate-do_not_recommend.rs:15:13 - | -LL | fn stuff(_: T) {} - | ^^^ required by this bound in `stuff` - -error: aborting due to 1 previous error - -For more information about this error, try `rustc --explain E0277`. diff --git a/tests/ui/diagnostic_namespace/do_not_recommend/feature-gate-do_not_recommend.rs b/tests/ui/diagnostic_namespace/do_not_recommend/feature-gate-do_not_recommend.rs deleted file mode 100644 index 4adce112f15e..000000000000 --- a/tests/ui/diagnostic_namespace/do_not_recommend/feature-gate-do_not_recommend.rs +++ /dev/null @@ -1,20 +0,0 @@ -//@ revisions: current next -//@ ignore-compare-mode-next-solver (explicit revisions) -//@[next] compile-flags: -Znext-solver -#![feature(do_not_recommend)] - -pub trait Foo {} - -impl Foo for i32 {} - -pub trait Bar {} - -#[diagnostic::do_not_recommend] -impl Bar for T {} - -fn stuff(_: T) {} - -fn main() { - stuff(1u8); - //~^ the trait bound `u8: Bar` is not satisfied -} diff --git a/tests/ui/diagnostic_namespace/do_not_recommend/incorrect-locations.current.stderr b/tests/ui/diagnostic_namespace/do_not_recommend/incorrect-locations.current.stderr index 84ab0827ab68..0b0dac32b39f 100644 --- a/tests/ui/diagnostic_namespace/do_not_recommend/incorrect-locations.current.stderr +++ b/tests/ui/diagnostic_namespace/do_not_recommend/incorrect-locations.current.stderr @@ -1,5 +1,5 @@ warning: `#[diagnostic::do_not_recommend]` can only be placed on trait implementations - --> $DIR/incorrect-locations.rs:7:1 + --> $DIR/incorrect-locations.rs:6:1 | LL | #[diagnostic::do_not_recommend] | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ @@ -7,43 +7,43 @@ LL | #[diagnostic::do_not_recommend] = note: `#[warn(unknown_or_malformed_diagnostic_attributes)]` on by default warning: `#[diagnostic::do_not_recommend]` can only be placed on trait implementations - --> $DIR/incorrect-locations.rs:11:1 + --> $DIR/incorrect-locations.rs:10:1 | LL | #[diagnostic::do_not_recommend] | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ warning: `#[diagnostic::do_not_recommend]` can only be placed on trait implementations - --> $DIR/incorrect-locations.rs:15:1 + --> $DIR/incorrect-locations.rs:14:1 | LL | #[diagnostic::do_not_recommend] | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ warning: `#[diagnostic::do_not_recommend]` can only be placed on trait implementations - --> $DIR/incorrect-locations.rs:19:1 + --> $DIR/incorrect-locations.rs:18:1 | LL | #[diagnostic::do_not_recommend] | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ warning: `#[diagnostic::do_not_recommend]` can only be placed on trait implementations - --> $DIR/incorrect-locations.rs:23:1 + --> $DIR/incorrect-locations.rs:22:1 | LL | #[diagnostic::do_not_recommend] | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ warning: `#[diagnostic::do_not_recommend]` can only be placed on trait implementations - --> $DIR/incorrect-locations.rs:27:1 + --> $DIR/incorrect-locations.rs:26:1 | LL | #[diagnostic::do_not_recommend] | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ warning: `#[diagnostic::do_not_recommend]` can only be placed on trait implementations - --> $DIR/incorrect-locations.rs:31:1 + --> $DIR/incorrect-locations.rs:30:1 | LL | #[diagnostic::do_not_recommend] | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ warning: `#[diagnostic::do_not_recommend]` can only be placed on trait implementations - --> $DIR/incorrect-locations.rs:35:1 + --> $DIR/incorrect-locations.rs:34:1 | LL | #[diagnostic::do_not_recommend] | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ diff --git a/tests/ui/diagnostic_namespace/do_not_recommend/incorrect-locations.next.stderr b/tests/ui/diagnostic_namespace/do_not_recommend/incorrect-locations.next.stderr index 84ab0827ab68..0b0dac32b39f 100644 --- a/tests/ui/diagnostic_namespace/do_not_recommend/incorrect-locations.next.stderr +++ b/tests/ui/diagnostic_namespace/do_not_recommend/incorrect-locations.next.stderr @@ -1,5 +1,5 @@ warning: `#[diagnostic::do_not_recommend]` can only be placed on trait implementations - --> $DIR/incorrect-locations.rs:7:1 + --> $DIR/incorrect-locations.rs:6:1 | LL | #[diagnostic::do_not_recommend] | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ @@ -7,43 +7,43 @@ LL | #[diagnostic::do_not_recommend] = note: `#[warn(unknown_or_malformed_diagnostic_attributes)]` on by default warning: `#[diagnostic::do_not_recommend]` can only be placed on trait implementations - --> $DIR/incorrect-locations.rs:11:1 + --> $DIR/incorrect-locations.rs:10:1 | LL | #[diagnostic::do_not_recommend] | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ warning: `#[diagnostic::do_not_recommend]` can only be placed on trait implementations - --> $DIR/incorrect-locations.rs:15:1 + --> $DIR/incorrect-locations.rs:14:1 | LL | #[diagnostic::do_not_recommend] | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ warning: `#[diagnostic::do_not_recommend]` can only be placed on trait implementations - --> $DIR/incorrect-locations.rs:19:1 + --> $DIR/incorrect-locations.rs:18:1 | LL | #[diagnostic::do_not_recommend] | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ warning: `#[diagnostic::do_not_recommend]` can only be placed on trait implementations - --> $DIR/incorrect-locations.rs:23:1 + --> $DIR/incorrect-locations.rs:22:1 | LL | #[diagnostic::do_not_recommend] | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ warning: `#[diagnostic::do_not_recommend]` can only be placed on trait implementations - --> $DIR/incorrect-locations.rs:27:1 + --> $DIR/incorrect-locations.rs:26:1 | LL | #[diagnostic::do_not_recommend] | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ warning: `#[diagnostic::do_not_recommend]` can only be placed on trait implementations - --> $DIR/incorrect-locations.rs:31:1 + --> $DIR/incorrect-locations.rs:30:1 | LL | #[diagnostic::do_not_recommend] | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ warning: `#[diagnostic::do_not_recommend]` can only be placed on trait implementations - --> $DIR/incorrect-locations.rs:35:1 + --> $DIR/incorrect-locations.rs:34:1 | LL | #[diagnostic::do_not_recommend] | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ diff --git a/tests/ui/diagnostic_namespace/do_not_recommend/incorrect-locations.rs b/tests/ui/diagnostic_namespace/do_not_recommend/incorrect-locations.rs index daacf55ea792..014be580f61f 100644 --- a/tests/ui/diagnostic_namespace/do_not_recommend/incorrect-locations.rs +++ b/tests/ui/diagnostic_namespace/do_not_recommend/incorrect-locations.rs @@ -2,7 +2,6 @@ //@ revisions: current next //@ ignore-compare-mode-next-solver (explicit revisions) //@[next] compile-flags: -Znext-solver -#![feature(do_not_recommend)] #[diagnostic::do_not_recommend] //~^WARN `#[diagnostic::do_not_recommend]` can only be placed diff --git a/tests/ui/diagnostic_namespace/do_not_recommend/nested.current.stderr b/tests/ui/diagnostic_namespace/do_not_recommend/nested.current.stderr index 2e08a6793602..b14c68d68976 100644 --- a/tests/ui/diagnostic_namespace/do_not_recommend/nested.current.stderr +++ b/tests/ui/diagnostic_namespace/do_not_recommend/nested.current.stderr @@ -1,11 +1,11 @@ error[E0277]: the trait bound `(): Root` is not satisfied - --> $DIR/nested.rs:23:18 + --> $DIR/nested.rs:21:18 | LL | needs_root::<()>(); | ^^ the trait `Root` is not implemented for `()` | note: required by a bound in `needs_root` - --> $DIR/nested.rs:20:18 + --> $DIR/nested.rs:18:18 | LL | fn needs_root() {} | ^^^^ required by this bound in `needs_root` diff --git a/tests/ui/diagnostic_namespace/do_not_recommend/nested.next.stderr b/tests/ui/diagnostic_namespace/do_not_recommend/nested.next.stderr index 2e08a6793602..b14c68d68976 100644 --- a/tests/ui/diagnostic_namespace/do_not_recommend/nested.next.stderr +++ b/tests/ui/diagnostic_namespace/do_not_recommend/nested.next.stderr @@ -1,11 +1,11 @@ error[E0277]: the trait bound `(): Root` is not satisfied - --> $DIR/nested.rs:23:18 + --> $DIR/nested.rs:21:18 | LL | needs_root::<()>(); | ^^ the trait `Root` is not implemented for `()` | note: required by a bound in `needs_root` - --> $DIR/nested.rs:20:18 + --> $DIR/nested.rs:18:18 | LL | fn needs_root() {} | ^^^^ required by this bound in `needs_root` diff --git a/tests/ui/diagnostic_namespace/do_not_recommend/nested.rs b/tests/ui/diagnostic_namespace/do_not_recommend/nested.rs index d499cff9f56e..6534157d1fb2 100644 --- a/tests/ui/diagnostic_namespace/do_not_recommend/nested.rs +++ b/tests/ui/diagnostic_namespace/do_not_recommend/nested.rs @@ -2,8 +2,6 @@ //@ ignore-compare-mode-next-solver (explicit revisions) //@[next] compile-flags: -Znext-solver -#![feature(do_not_recommend)] - trait Root {} trait DontRecommend {} trait Other {} diff --git a/tests/ui/diagnostic_namespace/do_not_recommend/simple.current.stderr b/tests/ui/diagnostic_namespace/do_not_recommend/simple.current.stderr index 729cb5694e21..884b13c17b80 100644 --- a/tests/ui/diagnostic_namespace/do_not_recommend/simple.current.stderr +++ b/tests/ui/diagnostic_namespace/do_not_recommend/simple.current.stderr @@ -1,11 +1,11 @@ error[E0277]: the trait bound `*mut (): Foo` is not satisfied - --> $DIR/simple.rs:17:17 + --> $DIR/simple.rs:15:17 | LL | needs_foo::<*mut ()>(); | ^^^^^^^ the trait `Foo` is not implemented for `*mut ()` | note: required by a bound in `needs_foo` - --> $DIR/simple.rs:12:17 + --> $DIR/simple.rs:10:17 | LL | fn needs_foo() {} | ^^^ required by this bound in `needs_foo` diff --git a/tests/ui/diagnostic_namespace/do_not_recommend/simple.next.stderr b/tests/ui/diagnostic_namespace/do_not_recommend/simple.next.stderr index 729cb5694e21..884b13c17b80 100644 --- a/tests/ui/diagnostic_namespace/do_not_recommend/simple.next.stderr +++ b/tests/ui/diagnostic_namespace/do_not_recommend/simple.next.stderr @@ -1,11 +1,11 @@ error[E0277]: the trait bound `*mut (): Foo` is not satisfied - --> $DIR/simple.rs:17:17 + --> $DIR/simple.rs:15:17 | LL | needs_foo::<*mut ()>(); | ^^^^^^^ the trait `Foo` is not implemented for `*mut ()` | note: required by a bound in `needs_foo` - --> $DIR/simple.rs:12:17 + --> $DIR/simple.rs:10:17 | LL | fn needs_foo() {} | ^^^ required by this bound in `needs_foo` diff --git a/tests/ui/diagnostic_namespace/do_not_recommend/simple.rs b/tests/ui/diagnostic_namespace/do_not_recommend/simple.rs index 780649b009c6..6bca2b724d24 100644 --- a/tests/ui/diagnostic_namespace/do_not_recommend/simple.rs +++ b/tests/ui/diagnostic_namespace/do_not_recommend/simple.rs @@ -2,8 +2,6 @@ //@ ignore-compare-mode-next-solver (explicit revisions) //@[next] compile-flags: -Znext-solver -#![feature(do_not_recommend)] - trait Foo {} #[diagnostic::do_not_recommend] diff --git a/tests/ui/diagnostic_namespace/do_not_recommend/stacked.current.stderr b/tests/ui/diagnostic_namespace/do_not_recommend/stacked.current.stderr index 41a10a61e1df..d86058063955 100644 --- a/tests/ui/diagnostic_namespace/do_not_recommend/stacked.current.stderr +++ b/tests/ui/diagnostic_namespace/do_not_recommend/stacked.current.stderr @@ -1,11 +1,11 @@ error[E0277]: the trait bound `(): Root` is not satisfied - --> $DIR/stacked.rs:19:18 + --> $DIR/stacked.rs:17:18 | LL | needs_root::<()>(); | ^^ the trait `Root` is not implemented for `()` | note: required by a bound in `needs_root` - --> $DIR/stacked.rs:16:18 + --> $DIR/stacked.rs:14:18 | LL | fn needs_root() {} | ^^^^ required by this bound in `needs_root` diff --git a/tests/ui/diagnostic_namespace/do_not_recommend/stacked.next.stderr b/tests/ui/diagnostic_namespace/do_not_recommend/stacked.next.stderr index 41a10a61e1df..d86058063955 100644 --- a/tests/ui/diagnostic_namespace/do_not_recommend/stacked.next.stderr +++ b/tests/ui/diagnostic_namespace/do_not_recommend/stacked.next.stderr @@ -1,11 +1,11 @@ error[E0277]: the trait bound `(): Root` is not satisfied - --> $DIR/stacked.rs:19:18 + --> $DIR/stacked.rs:17:18 | LL | needs_root::<()>(); | ^^ the trait `Root` is not implemented for `()` | note: required by a bound in `needs_root` - --> $DIR/stacked.rs:16:18 + --> $DIR/stacked.rs:14:18 | LL | fn needs_root() {} | ^^^^ required by this bound in `needs_root` diff --git a/tests/ui/diagnostic_namespace/do_not_recommend/stacked.rs b/tests/ui/diagnostic_namespace/do_not_recommend/stacked.rs index fc355bdc4e20..842e04b9d901 100644 --- a/tests/ui/diagnostic_namespace/do_not_recommend/stacked.rs +++ b/tests/ui/diagnostic_namespace/do_not_recommend/stacked.rs @@ -2,8 +2,6 @@ //@ ignore-compare-mode-next-solver (explicit revisions) //@[next] compile-flags: -Znext-solver -#![feature(do_not_recommend)] - trait Root {} trait DontRecommend {} trait Other {} diff --git a/tests/ui/diagnostic_namespace/do_not_recommend/supress_suggestions_in_help.current.stderr b/tests/ui/diagnostic_namespace/do_not_recommend/supress_suggestions_in_help.current.stderr index ca9a6ebc1c45..95ccbb92a89b 100644 --- a/tests/ui/diagnostic_namespace/do_not_recommend/supress_suggestions_in_help.current.stderr +++ b/tests/ui/diagnostic_namespace/do_not_recommend/supress_suggestions_in_help.current.stderr @@ -1,5 +1,5 @@ error[E0277]: the trait bound `(): Foo` is not satisfied - --> $DIR/supress_suggestions_in_help.rs:23:11 + --> $DIR/supress_suggestions_in_help.rs:21:11 | LL | check(()); | ----- ^^ the trait `Foo` is not implemented for `()` @@ -8,7 +8,7 @@ LL | check(()); | = help: the trait `Foo` is implemented for `i32` note: required by a bound in `check` - --> $DIR/supress_suggestions_in_help.rs:20:18 + --> $DIR/supress_suggestions_in_help.rs:18:18 | LL | fn check(a: impl Foo) {} | ^^^ required by this bound in `check` diff --git a/tests/ui/diagnostic_namespace/do_not_recommend/supress_suggestions_in_help.next.stderr b/tests/ui/diagnostic_namespace/do_not_recommend/supress_suggestions_in_help.next.stderr index ca9a6ebc1c45..95ccbb92a89b 100644 --- a/tests/ui/diagnostic_namespace/do_not_recommend/supress_suggestions_in_help.next.stderr +++ b/tests/ui/diagnostic_namespace/do_not_recommend/supress_suggestions_in_help.next.stderr @@ -1,5 +1,5 @@ error[E0277]: the trait bound `(): Foo` is not satisfied - --> $DIR/supress_suggestions_in_help.rs:23:11 + --> $DIR/supress_suggestions_in_help.rs:21:11 | LL | check(()); | ----- ^^ the trait `Foo` is not implemented for `()` @@ -8,7 +8,7 @@ LL | check(()); | = help: the trait `Foo` is implemented for `i32` note: required by a bound in `check` - --> $DIR/supress_suggestions_in_help.rs:20:18 + --> $DIR/supress_suggestions_in_help.rs:18:18 | LL | fn check(a: impl Foo) {} | ^^^ required by this bound in `check` diff --git a/tests/ui/diagnostic_namespace/do_not_recommend/supress_suggestions_in_help.rs b/tests/ui/diagnostic_namespace/do_not_recommend/supress_suggestions_in_help.rs index ef6f255c3518..2c7c15161230 100644 --- a/tests/ui/diagnostic_namespace/do_not_recommend/supress_suggestions_in_help.rs +++ b/tests/ui/diagnostic_namespace/do_not_recommend/supress_suggestions_in_help.rs @@ -2,8 +2,6 @@ //@ ignore-compare-mode-next-solver (explicit revisions) //@[next] compile-flags: -Znext-solver -#![feature(do_not_recommend)] - trait Foo {} #[diagnostic::do_not_recommend] diff --git a/tests/ui/diagnostic_namespace/do_not_recommend/type_mismatch.current.stderr b/tests/ui/diagnostic_namespace/do_not_recommend/type_mismatch.current.stderr index bcede8a255f2..b53febbb71ab 100644 --- a/tests/ui/diagnostic_namespace/do_not_recommend/type_mismatch.current.stderr +++ b/tests/ui/diagnostic_namespace/do_not_recommend/type_mismatch.current.stderr @@ -1,11 +1,11 @@ error[E0277]: Very important message! - --> $DIR/type_mismatch.rs:25:14 + --> $DIR/type_mismatch.rs:23:14 | LL | verify::(); | ^^ the trait `TheImportantOne` is not implemented for `u8` | note: required by a bound in `verify` - --> $DIR/type_mismatch.rs:22:14 + --> $DIR/type_mismatch.rs:20:14 | LL | fn verify() {} | ^^^^^^^^^^^^^^^ required by this bound in `verify` diff --git a/tests/ui/diagnostic_namespace/do_not_recommend/type_mismatch.next.stderr b/tests/ui/diagnostic_namespace/do_not_recommend/type_mismatch.next.stderr index bcede8a255f2..b53febbb71ab 100644 --- a/tests/ui/diagnostic_namespace/do_not_recommend/type_mismatch.next.stderr +++ b/tests/ui/diagnostic_namespace/do_not_recommend/type_mismatch.next.stderr @@ -1,11 +1,11 @@ error[E0277]: Very important message! - --> $DIR/type_mismatch.rs:25:14 + --> $DIR/type_mismatch.rs:23:14 | LL | verify::(); | ^^ the trait `TheImportantOne` is not implemented for `u8` | note: required by a bound in `verify` - --> $DIR/type_mismatch.rs:22:14 + --> $DIR/type_mismatch.rs:20:14 | LL | fn verify() {} | ^^^^^^^^^^^^^^^ required by this bound in `verify` diff --git a/tests/ui/diagnostic_namespace/do_not_recommend/type_mismatch.rs b/tests/ui/diagnostic_namespace/do_not_recommend/type_mismatch.rs index d6721ccc848f..7f30fdb06c75 100644 --- a/tests/ui/diagnostic_namespace/do_not_recommend/type_mismatch.rs +++ b/tests/ui/diagnostic_namespace/do_not_recommend/type_mismatch.rs @@ -2,8 +2,6 @@ //@ ignore-compare-mode-next-solver (explicit revisions) //@[next] compile-flags: -Znext-solver -#![feature(do_not_recommend)] - #[diagnostic::on_unimplemented(message = "Very important message!")] trait TheImportantOne {} diff --git a/tests/ui/diagnostic_namespace/do_not_recommend/unstable-feature.current.stderr b/tests/ui/diagnostic_namespace/do_not_recommend/unstable-feature.current.stderr deleted file mode 100644 index fdea9eacae14..000000000000 --- a/tests/ui/diagnostic_namespace/do_not_recommend/unstable-feature.current.stderr +++ /dev/null @@ -1,14 +0,0 @@ -error: unknown diagnostic attribute - --> $DIR/unstable-feature.rs:7:15 - | -LL | #[diagnostic::do_not_recommend] - | ^^^^^^^^^^^^^^^^ - | -note: the lint level is defined here - --> $DIR/unstable-feature.rs:4:9 - | -LL | #![deny(unknown_or_malformed_diagnostic_attributes)] - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ - -error: aborting due to 1 previous error - diff --git a/tests/ui/diagnostic_namespace/do_not_recommend/unstable-feature.next.stderr b/tests/ui/diagnostic_namespace/do_not_recommend/unstable-feature.next.stderr deleted file mode 100644 index fdea9eacae14..000000000000 --- a/tests/ui/diagnostic_namespace/do_not_recommend/unstable-feature.next.stderr +++ /dev/null @@ -1,14 +0,0 @@ -error: unknown diagnostic attribute - --> $DIR/unstable-feature.rs:7:15 - | -LL | #[diagnostic::do_not_recommend] - | ^^^^^^^^^^^^^^^^ - | -note: the lint level is defined here - --> $DIR/unstable-feature.rs:4:9 - | -LL | #![deny(unknown_or_malformed_diagnostic_attributes)] - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ - -error: aborting due to 1 previous error - diff --git a/tests/ui/diagnostic_namespace/do_not_recommend/unstable-feature.rs b/tests/ui/diagnostic_namespace/do_not_recommend/unstable-feature.rs deleted file mode 100644 index 7a67f67b67f2..000000000000 --- a/tests/ui/diagnostic_namespace/do_not_recommend/unstable-feature.rs +++ /dev/null @@ -1,11 +0,0 @@ -//@ revisions: current next -//@ ignore-compare-mode-next-solver (explicit revisions) -//@[next] compile-flags: -Znext-solver -#![deny(unknown_or_malformed_diagnostic_attributes)] -trait Foo {} - -#[diagnostic::do_not_recommend] -//~^ ERROR unknown diagnostic attribute [unknown_or_malformed_diagnostic_attributes] -impl Foo for i32 {} - -fn main() {} diff --git a/tests/ui/diagnostic_namespace/do_not_recommend/with_lifetime.current.stderr b/tests/ui/diagnostic_namespace/do_not_recommend/with_lifetime.current.stderr index c2874cf45945..a8429ff60f83 100644 --- a/tests/ui/diagnostic_namespace/do_not_recommend/with_lifetime.current.stderr +++ b/tests/ui/diagnostic_namespace/do_not_recommend/with_lifetime.current.stderr @@ -1,5 +1,5 @@ error: lifetime may not live long enough - --> $DIR/with_lifetime.rs:19:5 + --> $DIR/with_lifetime.rs:17:5 | LL | fn foo<'a>(a: &'a ()) { | -- lifetime `'a` defined here diff --git a/tests/ui/diagnostic_namespace/do_not_recommend/with_lifetime.next.stderr b/tests/ui/diagnostic_namespace/do_not_recommend/with_lifetime.next.stderr index c2874cf45945..a8429ff60f83 100644 --- a/tests/ui/diagnostic_namespace/do_not_recommend/with_lifetime.next.stderr +++ b/tests/ui/diagnostic_namespace/do_not_recommend/with_lifetime.next.stderr @@ -1,5 +1,5 @@ error: lifetime may not live long enough - --> $DIR/with_lifetime.rs:19:5 + --> $DIR/with_lifetime.rs:17:5 | LL | fn foo<'a>(a: &'a ()) { | -- lifetime `'a` defined here diff --git a/tests/ui/diagnostic_namespace/do_not_recommend/with_lifetime.rs b/tests/ui/diagnostic_namespace/do_not_recommend/with_lifetime.rs index 9aaf7f33ecdc..6a67d83d5fe4 100644 --- a/tests/ui/diagnostic_namespace/do_not_recommend/with_lifetime.rs +++ b/tests/ui/diagnostic_namespace/do_not_recommend/with_lifetime.rs @@ -2,8 +2,6 @@ //@ ignore-compare-mode-next-solver (explicit revisions) //@[next] compile-flags: -Znext-solver -#![feature(do_not_recommend)] - trait Root {} trait DontRecommend {} From ad29947f02520878d6e60e6b26b3a55fae3b7982 Mon Sep 17 00:00:00 2001 From: Georg Semmler Date: Fri, 25 Oct 2024 08:54:05 +0200 Subject: [PATCH 38/92] Also warn against `#[diagnostic::do_not_recommend]` on plain impls --- compiler/rustc_passes/src/check_attr.rs | 11 +++++++++-- .../incorrect-locations.current.stderr | 8 +++++++- .../do_not_recommend/incorrect-locations.next.stderr | 8 +++++++- .../do_not_recommend/incorrect-locations.rs | 4 ++++ 4 files changed, 27 insertions(+), 4 deletions(-) diff --git a/compiler/rustc_passes/src/check_attr.rs b/compiler/rustc_passes/src/check_attr.rs index 9879dfa9720e..2310dd9dc72d 100644 --- a/compiler/rustc_passes/src/check_attr.rs +++ b/compiler/rustc_passes/src/check_attr.rs @@ -115,7 +115,7 @@ impl<'tcx> CheckAttrVisitor<'tcx> { for attr in attrs { match attr.path().as_slice() { [sym::diagnostic, sym::do_not_recommend, ..] => { - self.check_do_not_recommend(attr.span, hir_id, target, attr) + self.check_do_not_recommend(attr.span, hir_id, target, attr, item) } [sym::diagnostic, sym::on_unimplemented, ..] => { self.check_diagnostic_on_unimplemented(attr.span, hir_id, target) @@ -354,8 +354,15 @@ impl<'tcx> CheckAttrVisitor<'tcx> { hir_id: HirId, target: Target, attr: &Attribute, + item: Option>, ) { - if !matches!(target, Target::Impl) { + if !matches!(target, Target::Impl) + || matches!( + item, + Some(ItemLike::Item(hir::Item { kind: hir::ItemKind::Impl(_impl),.. })) + if _impl.of_trait.is_none() + ) + { self.tcx.emit_node_span_lint( UNKNOWN_OR_MALFORMED_DIAGNOSTIC_ATTRIBUTES, hir_id, diff --git a/tests/ui/diagnostic_namespace/do_not_recommend/incorrect-locations.current.stderr b/tests/ui/diagnostic_namespace/do_not_recommend/incorrect-locations.current.stderr index 0b0dac32b39f..ee6ebabadd97 100644 --- a/tests/ui/diagnostic_namespace/do_not_recommend/incorrect-locations.current.stderr +++ b/tests/ui/diagnostic_namespace/do_not_recommend/incorrect-locations.current.stderr @@ -48,5 +48,11 @@ warning: `#[diagnostic::do_not_recommend]` can only be placed on trait implement LL | #[diagnostic::do_not_recommend] | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ -warning: 8 warnings emitted +warning: `#[diagnostic::do_not_recommend]` can only be placed on trait implementations + --> $DIR/incorrect-locations.rs:38:1 + | +LL | #[diagnostic::do_not_recommend] + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +warning: 9 warnings emitted diff --git a/tests/ui/diagnostic_namespace/do_not_recommend/incorrect-locations.next.stderr b/tests/ui/diagnostic_namespace/do_not_recommend/incorrect-locations.next.stderr index 0b0dac32b39f..ee6ebabadd97 100644 --- a/tests/ui/diagnostic_namespace/do_not_recommend/incorrect-locations.next.stderr +++ b/tests/ui/diagnostic_namespace/do_not_recommend/incorrect-locations.next.stderr @@ -48,5 +48,11 @@ warning: `#[diagnostic::do_not_recommend]` can only be placed on trait implement LL | #[diagnostic::do_not_recommend] | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ -warning: 8 warnings emitted +warning: `#[diagnostic::do_not_recommend]` can only be placed on trait implementations + --> $DIR/incorrect-locations.rs:38:1 + | +LL | #[diagnostic::do_not_recommend] + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +warning: 9 warnings emitted diff --git a/tests/ui/diagnostic_namespace/do_not_recommend/incorrect-locations.rs b/tests/ui/diagnostic_namespace/do_not_recommend/incorrect-locations.rs index 014be580f61f..1cf436aa2af3 100644 --- a/tests/ui/diagnostic_namespace/do_not_recommend/incorrect-locations.rs +++ b/tests/ui/diagnostic_namespace/do_not_recommend/incorrect-locations.rs @@ -19,6 +19,10 @@ type Type = (); //~^WARN `#[diagnostic::do_not_recommend]` can only be placed enum Enum {} +#[diagnostic::do_not_recommend] +//~^WARN `#[diagnostic::do_not_recommend]` can only be placed +impl Enum {} + #[diagnostic::do_not_recommend] //~^WARN `#[diagnostic::do_not_recommend]` can only be placed extern "C" {} From 20bff638bf45990b7d71cdc330b4f68bd4b4bc73 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jalil=20David=20Salam=C3=A9=20Messina?= Date: Wed, 18 Dec 2024 09:37:45 +0100 Subject: [PATCH 39/92] fix(LazyCell): documentation of get[_mut] was wrong - `LazyCell::get`: said it was returning a **mutable** reference. - `LazyCell::get_mut`: said it was returning a reference (the mutable was missing). --- library/core/src/cell/lazy.rs | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/library/core/src/cell/lazy.rs b/library/core/src/cell/lazy.rs index 5ac33516684d..84cbbc71f40a 100644 --- a/library/core/src/cell/lazy.rs +++ b/library/core/src/cell/lazy.rs @@ -219,7 +219,7 @@ impl T> LazyCell { } impl LazyCell { - /// Returns a reference to the value if initialized, or `None` if not. + /// Returns a mutable reference to the value if initialized, or `None` if not. /// /// # Examples /// @@ -245,7 +245,7 @@ impl LazyCell { } } - /// Returns a mutable reference to the value if initialized, or `None` if not. + /// Returns a reference to the value if initialized, or `None` if not. /// /// # Examples /// From 64abe8be33326643bcc32e25e4c6aaf3555e145b Mon Sep 17 00:00:00 2001 From: Nicholas Nethercote Date: Fri, 13 Dec 2024 20:54:36 +1100 Subject: [PATCH 40/92] Simplify `AllKeywords`. It's a verbose reinvention of a range type, and can be cut down a lot. --- .../rustc_parse/src/parser/diagnostics.rs | 4 +- compiler/rustc_span/src/symbol.rs | 52 ++++++------------- 2 files changed, 17 insertions(+), 39 deletions(-) diff --git a/compiler/rustc_parse/src/parser/diagnostics.rs b/compiler/rustc_parse/src/parser/diagnostics.rs index d1a725e729aa..9b335df6c0f3 100644 --- a/compiler/rustc_parse/src/parser/diagnostics.rs +++ b/compiler/rustc_parse/src/parser/diagnostics.rs @@ -22,7 +22,7 @@ use rustc_errors::{ use rustc_session::errors::ExprParenthesesNeeded; use rustc_span::edit_distance::find_best_match_for_name; use rustc_span::source_map::Spanned; -use rustc_span::symbol::AllKeywords; +use rustc_span::symbol::used_keywords; use rustc_span::{BytePos, DUMMY_SP, Ident, Span, SpanSnippetError, Symbol, kw, sym}; use thin_vec::{ThinVec, thin_vec}; use tracing::{debug, trace}; @@ -811,7 +811,7 @@ impl<'a> Parser<'a> { // so that it gets generated only when the diagnostic needs it. // Also, it is unlikely that this list is generated multiple times because the // parser halts after execution hits this path. - let all_keywords = AllKeywords::new().collect_used(|| prev_ident.span.edition()); + let all_keywords = used_keywords(|| prev_ident.span.edition()); // Otherwise, check the previous token with all the keywords as possible candidates. // This handles code like `Struct Human;` and `While a < b {}`. diff --git a/compiler/rustc_span/src/symbol.rs b/compiler/rustc_span/src/symbol.rs index 7d99ca5a31e2..64ee9007df08 100644 --- a/compiler/rustc_span/src/symbol.rs +++ b/compiler/rustc_span/src/symbol.rs @@ -20,8 +20,8 @@ mod tests; // The proc macro code for this is in `compiler/rustc_macros/src/symbols.rs`. symbols! { - // If you modify this list, adjust `is_special`, `is_used_keyword`/`is_unused_keyword` - // and `AllKeywords`. + // If you modify this list, adjust any relevant `Symbol::{is,can_be}_*` functions and + // `used_keywords`. // But this should rarely be necessary if the keywords are kept in alphabetic order. Keywords { // Special reserved identifiers used internally for elided lifetimes, @@ -2683,41 +2683,19 @@ impl Ident { } } -/// An iterator over all the keywords in Rust. -#[derive(Copy, Clone)] -pub struct AllKeywords { - curr_idx: u32, - end_idx: u32, -} - -impl AllKeywords { - /// Initialize a new iterator over all the keywords. - /// - /// *Note:* Please update this if a new keyword is added beyond the current - /// range. - pub fn new() -> Self { - AllKeywords { curr_idx: kw::Empty.as_u32(), end_idx: kw::Yeet.as_u32() } - } - - /// Collect all the keywords in a given edition into a vector. - pub fn collect_used(&self, edition: impl Copy + FnOnce() -> Edition) -> Vec { - self.filter(|&keyword| { - keyword.is_used_keyword_always() || keyword.is_used_keyword_conditional(edition) +/// Collect all the keywords in a given edition into a vector. +/// +/// *Note:* Please update this if a new keyword is added beyond the current +/// range. +pub fn used_keywords(edition: impl Copy + FnOnce() -> Edition) -> Vec { + (kw::Empty.as_u32()..kw::Yeet.as_u32()) + .filter_map(|kw| { + let kw = Symbol::new(kw); + if kw.is_used_keyword_always() || kw.is_used_keyword_conditional(edition) { + Some(kw) + } else { + None + } }) .collect() - } -} - -impl Iterator for AllKeywords { - type Item = Symbol; - - fn next(&mut self) -> Option { - if self.curr_idx <= self.end_idx { - let keyword = Symbol::new(self.curr_idx); - self.curr_idx += 1; - Some(keyword) - } else { - None - } - } } From 1564318482e80152d43150fdfc3ade2c868f2677 Mon Sep 17 00:00:00 2001 From: Nicholas Nethercote Date: Fri, 13 Dec 2024 21:07:58 +1100 Subject: [PATCH 41/92] Only have one source of truth for keywords. `rustc_symbol` is the source of truth for keywords. rustdoc has its own implicit definition of keywords, via the `is_doc_keyword`. It (presumably) intends to include all keywords, but it omits `yeet`. rustfmt has its own explicit list of Rust keywords. It also (presumably) intends to include all keywords, but it omits `await`, `builtin`, `gen`, `macro_rules`, `raw`, `reuse`, `safe`, and `yeet`. Also, it does linear searches through this list, which is inefficient. This commit fixes all of the above problems by introducing a new predicate `is_any_keyword` in rustc and using it in rustdoc and rustfmt. It documents that it's not the right predicate in most cases. --- compiler/rustc_ast/src/token.rs | 8 +- .../rustc_parse/src/parser/diagnostics.rs | 4 +- compiler/rustc_span/src/symbol.rs | 10 +++ src/tools/rustfmt/src/parse/macros/mod.rs | 87 +++---------------- 4 files changed, 31 insertions(+), 78 deletions(-) diff --git a/compiler/rustc_ast/src/token.rs b/compiler/rustc_ast/src/token.rs index ab82f18133e7..f639e785bc4f 100644 --- a/compiler/rustc_ast/src/token.rs +++ b/compiler/rustc_ast/src/token.rs @@ -903,7 +903,8 @@ impl Token { self.is_non_raw_ident_where(|id| id.name == kw) } - /// Returns `true` if the token is a given keyword, `kw` or if `case` is `Insensitive` and this token is an identifier equal to `kw` ignoring the case. + /// Returns `true` if the token is a given keyword, `kw` or if `case` is `Insensitive` and this + /// token is an identifier equal to `kw` ignoring the case. pub fn is_keyword_case(&self, kw: Symbol, case: Case) -> bool { self.is_keyword(kw) || (case == Case::Insensitive @@ -916,6 +917,11 @@ impl Token { self.is_non_raw_ident_where(Ident::is_path_segment_keyword) } + /// Don't use this unless you're doing something very loose and heuristic-y. + pub fn is_any_keyword(&self) -> bool { + self.is_non_raw_ident_where(Ident::is_any_keyword) + } + /// Returns true for reserved identifiers used internally for elided lifetimes, /// unnamed method parameters, crate root module, error recovery etc. pub fn is_special_ident(&self) -> bool { diff --git a/compiler/rustc_parse/src/parser/diagnostics.rs b/compiler/rustc_parse/src/parser/diagnostics.rs index 9b335df6c0f3..8417701ac0cd 100644 --- a/compiler/rustc_parse/src/parser/diagnostics.rs +++ b/compiler/rustc_parse/src/parser/diagnostics.rs @@ -815,8 +815,8 @@ impl<'a> Parser<'a> { // Otherwise, check the previous token with all the keywords as possible candidates. // This handles code like `Struct Human;` and `While a < b {}`. - // We check the previous token only when the current token is an identifier to avoid false - // positives like suggesting keyword `for` for `extern crate foo {}`. + // We check the previous token only when the current token is an identifier to avoid + // false positives like suggesting keyword `for` for `extern crate foo {}`. if let Some(misspelled_kw) = find_similar_kw(prev_ident, &all_keywords) { err.subdiagnostic(misspelled_kw); // We don't want other suggestions to be added as they are most likely meaningless diff --git a/compiler/rustc_span/src/symbol.rs b/compiler/rustc_span/src/symbol.rs index 64ee9007df08..d2391f30168f 100644 --- a/compiler/rustc_span/src/symbol.rs +++ b/compiler/rustc_span/src/symbol.rs @@ -2589,6 +2589,11 @@ pub mod sym { } impl Symbol { + /// Don't use this unless you're doing something very loose and heuristic-y. + pub fn is_any_keyword(self) -> bool { + self >= kw::As && self <= kw::Yeet + } + fn is_special(self) -> bool { self <= kw::Underscore } @@ -2645,6 +2650,11 @@ impl Symbol { } impl Ident { + /// Don't use this unless you're doing something very loose and heuristic-y. + pub fn is_any_keyword(self) -> bool { + self.name.is_any_keyword() + } + /// Returns `true` for reserved identifiers used internally for elided lifetimes, /// unnamed method parameters, crate root module, error recovery etc. pub fn is_special(self) -> bool { diff --git a/src/tools/rustfmt/src/parse/macros/mod.rs b/src/tools/rustfmt/src/parse/macros/mod.rs index 7271e73db8dd..680a35f7e03a 100644 --- a/src/tools/rustfmt/src/parse/macros/mod.rs +++ b/src/tools/rustfmt/src/parse/macros/mod.rs @@ -4,8 +4,7 @@ use rustc_ast::{ast, ptr}; use rustc_parse::MACRO_ARGUMENTS; use rustc_parse::parser::{ForceCollect, Parser, Recovery}; use rustc_session::parse::ParseSess; -use rustc_span::Symbol; -use rustc_span::symbol::{self, kw}; +use rustc_span::symbol; use crate::macros::MacroArg; use crate::rewrite::RewriteContext; @@ -82,18 +81,18 @@ pub(crate) struct ParsedMacroArgs { } fn check_keyword<'a, 'b: 'a>(parser: &'a mut Parser<'b>) -> Option { - for &keyword in RUST_KW.iter() { - if parser.token.is_keyword(keyword) - && parser.look_ahead(1, |t| *t == TokenKind::Eof || *t == TokenKind::Comma) - { - parser.bump(); - return Some(MacroArg::Keyword( - symbol::Ident::with_dummy_span(keyword), - parser.prev_token.span, - )); - } + if parser.token.is_any_keyword() + && parser.look_ahead(1, |t| *t == TokenKind::Eof || *t == TokenKind::Comma) + { + let keyword = parser.token.ident().unwrap().0.name; + parser.bump(); + Some(MacroArg::Keyword( + symbol::Ident::with_dummy_span(keyword), + parser.prev_token.span, + )) + } else { + None } - None } pub(crate) fn parse_macro_args( @@ -169,65 +168,3 @@ pub(crate) fn parse_expr( let mut parser = build_parser(context, tokens); parser.parse_expr().ok() } - -const RUST_KW: [Symbol; 59] = [ - kw::PathRoot, - kw::DollarCrate, - kw::Underscore, - kw::As, - kw::Box, - kw::Break, - kw::Const, - kw::Continue, - kw::Crate, - kw::Else, - kw::Enum, - kw::Extern, - kw::False, - kw::Fn, - kw::For, - kw::If, - kw::Impl, - kw::In, - kw::Let, - kw::Loop, - kw::Match, - kw::Mod, - kw::Move, - kw::Mut, - kw::Pub, - kw::Ref, - kw::Return, - kw::SelfLower, - kw::SelfUpper, - kw::Static, - kw::Struct, - kw::Super, - kw::Trait, - kw::True, - kw::Type, - kw::Unsafe, - kw::Use, - kw::Where, - kw::While, - kw::Abstract, - kw::Become, - kw::Do, - kw::Final, - kw::Macro, - kw::Override, - kw::Priv, - kw::Typeof, - kw::Unsized, - kw::Virtual, - kw::Yield, - kw::Dyn, - kw::Async, - kw::Try, - kw::UnderscoreLifetime, - kw::StaticLifetime, - kw::Auto, - kw::Catch, - kw::Default, - kw::Union, -]; From ed5b91abc8591fbbc4337cc14b484eb3ed5a2955 Mon Sep 17 00:00:00 2001 From: Nicholas Nethercote Date: Fri, 13 Dec 2024 13:43:47 +1100 Subject: [PATCH 42/92] Move `gen` in the keyword list. `gen` is an edition-specific keyword used in unstable Rust, and so belongs with `try` (as `is_unused_keyword_conditional` indicates). Also, the cases in `is_unused_keyword_conditional` should be in alphabetical order, to match the keyword list. These changes don't affect the behaviour of any of the `Symbol::is_*` functions. --- compiler/rustc_span/src/symbol.rs | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/compiler/rustc_span/src/symbol.rs b/compiler/rustc_span/src/symbol.rs index d2391f30168f..11441854a76c 100644 --- a/compiler/rustc_span/src/symbol.rs +++ b/compiler/rustc_span/src/symbol.rs @@ -88,6 +88,7 @@ symbols! { Dyn: "dyn", // >= 2018 Edition only // Edition-specific keywords that are used in unstable Rust or reserved for future use. + Gen: "gen", // >= 2024 Edition only Try: "try", // >= 2018 Edition only // Special lifetime names @@ -99,7 +100,6 @@ symbols! { Builtin: "builtin", Catch: "catch", Default: "default", - Gen: "gen", MacroRules: "macro_rules", Raw: "raw", Reuse: "reuse", @@ -2611,8 +2611,8 @@ impl Symbol { } fn is_unused_keyword_conditional(self, edition: impl Copy + FnOnce() -> Edition) -> bool { - self == kw::Try && edition().at_least_rust_2018() - || self == kw::Gen && edition().at_least_rust_2024() + self == kw::Gen && edition().at_least_rust_2024() + || self == kw::Try && edition().at_least_rust_2018() } pub fn is_reserved(self, edition: impl Copy + FnOnce() -> Edition) -> bool { From 6de550cc68d5eb7dc5013987c87859e2f589ac12 Mon Sep 17 00:00:00 2001 From: Nicholas Nethercote Date: Tue, 17 Dec 2024 11:46:23 +1100 Subject: [PATCH 43/92] Improve comments on `Keywords`. In particular, clarify which predicates apply to which keywords. --- compiler/rustc_span/src/symbol.rs | 19 +++++++++++++++++-- 1 file changed, 17 insertions(+), 2 deletions(-) diff --git a/compiler/rustc_span/src/symbol.rs b/compiler/rustc_span/src/symbol.rs index 11441854a76c..a7ff0576f92d 100644 --- a/compiler/rustc_span/src/symbol.rs +++ b/compiler/rustc_span/src/symbol.rs @@ -20,18 +20,26 @@ mod tests; // The proc macro code for this is in `compiler/rustc_macros/src/symbols.rs`. symbols! { - // If you modify this list, adjust any relevant `Symbol::{is,can_be}_*` functions and + // This list includes things that are definitely keywords (e.g. `if`), + // a few things that are definitely not keywords (e.g. the empty symbol, + // `{{root}}`) and things where there is disagreement between people and/or + // documents (such as the Rust Reference) about whether it is a keyword + // (e.g. `_`). + // + // If you modify this list, adjust any relevant `Symbol::{is,can_be}_*` predicates and // `used_keywords`. // But this should rarely be necessary if the keywords are kept in alphabetic order. Keywords { // Special reserved identifiers used internally for elided lifetimes, // unnamed method parameters, crate root module, error recovery etc. + // Matching predicates: `is_any_keyword`, `is_special`/`is_reserved` Empty: "", PathRoot: "{{root}}", DollarCrate: "$crate", Underscore: "_", // Keywords that are used in stable Rust. + // Matching predicates: `is_any_keyword`, `is_used_keyword_always`/`is_reserved` As: "as", Break: "break", Const: "const", @@ -69,6 +77,7 @@ symbols! { While: "while", // Keywords that are used in unstable Rust or reserved for future use. + // Matching predicates: `is_any_keyword`, `is_unused_keyword_always`/`is_reserved` Abstract: "abstract", Become: "become", Box: "box", @@ -83,19 +92,25 @@ symbols! { Yield: "yield", // Edition-specific keywords that are used in stable Rust. + // Matching predicates: `is_any_keyword`, `is_used_keyword_conditional`/`is_reserved` (if + // the edition suffices) Async: "async", // >= 2018 Edition only Await: "await", // >= 2018 Edition only Dyn: "dyn", // >= 2018 Edition only // Edition-specific keywords that are used in unstable Rust or reserved for future use. + // Matching predicates: `is_any_keyword`, `is_unused_keyword_conditional`/`is_reserved` (if + // the edition suffices) Gen: "gen", // >= 2024 Edition only Try: "try", // >= 2018 Edition only - // Special lifetime names + // "Lifetime keywords": regular keywords with a leading `'`. + // Matching predicates: `is_any_keyword` UnderscoreLifetime: "'_", StaticLifetime: "'static", // Weak keywords, have special meaning only in specific contexts. + // Matching predicates: `is_any_keyword` Auto: "auto", Builtin: "builtin", Catch: "catch", From 21de42bf8ddd0f39c766c7705990152302ae1f3b Mon Sep 17 00:00:00 2001 From: Ralf Jung Date: Sun, 1 Dec 2024 13:12:43 +0100 Subject: [PATCH 44/92] Variants::Single: do not use invalid VariantIdx for uninhabited enums --- compiler/rustc_abi/src/layout.rs | 14 +- compiler/rustc_abi/src/lib.rs | 8 +- .../src/discriminant.rs | 5 +- compiler/rustc_codegen_gcc/src/type_of.rs | 6 +- .../src/debuginfo/metadata/enums/cpp_like.rs | 4 +- compiler/rustc_codegen_llvm/src/type_of.rs | 8 +- compiler/rustc_codegen_ssa/src/mir/place.rs | 3 +- .../src/interpret/discriminant.rs | 23 ++-- .../src/interpret/validity.rs | 4 +- .../rustc_middle/src/mir/interpret/error.rs | 2 +- compiler/rustc_middle/src/ty/layout.rs | 13 +- .../rustc_mir_transform/src/jump_threading.rs | 31 +---- .../src/unreachable_enum_branching.rs | 6 +- .../rustc_smir/src/rustc_smir/convert/abi.rs | 6 +- compiler/rustc_transmute/src/layout/tree.rs | 10 +- compiler/rustc_ty_utils/src/layout.rs | 14 +- .../rustc_ty_utils/src/layout/invariant.rs | 124 ++++++++++-------- compiler/stable_mir/src/abi.rs | 1 + .../rust-analyzer/crates/hir-ty/src/layout.rs | 8 +- .../crates/hir-ty/src/mir/eval.rs | 3 +- .../rust-analyzer/crates/hir-ty/src/utils.rs | 2 +- .../set_no_discriminant.f.JumpThreading.diff | 3 +- ...no_discriminant.generic.JumpThreading.diff | 3 +- tests/mir-opt/set_no_discriminant.rs | 21 +-- tests/ui/abi/c-zst.aarch64-darwin.stderr | 8 +- tests/ui/abi/c-zst.powerpc-linux.stderr | 8 +- tests/ui/abi/c-zst.s390x-linux.stderr | 8 +- tests/ui/abi/c-zst.sparc64-linux.stderr | 8 +- tests/ui/abi/c-zst.x86_64-linux.stderr | 8 +- .../ui/abi/c-zst.x86_64-pc-windows-gnu.stderr | 8 +- tests/ui/abi/debug.stderr | 96 ++++++++++---- tests/ui/abi/sysv64-zst.stderr | 8 +- tests/ui/abi/win64-zst.x86_64-linux.stderr | 8 +- .../abi/win64-zst.x86_64-windows-gnu.stderr | 8 +- .../abi/win64-zst.x86_64-windows-msvc.stderr | 8 +- tests/ui/layout/debug.stderr | 64 ++++++--- tests/ui/layout/hexagon-enum.stderr | 20 ++- ...-scalarpair-payload-might-be-uninit.stderr | 48 +++++-- .../issue-96185-overaligned-enum.stderr | 16 ++- tests/ui/layout/thumb-enum.stderr | 20 ++- .../layout/zero-sized-array-enum-niche.stderr | 36 +++-- ...-variants.aarch64-unknown-linux-gnu.stderr | 20 ++- ...-c-dead-variants.armebv7r-none-eabi.stderr | 20 ++- ...-dead-variants.i686-pc-windows-msvc.stderr | 20 ++- ...d-variants.x86_64-unknown-linux-gnu.stderr | 20 ++- tests/ui/repr/repr-c-int-dead-variants.stderr | 20 ++- .../type/pattern_types/range_patterns.stderr | 28 +++- 47 files changed, 549 insertions(+), 281 deletions(-) diff --git a/compiler/rustc_abi/src/layout.rs b/compiler/rustc_abi/src/layout.rs index e6d66f608dae..f2b50ae408e9 100644 --- a/compiler/rustc_abi/src/layout.rs +++ b/compiler/rustc_abi/src/layout.rs @@ -120,7 +120,7 @@ impl LayoutCalculator { .max_by_key(|niche| niche.available(dl)); LayoutData { - variants: Variants::Single { index: VariantIdx::new(0) }, + variants: Variants::Single { index: Some(VariantIdx::new(0)) }, fields: FieldsShape::Arbitrary { offsets: [Size::ZERO, b_offset].into(), memory_index: [0, 1].into(), @@ -214,7 +214,7 @@ impl LayoutCalculator { ) -> LayoutData { let dl = self.cx.data_layout(); LayoutData { - variants: Variants::Single { index: VariantIdx::new(0) }, + variants: Variants::Single { index: None }, fields: FieldsShape::Primitive, backend_repr: BackendRepr::Uninhabited, largest_niche: None, @@ -385,7 +385,7 @@ impl LayoutCalculator { }; Ok(LayoutData { - variants: Variants::Single { index: only_variant_idx }, + variants: Variants::Single { index: Some(only_variant_idx) }, fields: FieldsShape::Union(union_field_count), backend_repr: abi, largest_niche: None, @@ -424,7 +424,7 @@ impl LayoutCalculator { }; let mut st = self.univariant(&variants[v], repr, kind)?; - st.variants = Variants::Single { index: v }; + st.variants = Variants::Single { index: Some(v) }; if is_unsafe_cell { let hide_niches = |scalar: &mut _| match scalar { @@ -543,7 +543,7 @@ impl LayoutCalculator { .iter_enumerated() .map(|(j, v)| { let mut st = self.univariant(v, repr, StructKind::AlwaysSized).ok()?; - st.variants = Variants::Single { index: j }; + st.variants = Variants::Single { index: Some(j) }; align = align.max(st.align); max_repr_align = max_repr_align.max(st.max_repr_align); @@ -736,7 +736,7 @@ impl LayoutCalculator { repr, StructKind::Prefixed(min_ity.size(), prefix_align), )?; - st.variants = Variants::Single { index: i }; + st.variants = Variants::Single { index: Some(i) }; // Find the first field we can't move later // to make room for a larger discriminant. for field_idx in st.fields.index_by_increasing_offset() { @@ -1344,7 +1344,7 @@ impl LayoutCalculator { }; Ok(LayoutData { - variants: Variants::Single { index: VariantIdx::new(0) }, + variants: Variants::Single { index: Some(VariantIdx::new(0)) }, fields: FieldsShape::Arbitrary { offsets, memory_index }, backend_repr: abi, largest_niche, diff --git a/compiler/rustc_abi/src/lib.rs b/compiler/rustc_abi/src/lib.rs index 15a27c0b6ee0..242e2cadd18a 100644 --- a/compiler/rustc_abi/src/lib.rs +++ b/compiler/rustc_abi/src/lib.rs @@ -1506,9 +1506,9 @@ impl BackendRepr { pub enum Variants { /// Single enum variants, structs/tuples, unions, and all non-ADTs. Single { - /// Always 0 for non-enums/generators. - /// For enums without a variant, this is an invalid index! - index: VariantIdx, + /// Always `Some(0)` for types without variants (i.e., everything except for `!`, enums, and + /// generators). `None` indicates an uninhabited type; this is used for zero-variant enums. + index: Option, }, /// Enum-likes with more than one variant: each variant comes with @@ -1706,7 +1706,7 @@ impl LayoutData { let size = scalar.size(cx); let align = scalar.align(cx); LayoutData { - variants: Variants::Single { index: VariantIdx::new(0) }, + variants: Variants::Single { index: Some(VariantIdx::new(0)) }, fields: FieldsShape::Primitive, backend_repr: BackendRepr::Scalar(scalar), largest_niche, diff --git a/compiler/rustc_codegen_cranelift/src/discriminant.rs b/compiler/rustc_codegen_cranelift/src/discriminant.rs index 45794a426658..055063c876fa 100644 --- a/compiler/rustc_codegen_cranelift/src/discriminant.rs +++ b/compiler/rustc_codegen_cranelift/src/discriminant.rs @@ -19,7 +19,7 @@ pub(crate) fn codegen_set_discriminant<'tcx>( } match layout.variants { Variants::Single { index } => { - assert_eq!(index, variant_index); + assert_eq!(index.unwrap(), variant_index); } Variants::Multiple { tag: _, @@ -86,9 +86,10 @@ pub(crate) fn codegen_get_discriminant<'tcx>( let (tag_scalar, tag_field, tag_encoding) = match &layout.variants { Variants::Single { index } => { + let index = index.unwrap(); let discr_val = layout .ty - .discriminant_for_variant(fx.tcx, *index) + .discriminant_for_variant(fx.tcx, index) .map_or(u128::from(index.as_u32()), |discr| discr.val); let val = match dest_layout.ty.kind() { diff --git a/compiler/rustc_codegen_gcc/src/type_of.rs b/compiler/rustc_codegen_gcc/src/type_of.rs index 0efdf36da485..426d28f4ed78 100644 --- a/compiler/rustc_codegen_gcc/src/type_of.rs +++ b/compiler/rustc_codegen_gcc/src/type_of.rs @@ -99,14 +99,14 @@ fn uncached_gcc_type<'gcc, 'tcx>( if !cx.sess().fewer_names() => { let mut name = with_no_trimmed_paths!(layout.ty.to_string()); - if let (&ty::Adt(def, _), &Variants::Single { index }) = + if let (&ty::Adt(def, _), &Variants::Single { index: Some(index) }) = (layout.ty.kind(), &layout.variants) { if def.is_enum() && !def.variants().is_empty() { write!(&mut name, "::{}", def.variant(index).name).unwrap(); } } - if let (&ty::Coroutine(_, _), &Variants::Single { index }) = + if let (&ty::Coroutine(_, _), &Variants::Single { index: Some(index) }) = (layout.ty.kind(), &layout.variants) { write!(&mut name, "::{}", ty::CoroutineArgs::variant_name(index)).unwrap(); @@ -230,7 +230,7 @@ impl<'tcx> LayoutGccExt<'tcx> for TyAndLayout<'tcx> { // Check the cache. let variant_index = match self.variants { - Variants::Single { index } => Some(index), + Variants::Single { index } => index, _ => None, }; let cached_type = cx.types.borrow().get(&(self.ty, variant_index)).cloned(); diff --git a/compiler/rustc_codegen_llvm/src/debuginfo/metadata/enums/cpp_like.rs b/compiler/rustc_codegen_llvm/src/debuginfo/metadata/enums/cpp_like.rs index d374767f187d..8ec83fa7c92d 100644 --- a/compiler/rustc_codegen_llvm/src/debuginfo/metadata/enums/cpp_like.rs +++ b/compiler/rustc_codegen_llvm/src/debuginfo/metadata/enums/cpp_like.rs @@ -213,11 +213,11 @@ pub(super) fn build_enum_type_di_node<'ll, 'tcx>( |cx, enum_type_di_node| { match enum_type_and_layout.variants { Variants::Single { index: variant_index } => { - if enum_adt_def.variants().is_empty() { + let Some(variant_index) = variant_index else { // Uninhabited enums have Variants::Single. We don't generate // any members for them. return smallvec![]; - } + }; build_single_variant_union_fields( cx, diff --git a/compiler/rustc_codegen_llvm/src/type_of.rs b/compiler/rustc_codegen_llvm/src/type_of.rs index 2b05e24a7bab..833a687fe742 100644 --- a/compiler/rustc_codegen_llvm/src/type_of.rs +++ b/compiler/rustc_codegen_llvm/src/type_of.rs @@ -35,14 +35,14 @@ fn uncached_llvm_type<'a, 'tcx>( if !cx.sess().fewer_names() => { let mut name = with_no_visible_paths!(with_no_trimmed_paths!(layout.ty.to_string())); - if let (&ty::Adt(def, _), &Variants::Single { index }) = + if let (&ty::Adt(def, _), &Variants::Single { index: Some(index) }) = (layout.ty.kind(), &layout.variants) { - if def.is_enum() && !def.variants().is_empty() { + if def.is_enum() { write!(&mut name, "::{}", def.variant(index).name).unwrap(); } } - if let (&ty::Coroutine(_, _), &Variants::Single { index }) = + if let (&ty::Coroutine(_, _), &Variants::Single { index: Some(index) }) = (layout.ty.kind(), &layout.variants) { write!(&mut name, "::{}", ty::CoroutineArgs::variant_name(index)).unwrap(); @@ -216,7 +216,7 @@ impl<'tcx> LayoutLlvmExt<'tcx> for TyAndLayout<'tcx> { // Check the cache. let variant_index = match self.variants { - Variants::Single { index } => Some(index), + Variants::Single { index } => index, _ => None, }; if let Some(llty) = cx.type_lowering.borrow().get(&(self.ty, variant_index)) { diff --git a/compiler/rustc_codegen_ssa/src/mir/place.rs b/compiler/rustc_codegen_ssa/src/mir/place.rs index a9e80e27ed40..cef3d8255a0e 100644 --- a/compiler/rustc_codegen_ssa/src/mir/place.rs +++ b/compiler/rustc_codegen_ssa/src/mir/place.rs @@ -244,6 +244,7 @@ impl<'a, 'tcx, V: CodegenObject> PlaceRef<'tcx, V> { } let (tag_scalar, tag_encoding, tag_field) = match self.layout.variants { Variants::Single { index } => { + let index = index.unwrap(); // we already checked `is_uninhabited` let discr_val = self .layout .ty @@ -366,7 +367,7 @@ impl<'a, 'tcx, V: CodegenObject> PlaceRef<'tcx, V> { } match self.layout.variants { Variants::Single { index } => { - assert_eq!(index, variant_index); + assert_eq!(index.unwrap(), variant_index); } Variants::Multiple { tag_encoding: TagEncoding::Direct, tag_field, .. } => { let ptr = self.project_field(bx, tag_field); diff --git a/compiler/rustc_const_eval/src/interpret/discriminant.rs b/compiler/rustc_const_eval/src/interpret/discriminant.rs index 6faac1582ab8..6cfd1613229b 100644 --- a/compiler/rustc_const_eval/src/interpret/discriminant.rs +++ b/compiler/rustc_const_eval/src/interpret/discriminant.rs @@ -44,7 +44,7 @@ impl<'tcx, M: Machine<'tcx>> InterpCx<'tcx, M> { } } - /// Read discriminant, return the runtime value as well as the variant index. + /// Read discriminant, return the variant index. /// Can also legally be called on non-enums (e.g. through the discriminant_value intrinsic)! /// /// Will never return an uninhabited variant. @@ -66,21 +66,14 @@ impl<'tcx, M: Machine<'tcx>> InterpCx<'tcx, M> { // straight-forward (`TagEncoding::Direct`) or with a niche (`TagEncoding::Niche`). let (tag_scalar_layout, tag_encoding, tag_field) = match op.layout().variants { Variants::Single { index } => { - // Do some extra checks on enums. - if ty.is_enum() { - // Hilariously, `Single` is used even for 0-variant enums. - // (See https://github.com/rust-lang/rust/issues/89765). - if ty.ty_adt_def().unwrap().variants().is_empty() { - throw_ub!(UninhabitedEnumVariantRead(index)) - } + if op.layout().is_uninhabited() { // For consistency with `write_discriminant`, and to make sure that // `project_downcast` cannot fail due to strange layouts, we declare immediate UB - // for uninhabited variants. - if op.layout().for_variant(self, index).is_uninhabited() { - throw_ub!(UninhabitedEnumVariantRead(index)) - } + // for uninhabited enums. + throw_ub!(UninhabitedEnumVariantRead(None)); } - return interp_ok(index); + // Since the type is inhabited, there must be an index. + return interp_ok(index.unwrap()); } Variants::Multiple { tag, ref tag_encoding, tag_field, .. } => { (tag, tag_encoding, tag_field) @@ -199,11 +192,13 @@ impl<'tcx, M: Machine<'tcx>> InterpCx<'tcx, M> { // `uninhabited_enum_branching` MIR pass. It also ensures consistency with // `write_discriminant`. if op.layout().for_variant(self, index).is_uninhabited() { - throw_ub!(UninhabitedEnumVariantRead(index)) + throw_ub!(UninhabitedEnumVariantRead(Some(index))) } interp_ok(index) } + /// Read discriminant, return the user-visible discriminant. + /// Can also legally be called on non-enums (e.g. through the discriminant_value intrinsic)! pub fn discriminant_for_variant( &self, ty: Ty<'tcx>, diff --git a/compiler/rustc_const_eval/src/interpret/validity.rs b/compiler/rustc_const_eval/src/interpret/validity.rs index 8e18b243906f..832183b42dc4 100644 --- a/compiler/rustc_const_eval/src/interpret/validity.rs +++ b/compiler/rustc_const_eval/src/interpret/validity.rs @@ -342,7 +342,9 @@ impl<'rt, 'tcx, M: Machine<'tcx>> ValidityVisitor<'rt, 'tcx, M> { match layout.variants { Variants::Single { index } => { // Inside a variant - PathElem::Field(def.variant(index).fields[FieldIdx::from_usize(field)].name) + PathElem::Field( + def.variant(index.unwrap()).fields[FieldIdx::from_usize(field)].name, + ) } Variants::Multiple { .. } => bug!("we handled variants above"), } diff --git a/compiler/rustc_middle/src/mir/interpret/error.rs b/compiler/rustc_middle/src/mir/interpret/error.rs index fbada6ec405f..37328470aa7e 100644 --- a/compiler/rustc_middle/src/mir/interpret/error.rs +++ b/compiler/rustc_middle/src/mir/interpret/error.rs @@ -392,7 +392,7 @@ pub enum UndefinedBehaviorInfo<'tcx> { /// A discriminant of an uninhabited enum variant is written. UninhabitedEnumVariantWritten(VariantIdx), /// An uninhabited enum variant is projected. - UninhabitedEnumVariantRead(VariantIdx), + UninhabitedEnumVariantRead(Option), /// Trying to set discriminant to the niched variant, but the value does not match. InvalidNichedEnumVariantWritten { enum_ty: Ty<'tcx> }, /// ABI-incompatible argument types. diff --git a/compiler/rustc_middle/src/ty/layout.rs b/compiler/rustc_middle/src/ty/layout.rs index ad1680ed3a25..5f7b30b5d041 100644 --- a/compiler/rustc_middle/src/ty/layout.rs +++ b/compiler/rustc_middle/src/ty/layout.rs @@ -734,7 +734,7 @@ where let layout = match this.variants { Variants::Single { index } // If all variants but one are uninhabited, the variant layout is the enum layout. - if index == variant_index && + if index == Some(variant_index) && // Don't confuse variants of uninhabited enums with the enum itself. // For more details see https://github.com/rust-lang/rust/issues/69763. this.fields != FieldsShape::Primitive => @@ -743,6 +743,8 @@ where } Variants::Single { index } => { + // `Single` variant enums *can* have other variants, but those are uninhabited. + let tcx = cx.tcx(); let typing_env = cx.typing_env(); @@ -758,7 +760,7 @@ where _ => bug!("`ty_and_layout_for_variant` on unexpected type {}", this.ty), }; tcx.mk_layout(LayoutData { - variants: Variants::Single { index: variant_index }, + variants: Variants::Single { index: Some(variant_index) }, fields: match NonZero::new(fields) { Some(fields) => FieldsShape::Union(fields), None => FieldsShape::Arbitrary { offsets: IndexVec::new(), memory_index: IndexVec::new() }, @@ -775,7 +777,7 @@ where Variants::Multiple { ref variants, .. } => cx.tcx().mk_layout(variants[variant_index].clone()), }; - assert_eq!(*layout.variants(), Variants::Single { index: variant_index }); + assert_eq!(*layout.variants(), Variants::Single { index: Some(variant_index) }); TyAndLayout { ty: this.ty, layout } } @@ -905,7 +907,7 @@ where Variants::Single { index } => TyMaybeWithLayout::Ty( args.as_coroutine() .state_tys(def_id, tcx) - .nth(index.as_usize()) + .nth(index.unwrap().as_usize()) .unwrap() .nth(i) .unwrap(), @@ -924,7 +926,8 @@ where ty::Adt(def, args) => { match this.variants { Variants::Single { index } => { - let field = &def.variant(index).fields[FieldIdx::from_usize(i)]; + let field = + &def.variant(index.unwrap()).fields[FieldIdx::from_usize(i)]; TyMaybeWithLayout::Ty(field.ty(tcx, args)) } diff --git a/compiler/rustc_mir_transform/src/jump_threading.rs b/compiler/rustc_mir_transform/src/jump_threading.rs index beed007589bd..8feb90ff7a06 100644 --- a/compiler/rustc_mir_transform/src/jump_threading.rs +++ b/compiler/rustc_mir_transform/src/jump_threading.rs @@ -35,7 +35,6 @@ //! Likewise, applying the optimisation can create a lot of new MIR, so we bound the instruction //! cost by `MAX_COST`. -use rustc_abi::{TagEncoding, Variants}; use rustc_arena::DroplessArena; use rustc_const_eval::const_eval::DummyMachine; use rustc_const_eval::interpret::{ImmTy, Immediate, InterpCx, OpTy, Projectable}; @@ -565,31 +564,15 @@ impl<'a, 'tcx> TOFinder<'a, 'tcx> { StatementKind::SetDiscriminant { box place, variant_index } => { let Some(discr_target) = self.map.find_discr(place.as_ref()) else { return }; let enum_ty = place.ty(self.body, self.tcx).ty; - // `SetDiscriminant` may be a no-op if the assigned variant is the untagged variant - // of a niche encoding. If we cannot ensure that we write to the discriminant, do - // nothing. - let Ok(enum_layout) = self.ecx.layout_of(enum_ty) else { + // `SetDiscriminant` guarantees that the discriminant is now `variant_index`. + // Even if the discriminant write does nothing due to niches, it is UB to set the + // discriminant when the data does not encode the desired discriminant. + let Some(discr) = + self.ecx.discriminant_for_variant(enum_ty, *variant_index).discard_err() + else { return; }; - let writes_discriminant = match enum_layout.variants { - Variants::Single { index } => { - assert_eq!(index, *variant_index); - true - } - Variants::Multiple { tag_encoding: TagEncoding::Direct, .. } => true, - Variants::Multiple { - tag_encoding: TagEncoding::Niche { untagged_variant, .. }, - .. - } => *variant_index != untagged_variant, - }; - if writes_discriminant { - let Some(discr) = - self.ecx.discriminant_for_variant(enum_ty, *variant_index).discard_err() - else { - return; - }; - self.process_immediate(bb, discr_target, discr, state); - } + self.process_immediate(bb, discr_target, discr, state); } // If we expect `lhs ?= true`, we have an opportunity if we assume `lhs == true`. StatementKind::Intrinsic(box NonDivergingIntrinsic::Assume( diff --git a/compiler/rustc_mir_transform/src/unreachable_enum_branching.rs b/compiler/rustc_mir_transform/src/unreachable_enum_branching.rs index 57e255b7c32c..0ce3955163b8 100644 --- a/compiler/rustc_mir_transform/src/unreachable_enum_branching.rs +++ b/compiler/rustc_mir_transform/src/unreachable_enum_branching.rs @@ -54,7 +54,11 @@ fn variant_discriminants<'tcx>( tcx: TyCtxt<'tcx>, ) -> FxHashSet { match &layout.variants { - Variants::Single { index } => { + Variants::Single { index: None } => { + // Uninhabited, no valid discriminant. + FxHashSet::default() + } + Variants::Single { index: Some(index) } => { let mut res = FxHashSet::default(); res.insert( ty.discriminant_for_variant(tcx, *index) diff --git a/compiler/rustc_smir/src/rustc_smir/convert/abi.rs b/compiler/rustc_smir/src/rustc_smir/convert/abi.rs index af24fd23f50b..2717f4ab62f2 100644 --- a/compiler/rustc_smir/src/rustc_smir/convert/abi.rs +++ b/compiler/rustc_smir/src/rustc_smir/convert/abi.rs @@ -164,9 +164,9 @@ impl<'tcx> Stable<'tcx> for rustc_abi::Variants) -> Self::T { match self { - rustc_abi::Variants::Single { index } => { - VariantsShape::Single { index: index.stable(tables) } - } + rustc_abi::Variants::Single { index } => VariantsShape::Single { + index: index.unwrap_or(rustc_abi::VariantIdx::from_u32(0)).stable(tables), + }, rustc_abi::Variants::Multiple { tag, tag_encoding, tag_field, variants } => { VariantsShape::Multiple { tag: tag.stable(tables), diff --git a/compiler/rustc_transmute/src/layout/tree.rs b/compiler/rustc_transmute/src/layout/tree.rs index 83463babc4f4..049f4734e7b5 100644 --- a/compiler/rustc_transmute/src/layout/tree.rs +++ b/compiler/rustc_transmute/src/layout/tree.rs @@ -339,14 +339,12 @@ pub(crate) mod rustc { match layout.variants() { Variants::Single { index } => { - // Hilariously, `Single` is used even for 0-variant enums; - // `index` is just junk in that case. - if ty.ty_adt_def().unwrap().variants().is_empty() { - Ok(Self::uninhabited()) - } else { + if let Some(index) = index { // `Variants::Single` on enums with variants denotes that // the enum delegates its layout to the variant at `index`. layout_of_variant(*index, None) + } else { + Ok(Self::uninhabited()) } } Variants::Multiple { tag, tag_encoding, tag_field, .. } => { @@ -504,7 +502,7 @@ pub(crate) mod rustc { ty::Adt(def, args) => { match layout.variants { Variants::Single { index } => { - let field = &def.variant(index).fields[i]; + let field = &def.variant(index.unwrap()).fields[i]; field.ty(cx.tcx(), args) } // Discriminant field for enums (where applicable). diff --git a/compiler/rustc_ty_utils/src/layout.rs b/compiler/rustc_ty_utils/src/layout.rs index 7c7c3803ad9c..b393190a4932 100644 --- a/compiler/rustc_ty_utils/src/layout.rs +++ b/compiler/rustc_ty_utils/src/layout.rs @@ -339,7 +339,7 @@ fn layout_of_uncached<'tcx>( let largest_niche = if count != 0 { element.largest_niche } else { None }; tcx.mk_layout(LayoutData { - variants: Variants::Single { index: FIRST_VARIANT }, + variants: Variants::Single { index: Some(FIRST_VARIANT) }, fields: FieldsShape::Array { stride: element.size, count }, backend_repr: abi, largest_niche, @@ -352,7 +352,7 @@ fn layout_of_uncached<'tcx>( ty::Slice(element) => { let element = cx.layout_of(element)?; tcx.mk_layout(LayoutData { - variants: Variants::Single { index: FIRST_VARIANT }, + variants: Variants::Single { index: Some(FIRST_VARIANT) }, fields: FieldsShape::Array { stride: element.size, count: 0 }, backend_repr: BackendRepr::Memory { sized: false }, largest_niche: None, @@ -363,7 +363,7 @@ fn layout_of_uncached<'tcx>( }) } ty::Str => tcx.mk_layout(LayoutData { - variants: Variants::Single { index: FIRST_VARIANT }, + variants: Variants::Single { index: Some(FIRST_VARIANT) }, fields: FieldsShape::Array { stride: Size::from_bytes(1), count: 0 }, backend_repr: BackendRepr::Memory { sized: false }, largest_niche: None, @@ -534,7 +534,7 @@ fn layout_of_uncached<'tcx>( }; tcx.mk_layout(LayoutData { - variants: Variants::Single { index: FIRST_VARIANT }, + variants: Variants::Single { index: Some(FIRST_VARIANT) }, fields, backend_repr: abi, largest_niche: e_ly.largest_niche, @@ -926,7 +926,7 @@ fn coroutine_layout<'tcx>( &ReprOptions::default(), StructKind::Prefixed(prefix_size, prefix_align.abi), )?; - variant.variants = Variants::Single { index }; + variant.variants = Variants::Single { index: Some(index) }; let FieldsShape::Arbitrary { offsets, memory_index } = variant.fields else { bug!(); @@ -1105,7 +1105,9 @@ fn variant_info_for_adt<'tcx>( match layout.variants { Variants::Single { index } => { - if !adt_def.variants().is_empty() && layout.fields != FieldsShape::Primitive { + if let Some(index) = index + && layout.fields != FieldsShape::Primitive + { debug!("print-type-size `{:#?}` variant {}", layout, adt_def.variant(index).name); let variant_def = &adt_def.variant(index); let fields: Vec<_> = variant_def.fields.iter().map(|f| f.name).collect(); diff --git a/compiler/rustc_ty_utils/src/layout/invariant.rs b/compiler/rustc_ty_utils/src/layout/invariant.rs index f39b87622f44..7e2375154c09 100644 --- a/compiler/rustc_ty_utils/src/layout/invariant.rs +++ b/compiler/rustc_ty_utils/src/layout/invariant.rs @@ -241,63 +241,81 @@ pub(super) fn layout_sanity_check<'tcx>(cx: &LayoutCx<'tcx>, layout: &TyAndLayou check_layout_abi(cx, layout); - if let Variants::Multiple { variants, tag, tag_encoding, .. } = &layout.variants { - if let TagEncoding::Niche { niche_start, untagged_variant, niche_variants } = tag_encoding { - let niche_size = tag.size(cx); - assert!(*niche_start <= niche_size.unsigned_int_max()); - for (idx, variant) in variants.iter_enumerated() { - // Ensure all inhabited variants are accounted for. - if !variant.is_uninhabited() { - assert!(idx == *untagged_variant || niche_variants.contains(&idx)); - } + match &layout.variants { + Variants::Single { index: None } => { + assert!(layout.is_uninhabited()); + } + Variants::Single { index: Some(idx) } => { + if let Some(variants) = layout.ty.variant_range(tcx) { + assert!(variants.contains(idx)); + } else { + // Types without variants use `0` as dummy variant index. + assert!(idx.as_u32() == 0); } } - for variant in variants.iter() { - // No nested "multiple". - assert_matches!(variant.variants, Variants::Single { .. }); - // Variants should have the same or a smaller size as the full thing, - // and same for alignment. - if variant.size > layout.size { - bug!( - "Type with size {} bytes has variant with size {} bytes: {layout:#?}", - layout.size.bytes(), - variant.size.bytes(), - ) - } - if variant.align.abi > layout.align.abi { - bug!( - "Type with alignment {} bytes has variant with alignment {} bytes: {layout:#?}", - layout.align.abi.bytes(), - variant.align.abi.bytes(), - ) - } - // Skip empty variants. - if variant.size == Size::ZERO || variant.fields.count() == 0 || variant.is_uninhabited() + Variants::Multiple { variants, tag, tag_encoding, .. } => { + if let TagEncoding::Niche { niche_start, untagged_variant, niche_variants } = + tag_encoding { - // These are never actually accessed anyway, so we can skip the coherence check - // for them. They also fail that check, since they have - // `Aggregate`/`Uninhabited` ABI even when the main type is - // `Scalar`/`ScalarPair`. (Note that sometimes, variants with fields have size - // 0, and sometimes, variants without fields have non-0 size.) - continue; - } - // The top-level ABI and the ABI of the variants should be coherent. - let scalar_coherent = - |s1: Scalar, s2: Scalar| s1.size(cx) == s2.size(cx) && s1.align(cx) == s2.align(cx); - let abi_coherent = match (layout.backend_repr, variant.backend_repr) { - (BackendRepr::Scalar(s1), BackendRepr::Scalar(s2)) => scalar_coherent(s1, s2), - (BackendRepr::ScalarPair(a1, b1), BackendRepr::ScalarPair(a2, b2)) => { - scalar_coherent(a1, a2) && scalar_coherent(b1, b2) + let niche_size = tag.size(cx); + assert!(*niche_start <= niche_size.unsigned_int_max()); + for (idx, variant) in variants.iter_enumerated() { + // Ensure all inhabited variants are accounted for. + if !variant.is_uninhabited() { + assert!(idx == *untagged_variant || niche_variants.contains(&idx)); + } + } + } + for variant in variants.iter() { + // No nested "multiple". + assert_matches!(variant.variants, Variants::Single { .. }); + // Variants should have the same or a smaller size as the full thing, + // and same for alignment. + if variant.size > layout.size { + bug!( + "Type with size {} bytes has variant with size {} bytes: {layout:#?}", + layout.size.bytes(), + variant.size.bytes(), + ) + } + if variant.align.abi > layout.align.abi { + bug!( + "Type with alignment {} bytes has variant with alignment {} bytes: {layout:#?}", + layout.align.abi.bytes(), + variant.align.abi.bytes(), + ) + } + // Skip empty variants. + if variant.size == Size::ZERO + || variant.fields.count() == 0 + || variant.is_uninhabited() + { + // These are never actually accessed anyway, so we can skip the coherence check + // for them. They also fail that check, since they have + // `Aggregate`/`Uninhabited` ABI even when the main type is + // `Scalar`/`ScalarPair`. (Note that sometimes, variants with fields have size + // 0, and sometimes, variants without fields have non-0 size.) + continue; + } + // The top-level ABI and the ABI of the variants should be coherent. + let scalar_coherent = |s1: Scalar, s2: Scalar| { + s1.size(cx) == s2.size(cx) && s1.align(cx) == s2.align(cx) + }; + let abi_coherent = match (layout.backend_repr, variant.backend_repr) { + (BackendRepr::Scalar(s1), BackendRepr::Scalar(s2)) => scalar_coherent(s1, s2), + (BackendRepr::ScalarPair(a1, b1), BackendRepr::ScalarPair(a2, b2)) => { + scalar_coherent(a1, a2) && scalar_coherent(b1, b2) + } + (BackendRepr::Uninhabited, _) => true, + (BackendRepr::Memory { .. }, _) => true, + _ => false, + }; + if !abi_coherent { + bug!( + "Variant ABI is incompatible with top-level ABI:\nvariant={:#?}\nTop-level: {layout:#?}", + variant + ); } - (BackendRepr::Uninhabited, _) => true, - (BackendRepr::Memory { .. }, _) => true, - _ => false, - }; - if !abi_coherent { - bug!( - "Variant ABI is incompatible with top-level ABI:\nvariant={:#?}\nTop-level: {layout:#?}", - variant - ); } } } diff --git a/compiler/stable_mir/src/abi.rs b/compiler/stable_mir/src/abi.rs index 2ac30b5aff12..cf28a0c58856 100644 --- a/compiler/stable_mir/src/abi.rs +++ b/compiler/stable_mir/src/abi.rs @@ -181,6 +181,7 @@ impl FieldsShape { #[derive(Clone, Debug, PartialEq, Eq, Hash, Serialize)] pub enum VariantsShape { /// Single enum variants, structs/tuples, unions, and all non-ADTs. + // FIXME: needs to become `Option` like in the internal type. Single { index: VariantIdx }, /// Enum-likes with more than one inhabited variant: each variant comes with diff --git a/src/tools/rust-analyzer/crates/hir-ty/src/layout.rs b/src/tools/rust-analyzer/crates/hir-ty/src/layout.rs index 0c1f63880cd2..08026f11c832 100644 --- a/src/tools/rust-analyzer/crates/hir-ty/src/layout.rs +++ b/src/tools/rust-analyzer/crates/hir-ty/src/layout.rs @@ -189,7 +189,7 @@ fn layout_of_simd_ty( }; Ok(Arc::new(Layout { - variants: Variants::Single { index: struct_variant_idx() }, + variants: Variants::Single { index: Some(struct_variant_idx()) }, fields, backend_repr: BackendRepr::Vector { element: e_abi, count: e_len }, largest_niche: e_ly.largest_niche, @@ -305,7 +305,7 @@ pub fn layout_of_ty_query( let largest_niche = if count != 0 { element.largest_niche } else { None }; Layout { - variants: Variants::Single { index: struct_variant_idx() }, + variants: Variants::Single { index: Some(struct_variant_idx()) }, fields: FieldsShape::Array { stride: element.size, count }, backend_repr, largest_niche, @@ -318,7 +318,7 @@ pub fn layout_of_ty_query( TyKind::Slice(element) => { let element = db.layout_of_ty(element.clone(), trait_env)?; Layout { - variants: Variants::Single { index: struct_variant_idx() }, + variants: Variants::Single { index: Some(struct_variant_idx()) }, fields: FieldsShape::Array { stride: element.size, count: 0 }, backend_repr: BackendRepr::Memory { sized: false }, largest_niche: None, @@ -329,7 +329,7 @@ pub fn layout_of_ty_query( } } TyKind::Str => Layout { - variants: Variants::Single { index: struct_variant_idx() }, + variants: Variants::Single { index: Some(struct_variant_idx()) }, fields: FieldsShape::Array { stride: Size::from_bytes(1), count: 0 }, backend_repr: BackendRepr::Memory { sized: false }, largest_niche: None, diff --git a/src/tools/rust-analyzer/crates/hir-ty/src/mir/eval.rs b/src/tools/rust-analyzer/crates/hir-ty/src/mir/eval.rs index d7029651fc18..9375853e9159 100644 --- a/src/tools/rust-analyzer/crates/hir-ty/src/mir/eval.rs +++ b/src/tools/rust-analyzer/crates/hir-ty/src/mir/eval.rs @@ -1639,7 +1639,8 @@ impl Evaluator<'_> { }; match &layout.variants { Variants::Single { index } => { - let r = self.const_eval_discriminant(self.db.enum_data(e).variants[index.0].0)?; + let r = self + .const_eval_discriminant(self.db.enum_data(e).variants[index.unwrap().0].0)?; Ok(r) } Variants::Multiple { tag, tag_encoding, variants, .. } => { diff --git a/src/tools/rust-analyzer/crates/hir-ty/src/utils.rs b/src/tools/rust-analyzer/crates/hir-ty/src/utils.rs index 06719b09f735..43ed6a06f428 100644 --- a/src/tools/rust-analyzer/crates/hir-ty/src/utils.rs +++ b/src/tools/rust-analyzer/crates/hir-ty/src/utils.rs @@ -335,7 +335,7 @@ pub(crate) fn detect_variant_from_bytes<'a>( ) -> Option<(EnumVariantId, &'a Layout)> { let (var_id, var_layout) = match &layout.variants { hir_def::layout::Variants::Single { index } => { - (db.enum_data(e).variants[index.0].0, layout) + (db.enum_data(e).variants[index.unwrap().0].0, layout) } hir_def::layout::Variants::Multiple { tag, tag_encoding, variants, .. } => { let size = tag.size(target_data_layout).bytes_usize(); diff --git a/tests/mir-opt/set_no_discriminant.f.JumpThreading.diff b/tests/mir-opt/set_no_discriminant.f.JumpThreading.diff index 3d9852aef657..992b16fabf6b 100644 --- a/tests/mir-opt/set_no_discriminant.f.JumpThreading.diff +++ b/tests/mir-opt/set_no_discriminant.f.JumpThreading.diff @@ -10,7 +10,8 @@ _2 = E::::A; discriminant(_2) = 1; _1 = discriminant(_2); - switchInt(copy _1) -> [0: bb1, otherwise: bb2]; +- switchInt(copy _1) -> [0: bb1, otherwise: bb2]; ++ goto -> bb2; } bb1: { diff --git a/tests/mir-opt/set_no_discriminant.generic.JumpThreading.diff b/tests/mir-opt/set_no_discriminant.generic.JumpThreading.diff index c7af16383161..0600b751699d 100644 --- a/tests/mir-opt/set_no_discriminant.generic.JumpThreading.diff +++ b/tests/mir-opt/set_no_discriminant.generic.JumpThreading.diff @@ -10,7 +10,8 @@ _2 = E::::A; discriminant(_2) = 1; _1 = discriminant(_2); - switchInt(copy _1) -> [0: bb1, otherwise: bb2]; +- switchInt(copy _1) -> [0: bb1, otherwise: bb2]; ++ goto -> bb2; } bb1: { diff --git a/tests/mir-opt/set_no_discriminant.rs b/tests/mir-opt/set_no_discriminant.rs index 586e28ae426a..c44575a4d611 100644 --- a/tests/mir-opt/set_no_discriminant.rs +++ b/tests/mir-opt/set_no_discriminant.rs @@ -1,5 +1,6 @@ // `SetDiscriminant` does not actually write anything if the chosen variant is the untagged variant -// of a niche encoding. Verify that we do not thread over this case. +// of a niche encoding. However, it is UB to call `SetDiscriminant` with the untagged variant if the +// value currently encodes a different variant. Verify that we do correctly thread in this case. //@ test-mir-pass: JumpThreading #![feature(custom_mir)] @@ -16,20 +17,21 @@ enum E { #[custom_mir(dialect = "runtime")] pub fn f() -> usize { // CHECK-LABEL: fn f( - // CHECK-NOT: goto - // CHECK: switchInt( - // CHECK-NOT: goto + // CHECK-NOT: switchInt + // CHECK: goto + // CHECK-NOT: switchInt mir! { let a: isize; let e: E; { e = E::A; - SetDiscriminant(e, 1); + SetDiscriminant(e, 1); // UB! a = Discriminant(e); match a { 0 => bb0, _ => bb1, } + } bb0 = { RET = 0; @@ -46,15 +48,15 @@ pub fn f() -> usize { #[custom_mir(dialect = "runtime")] pub fn generic() -> usize { // CHECK-LABEL: fn generic( - // CHECK-NOT: goto - // CHECK: switchInt( - // CHECK-NOT: goto + // CHECK-NOT: switchInt + // CHECK: goto + // CHECK-NOT: switchInt mir! { let a: isize; let e: E; { e = E::A; - SetDiscriminant(e, 1); + SetDiscriminant(e, 1); // UB! a = Discriminant(e); match a { 0 => bb0, @@ -72,6 +74,7 @@ pub fn generic() -> usize { } } +// CHECK-LABEL: fn main( fn main() { assert_eq!(f(), 0); assert_eq!(generic::(), 0); diff --git a/tests/ui/abi/c-zst.aarch64-darwin.stderr b/tests/ui/abi/c-zst.aarch64-darwin.stderr index 7d384bc875f9..aae92bd7dc9f 100644 --- a/tests/ui/abi/c-zst.aarch64-darwin.stderr +++ b/tests/ui/abi/c-zst.aarch64-darwin.stderr @@ -18,7 +18,9 @@ error: fn_abi_of(pass_zst) = FnAbi { }, largest_niche: None, variants: Single { - index: 0, + index: Some( + 0, + ), }, max_repr_align: None, unadjusted_abi_align: $SOME_ALIGN, @@ -45,7 +47,9 @@ error: fn_abi_of(pass_zst) = FnAbi { }, largest_niche: None, variants: Single { - index: 0, + index: Some( + 0, + ), }, max_repr_align: None, unadjusted_abi_align: $SOME_ALIGN, diff --git a/tests/ui/abi/c-zst.powerpc-linux.stderr b/tests/ui/abi/c-zst.powerpc-linux.stderr index 7980710bab67..4ff4a8b90cf7 100644 --- a/tests/ui/abi/c-zst.powerpc-linux.stderr +++ b/tests/ui/abi/c-zst.powerpc-linux.stderr @@ -18,7 +18,9 @@ error: fn_abi_of(pass_zst) = FnAbi { }, largest_niche: None, variants: Single { - index: 0, + index: Some( + 0, + ), }, max_repr_align: None, unadjusted_abi_align: $SOME_ALIGN, @@ -56,7 +58,9 @@ error: fn_abi_of(pass_zst) = FnAbi { }, largest_niche: None, variants: Single { - index: 0, + index: Some( + 0, + ), }, max_repr_align: None, unadjusted_abi_align: $SOME_ALIGN, diff --git a/tests/ui/abi/c-zst.s390x-linux.stderr b/tests/ui/abi/c-zst.s390x-linux.stderr index 7980710bab67..4ff4a8b90cf7 100644 --- a/tests/ui/abi/c-zst.s390x-linux.stderr +++ b/tests/ui/abi/c-zst.s390x-linux.stderr @@ -18,7 +18,9 @@ error: fn_abi_of(pass_zst) = FnAbi { }, largest_niche: None, variants: Single { - index: 0, + index: Some( + 0, + ), }, max_repr_align: None, unadjusted_abi_align: $SOME_ALIGN, @@ -56,7 +58,9 @@ error: fn_abi_of(pass_zst) = FnAbi { }, largest_niche: None, variants: Single { - index: 0, + index: Some( + 0, + ), }, max_repr_align: None, unadjusted_abi_align: $SOME_ALIGN, diff --git a/tests/ui/abi/c-zst.sparc64-linux.stderr b/tests/ui/abi/c-zst.sparc64-linux.stderr index 7980710bab67..4ff4a8b90cf7 100644 --- a/tests/ui/abi/c-zst.sparc64-linux.stderr +++ b/tests/ui/abi/c-zst.sparc64-linux.stderr @@ -18,7 +18,9 @@ error: fn_abi_of(pass_zst) = FnAbi { }, largest_niche: None, variants: Single { - index: 0, + index: Some( + 0, + ), }, max_repr_align: None, unadjusted_abi_align: $SOME_ALIGN, @@ -56,7 +58,9 @@ error: fn_abi_of(pass_zst) = FnAbi { }, largest_niche: None, variants: Single { - index: 0, + index: Some( + 0, + ), }, max_repr_align: None, unadjusted_abi_align: $SOME_ALIGN, diff --git a/tests/ui/abi/c-zst.x86_64-linux.stderr b/tests/ui/abi/c-zst.x86_64-linux.stderr index 7d384bc875f9..aae92bd7dc9f 100644 --- a/tests/ui/abi/c-zst.x86_64-linux.stderr +++ b/tests/ui/abi/c-zst.x86_64-linux.stderr @@ -18,7 +18,9 @@ error: fn_abi_of(pass_zst) = FnAbi { }, largest_niche: None, variants: Single { - index: 0, + index: Some( + 0, + ), }, max_repr_align: None, unadjusted_abi_align: $SOME_ALIGN, @@ -45,7 +47,9 @@ error: fn_abi_of(pass_zst) = FnAbi { }, largest_niche: None, variants: Single { - index: 0, + index: Some( + 0, + ), }, max_repr_align: None, unadjusted_abi_align: $SOME_ALIGN, diff --git a/tests/ui/abi/c-zst.x86_64-pc-windows-gnu.stderr b/tests/ui/abi/c-zst.x86_64-pc-windows-gnu.stderr index 7980710bab67..4ff4a8b90cf7 100644 --- a/tests/ui/abi/c-zst.x86_64-pc-windows-gnu.stderr +++ b/tests/ui/abi/c-zst.x86_64-pc-windows-gnu.stderr @@ -18,7 +18,9 @@ error: fn_abi_of(pass_zst) = FnAbi { }, largest_niche: None, variants: Single { - index: 0, + index: Some( + 0, + ), }, max_repr_align: None, unadjusted_abi_align: $SOME_ALIGN, @@ -56,7 +58,9 @@ error: fn_abi_of(pass_zst) = FnAbi { }, largest_niche: None, variants: Single { - index: 0, + index: Some( + 0, + ), }, max_repr_align: None, unadjusted_abi_align: $SOME_ALIGN, diff --git a/tests/ui/abi/debug.stderr b/tests/ui/abi/debug.stderr index aa51c42c58dc..0cbdf366616c 100644 --- a/tests/ui/abi/debug.stderr +++ b/tests/ui/abi/debug.stderr @@ -21,7 +21,9 @@ error: fn_abi_of(test) = FnAbi { fields: Primitive, largest_niche: None, variants: Single { - index: 0, + index: Some( + 0, + ), }, max_repr_align: None, unadjusted_abi_align: $SOME_ALIGN, @@ -67,7 +69,9 @@ error: fn_abi_of(test) = FnAbi { }, ), variants: Single { - index: 0, + index: Some( + 0, + ), }, max_repr_align: None, unadjusted_abi_align: $SOME_ALIGN, @@ -124,7 +128,9 @@ error: fn_abi_of(TestFnPtr) = FnAbi { }, ), variants: Single { - index: 0, + index: Some( + 0, + ), }, max_repr_align: None, unadjusted_abi_align: $SOME_ALIGN, @@ -161,7 +167,9 @@ error: fn_abi_of(TestFnPtr) = FnAbi { fields: Primitive, largest_niche: None, variants: Single { - index: 0, + index: Some( + 0, + ), }, max_repr_align: None, unadjusted_abi_align: $SOME_ALIGN, @@ -210,7 +218,9 @@ error: fn_abi_of(test_generic) = FnAbi { fields: Primitive, largest_niche: None, variants: Single { - index: 0, + index: Some( + 0, + ), }, max_repr_align: None, unadjusted_abi_align: $SOME_ALIGN, @@ -244,7 +254,9 @@ error: fn_abi_of(test_generic) = FnAbi { }, largest_niche: None, variants: Single { - index: 0, + index: Some( + 0, + ), }, max_repr_align: None, unadjusted_abi_align: $SOME_ALIGN, @@ -292,7 +304,9 @@ error: ABIs are not compatible fields: Primitive, largest_niche: None, variants: Single { - index: 0, + index: Some( + 0, + ), }, max_repr_align: None, unadjusted_abi_align: $SOME_ALIGN, @@ -326,7 +340,9 @@ error: ABIs are not compatible }, largest_niche: None, variants: Single { - index: 0, + index: Some( + 0, + ), }, max_repr_align: None, unadjusted_abi_align: $SOME_ALIGN, @@ -362,7 +378,9 @@ error: ABIs are not compatible fields: Primitive, largest_niche: None, variants: Single { - index: 0, + index: Some( + 0, + ), }, max_repr_align: None, unadjusted_abi_align: $SOME_ALIGN, @@ -396,7 +414,9 @@ error: ABIs are not compatible }, largest_niche: None, variants: Single { - index: 0, + index: Some( + 0, + ), }, max_repr_align: None, unadjusted_abi_align: $SOME_ALIGN, @@ -435,7 +455,9 @@ error: ABIs are not compatible }, largest_niche: None, variants: Single { - index: 0, + index: Some( + 0, + ), }, max_repr_align: None, unadjusted_abi_align: $SOME_ALIGN, @@ -473,7 +495,9 @@ error: ABIs are not compatible }, largest_niche: None, variants: Single { - index: 0, + index: Some( + 0, + ), }, max_repr_align: None, unadjusted_abi_align: $SOME_ALIGN, @@ -506,7 +530,9 @@ error: ABIs are not compatible }, largest_niche: None, variants: Single { - index: 0, + index: Some( + 0, + ), }, max_repr_align: None, unadjusted_abi_align: $SOME_ALIGN, @@ -544,7 +570,9 @@ error: ABIs are not compatible }, largest_niche: None, variants: Single { - index: 0, + index: Some( + 0, + ), }, max_repr_align: None, unadjusted_abi_align: $SOME_ALIGN, @@ -585,7 +613,9 @@ error: ABIs are not compatible fields: Primitive, largest_niche: None, variants: Single { - index: 0, + index: Some( + 0, + ), }, max_repr_align: None, unadjusted_abi_align: $SOME_ALIGN, @@ -619,7 +649,9 @@ error: ABIs are not compatible }, largest_niche: None, variants: Single { - index: 0, + index: Some( + 0, + ), }, max_repr_align: None, unadjusted_abi_align: $SOME_ALIGN, @@ -655,7 +687,9 @@ error: ABIs are not compatible fields: Primitive, largest_niche: None, variants: Single { - index: 0, + index: Some( + 0, + ), }, max_repr_align: None, unadjusted_abi_align: $SOME_ALIGN, @@ -689,7 +723,9 @@ error: ABIs are not compatible }, largest_niche: None, variants: Single { - index: 0, + index: Some( + 0, + ), }, max_repr_align: None, unadjusted_abi_align: $SOME_ALIGN, @@ -731,7 +767,9 @@ error: ABIs are not compatible fields: Primitive, largest_niche: None, variants: Single { - index: 0, + index: Some( + 0, + ), }, max_repr_align: None, unadjusted_abi_align: $SOME_ALIGN, @@ -765,7 +803,9 @@ error: ABIs are not compatible }, largest_niche: None, variants: Single { - index: 0, + index: Some( + 0, + ), }, max_repr_align: None, unadjusted_abi_align: $SOME_ALIGN, @@ -801,7 +841,9 @@ error: ABIs are not compatible fields: Primitive, largest_niche: None, variants: Single { - index: 0, + index: Some( + 0, + ), }, max_repr_align: None, unadjusted_abi_align: $SOME_ALIGN, @@ -835,7 +877,9 @@ error: ABIs are not compatible }, largest_niche: None, variants: Single { - index: 0, + index: Some( + 0, + ), }, max_repr_align: None, unadjusted_abi_align: $SOME_ALIGN, @@ -902,7 +946,9 @@ error: fn_abi_of(assoc_test) = FnAbi { }, ), variants: Single { - index: 0, + index: Some( + 0, + ), }, max_repr_align: None, unadjusted_abi_align: $SOME_ALIGN, @@ -938,7 +984,9 @@ error: fn_abi_of(assoc_test) = FnAbi { }, largest_niche: None, variants: Single { - index: 0, + index: Some( + 0, + ), }, max_repr_align: None, unadjusted_abi_align: $SOME_ALIGN, diff --git a/tests/ui/abi/sysv64-zst.stderr b/tests/ui/abi/sysv64-zst.stderr index 8e1791e27d27..920963c69874 100644 --- a/tests/ui/abi/sysv64-zst.stderr +++ b/tests/ui/abi/sysv64-zst.stderr @@ -18,7 +18,9 @@ error: fn_abi_of(pass_zst) = FnAbi { }, largest_niche: None, variants: Single { - index: 0, + index: Some( + 0, + ), }, max_repr_align: None, unadjusted_abi_align: $SOME_ALIGN, @@ -45,7 +47,9 @@ error: fn_abi_of(pass_zst) = FnAbi { }, largest_niche: None, variants: Single { - index: 0, + index: Some( + 0, + ), }, max_repr_align: None, unadjusted_abi_align: $SOME_ALIGN, diff --git a/tests/ui/abi/win64-zst.x86_64-linux.stderr b/tests/ui/abi/win64-zst.x86_64-linux.stderr index 76d90670eb1d..2752555b4f31 100644 --- a/tests/ui/abi/win64-zst.x86_64-linux.stderr +++ b/tests/ui/abi/win64-zst.x86_64-linux.stderr @@ -18,7 +18,9 @@ error: fn_abi_of(pass_zst) = FnAbi { }, largest_niche: None, variants: Single { - index: 0, + index: Some( + 0, + ), }, max_repr_align: None, unadjusted_abi_align: $SOME_ALIGN, @@ -45,7 +47,9 @@ error: fn_abi_of(pass_zst) = FnAbi { }, largest_niche: None, variants: Single { - index: 0, + index: Some( + 0, + ), }, max_repr_align: None, unadjusted_abi_align: $SOME_ALIGN, diff --git a/tests/ui/abi/win64-zst.x86_64-windows-gnu.stderr b/tests/ui/abi/win64-zst.x86_64-windows-gnu.stderr index 7ee90e247441..19abb5930b15 100644 --- a/tests/ui/abi/win64-zst.x86_64-windows-gnu.stderr +++ b/tests/ui/abi/win64-zst.x86_64-windows-gnu.stderr @@ -18,7 +18,9 @@ error: fn_abi_of(pass_zst) = FnAbi { }, largest_niche: None, variants: Single { - index: 0, + index: Some( + 0, + ), }, max_repr_align: None, unadjusted_abi_align: $SOME_ALIGN, @@ -56,7 +58,9 @@ error: fn_abi_of(pass_zst) = FnAbi { }, largest_niche: None, variants: Single { - index: 0, + index: Some( + 0, + ), }, max_repr_align: None, unadjusted_abi_align: $SOME_ALIGN, diff --git a/tests/ui/abi/win64-zst.x86_64-windows-msvc.stderr b/tests/ui/abi/win64-zst.x86_64-windows-msvc.stderr index 76d90670eb1d..2752555b4f31 100644 --- a/tests/ui/abi/win64-zst.x86_64-windows-msvc.stderr +++ b/tests/ui/abi/win64-zst.x86_64-windows-msvc.stderr @@ -18,7 +18,9 @@ error: fn_abi_of(pass_zst) = FnAbi { }, largest_niche: None, variants: Single { - index: 0, + index: Some( + 0, + ), }, max_repr_align: None, unadjusted_abi_align: $SOME_ALIGN, @@ -45,7 +47,9 @@ error: fn_abi_of(pass_zst) = FnAbi { }, largest_niche: None, variants: Single { - index: 0, + index: Some( + 0, + ), }, max_repr_align: None, unadjusted_abi_align: $SOME_ALIGN, diff --git a/tests/ui/layout/debug.stderr b/tests/ui/layout/debug.stderr index bd31665dac1f..8ae2933c427e 100644 --- a/tests/ui/layout/debug.stderr +++ b/tests/ui/layout/debug.stderr @@ -57,7 +57,9 @@ error: layout_of(E) = Layout { }, largest_niche: None, variants: Single { - index: 0, + index: Some( + 0, + ), }, max_repr_align: None, unadjusted_abi_align: Align(1 bytes), @@ -83,7 +85,9 @@ error: layout_of(E) = Layout { }, largest_niche: None, variants: Single { - index: 1, + index: Some( + 1, + ), }, max_repr_align: None, unadjusted_abi_align: Align(4 bytes), @@ -134,7 +138,9 @@ error: layout_of(S) = Layout { }, largest_niche: None, variants: Single { - index: 0, + index: Some( + 0, + ), }, max_repr_align: None, unadjusted_abi_align: Align(4 bytes), @@ -158,7 +164,9 @@ error: layout_of(U) = Layout { ), largest_niche: None, variants: Single { - index: 0, + index: Some( + 0, + ), }, max_repr_align: None, unadjusted_abi_align: Align(4 bytes), @@ -251,7 +259,9 @@ error: layout_of(Result) = Layout { }, largest_niche: None, variants: Single { - index: 0, + index: Some( + 0, + ), }, max_repr_align: None, unadjusted_abi_align: Align(4 bytes), @@ -288,7 +298,9 @@ error: layout_of(Result) = Layout { }, largest_niche: None, variants: Single { - index: 1, + index: Some( + 1, + ), }, max_repr_align: None, unadjusted_abi_align: Align(4 bytes), @@ -321,7 +333,9 @@ error: layout_of(i32) = Layout { fields: Primitive, largest_niche: None, variants: Single { - index: 0, + index: Some( + 0, + ), }, max_repr_align: None, unadjusted_abi_align: Align(4 bytes), @@ -345,7 +359,9 @@ error: layout_of(V) = Layout { ), largest_niche: None, variants: Single { - index: 0, + index: Some( + 0, + ), }, max_repr_align: None, unadjusted_abi_align: Align(2 bytes), @@ -369,7 +385,9 @@ error: layout_of(W) = Layout { ), largest_niche: None, variants: Single { - index: 0, + index: Some( + 0, + ), }, max_repr_align: None, unadjusted_abi_align: Align(2 bytes), @@ -393,7 +411,9 @@ error: layout_of(Y) = Layout { ), largest_niche: None, variants: Single { - index: 0, + index: Some( + 0, + ), }, max_repr_align: None, unadjusted_abi_align: Align(2 bytes), @@ -417,7 +437,9 @@ error: layout_of(P1) = Layout { ), largest_niche: None, variants: Single { - index: 0, + index: Some( + 0, + ), }, max_repr_align: None, unadjusted_abi_align: Align(1 bytes), @@ -441,7 +463,9 @@ error: layout_of(P2) = Layout { ), largest_niche: None, variants: Single { - index: 0, + index: Some( + 0, + ), }, max_repr_align: None, unadjusted_abi_align: Align(1 bytes), @@ -465,7 +489,9 @@ error: layout_of(P3) = Layout { ), largest_niche: None, variants: Single { - index: 0, + index: Some( + 0, + ), }, max_repr_align: None, unadjusted_abi_align: Align(1 bytes), @@ -489,7 +515,9 @@ error: layout_of(P4) = Layout { ), largest_niche: None, variants: Single { - index: 0, + index: Some( + 0, + ), }, max_repr_align: None, unadjusted_abi_align: Align(1 bytes), @@ -518,7 +546,9 @@ error: layout_of(P5) = Layout { ), largest_niche: None, variants: Single { - index: 0, + index: Some( + 0, + ), }, max_repr_align: None, unadjusted_abi_align: Align(1 bytes), @@ -547,7 +577,9 @@ error: layout_of(MaybeUninit) = Layout { ), largest_niche: None, variants: Single { - index: 0, + index: Some( + 0, + ), }, max_repr_align: None, unadjusted_abi_align: Align(1 bytes), diff --git a/tests/ui/layout/hexagon-enum.stderr b/tests/ui/layout/hexagon-enum.stderr index 59fe667923f1..a934f270911b 100644 --- a/tests/ui/layout/hexagon-enum.stderr +++ b/tests/ui/layout/hexagon-enum.stderr @@ -57,7 +57,9 @@ error: layout_of(A) = Layout { }, largest_niche: None, variants: Single { - index: 0, + index: Some( + 0, + ), }, max_repr_align: None, unadjusted_abi_align: Align(1 bytes), @@ -131,7 +133,9 @@ error: layout_of(B) = Layout { }, largest_niche: None, variants: Single { - index: 0, + index: Some( + 0, + ), }, max_repr_align: None, unadjusted_abi_align: Align(1 bytes), @@ -205,7 +209,9 @@ error: layout_of(C) = Layout { }, largest_niche: None, variants: Single { - index: 0, + index: Some( + 0, + ), }, max_repr_align: None, unadjusted_abi_align: Align(2 bytes), @@ -279,7 +285,9 @@ error: layout_of(P) = Layout { }, largest_niche: None, variants: Single { - index: 0, + index: Some( + 0, + ), }, max_repr_align: None, unadjusted_abi_align: Align(4 bytes), @@ -353,7 +361,9 @@ error: layout_of(T) = Layout { }, largest_niche: None, variants: Single { - index: 0, + index: Some( + 0, + ), }, max_repr_align: None, unadjusted_abi_align: Align(4 bytes), diff --git a/tests/ui/layout/issue-96158-scalarpair-payload-might-be-uninit.stderr b/tests/ui/layout/issue-96158-scalarpair-payload-might-be-uninit.stderr index ca041fb539b9..8b4e46de8450 100644 --- a/tests/ui/layout/issue-96158-scalarpair-payload-might-be-uninit.stderr +++ b/tests/ui/layout/issue-96158-scalarpair-payload-might-be-uninit.stderr @@ -79,7 +79,9 @@ error: layout_of(MissingPayloadField) = Layout { }, largest_niche: None, variants: Single { - index: 0, + index: Some( + 0, + ), }, max_repr_align: None, unadjusted_abi_align: Align(1 bytes), @@ -99,7 +101,9 @@ error: layout_of(MissingPayloadField) = Layout { }, largest_niche: None, variants: Single { - index: 1, + index: Some( + 1, + ), }, max_repr_align: None, unadjusted_abi_align: Align(1 bytes), @@ -197,7 +201,9 @@ error: layout_of(CommonPayloadField) = Layout { }, largest_niche: None, variants: Single { - index: 0, + index: Some( + 0, + ), }, max_repr_align: None, unadjusted_abi_align: Align(1 bytes), @@ -234,7 +240,9 @@ error: layout_of(CommonPayloadField) = Layout { }, largest_niche: None, variants: Single { - index: 1, + index: Some( + 1, + ), }, max_repr_align: None, unadjusted_abi_align: Align(1 bytes), @@ -330,7 +338,9 @@ error: layout_of(CommonPayloadFieldIsMaybeUninit) = Layout { }, largest_niche: None, variants: Single { - index: 0, + index: Some( + 0, + ), }, max_repr_align: None, unadjusted_abi_align: Align(1 bytes), @@ -366,7 +376,9 @@ error: layout_of(CommonPayloadFieldIsMaybeUninit) = Layout { }, largest_niche: None, variants: Single { - index: 1, + index: Some( + 1, + ), }, max_repr_align: None, unadjusted_abi_align: Align(1 bytes), @@ -478,7 +490,9 @@ error: layout_of(NicheFirst) = Layout { }, ), variants: Single { - index: 0, + index: Some( + 0, + ), }, max_repr_align: None, unadjusted_abi_align: Align(1 bytes), @@ -498,7 +512,9 @@ error: layout_of(NicheFirst) = Layout { }, largest_niche: None, variants: Single { - index: 1, + index: Some( + 1, + ), }, max_repr_align: None, unadjusted_abi_align: Align(1 bytes), @@ -518,7 +534,9 @@ error: layout_of(NicheFirst) = Layout { }, largest_niche: None, variants: Single { - index: 2, + index: Some( + 2, + ), }, max_repr_align: None, unadjusted_abi_align: Align(1 bytes), @@ -630,7 +648,9 @@ error: layout_of(NicheSecond) = Layout { }, ), variants: Single { - index: 0, + index: Some( + 0, + ), }, max_repr_align: None, unadjusted_abi_align: Align(1 bytes), @@ -650,7 +670,9 @@ error: layout_of(NicheSecond) = Layout { }, largest_niche: None, variants: Single { - index: 1, + index: Some( + 1, + ), }, max_repr_align: None, unadjusted_abi_align: Align(1 bytes), @@ -670,7 +692,9 @@ error: layout_of(NicheSecond) = Layout { }, largest_niche: None, variants: Single { - index: 2, + index: Some( + 2, + ), }, max_repr_align: None, unadjusted_abi_align: Align(1 bytes), diff --git a/tests/ui/layout/issue-96185-overaligned-enum.stderr b/tests/ui/layout/issue-96185-overaligned-enum.stderr index bc40a2aa482e..926434455950 100644 --- a/tests/ui/layout/issue-96185-overaligned-enum.stderr +++ b/tests/ui/layout/issue-96185-overaligned-enum.stderr @@ -51,7 +51,9 @@ error: layout_of(Aligned1) = Layout { }, largest_niche: None, variants: Single { - index: 0, + index: Some( + 0, + ), }, max_repr_align: Some( Align(8 bytes), @@ -73,7 +75,9 @@ error: layout_of(Aligned1) = Layout { }, largest_niche: None, variants: Single { - index: 1, + index: Some( + 1, + ), }, max_repr_align: Some( Align(8 bytes), @@ -151,7 +155,9 @@ error: layout_of(Aligned2) = Layout { }, largest_niche: None, variants: Single { - index: 0, + index: Some( + 0, + ), }, max_repr_align: Some( Align(1 bytes), @@ -173,7 +179,9 @@ error: layout_of(Aligned2) = Layout { }, largest_niche: None, variants: Single { - index: 1, + index: Some( + 1, + ), }, max_repr_align: Some( Align(1 bytes), diff --git a/tests/ui/layout/thumb-enum.stderr b/tests/ui/layout/thumb-enum.stderr index bf043af586b1..f35cf0dab3da 100644 --- a/tests/ui/layout/thumb-enum.stderr +++ b/tests/ui/layout/thumb-enum.stderr @@ -57,7 +57,9 @@ error: layout_of(A) = Layout { }, largest_niche: None, variants: Single { - index: 0, + index: Some( + 0, + ), }, max_repr_align: None, unadjusted_abi_align: Align(1 bytes), @@ -131,7 +133,9 @@ error: layout_of(B) = Layout { }, largest_niche: None, variants: Single { - index: 0, + index: Some( + 0, + ), }, max_repr_align: None, unadjusted_abi_align: Align(1 bytes), @@ -205,7 +209,9 @@ error: layout_of(C) = Layout { }, largest_niche: None, variants: Single { - index: 0, + index: Some( + 0, + ), }, max_repr_align: None, unadjusted_abi_align: Align(2 bytes), @@ -279,7 +285,9 @@ error: layout_of(P) = Layout { }, largest_niche: None, variants: Single { - index: 0, + index: Some( + 0, + ), }, max_repr_align: None, unadjusted_abi_align: Align(4 bytes), @@ -353,7 +361,9 @@ error: layout_of(T) = Layout { }, largest_niche: None, variants: Single { - index: 0, + index: Some( + 0, + ), }, max_repr_align: None, unadjusted_abi_align: Align(4 bytes), diff --git a/tests/ui/layout/zero-sized-array-enum-niche.stderr b/tests/ui/layout/zero-sized-array-enum-niche.stderr index d61408098df7..4c6f636b267a 100644 --- a/tests/ui/layout/zero-sized-array-enum-niche.stderr +++ b/tests/ui/layout/zero-sized-array-enum-niche.stderr @@ -55,7 +55,9 @@ error: layout_of(Result<[u32; 0], bool>) = Layout { }, largest_niche: None, variants: Single { - index: 0, + index: Some( + 0, + ), }, max_repr_align: None, unadjusted_abi_align: Align(4 bytes), @@ -88,7 +90,9 @@ error: layout_of(Result<[u32; 0], bool>) = Layout { }, ), variants: Single { - index: 1, + index: Some( + 1, + ), }, max_repr_align: None, unadjusted_abi_align: Align(1 bytes), @@ -160,7 +164,9 @@ error: layout_of(MultipleAlignments) = Layout { }, largest_niche: None, variants: Single { - index: 0, + index: Some( + 0, + ), }, max_repr_align: None, unadjusted_abi_align: Align(2 bytes), @@ -184,7 +190,9 @@ error: layout_of(MultipleAlignments) = Layout { }, largest_niche: None, variants: Single { - index: 1, + index: Some( + 1, + ), }, max_repr_align: None, unadjusted_abi_align: Align(4 bytes), @@ -217,7 +225,9 @@ error: layout_of(MultipleAlignments) = Layout { }, ), variants: Single { - index: 2, + index: Some( + 2, + ), }, max_repr_align: None, unadjusted_abi_align: Align(1 bytes), @@ -289,7 +299,9 @@ error: layout_of(Result<[u32; 0], Packed>>) = Layout { }, largest_niche: None, variants: Single { - index: 0, + index: Some( + 0, + ), }, max_repr_align: None, unadjusted_abi_align: Align(4 bytes), @@ -322,7 +334,9 @@ error: layout_of(Result<[u32; 0], Packed>>) = Layout { }, ), variants: Single { - index: 1, + index: Some( + 1, + ), }, max_repr_align: None, unadjusted_abi_align: Align(1 bytes), @@ -398,7 +412,9 @@ error: layout_of(Result<[u32; 0], Packed>) = Layout { }, largest_niche: None, variants: Single { - index: 0, + index: Some( + 0, + ), }, max_repr_align: None, unadjusted_abi_align: Align(4 bytes), @@ -431,7 +447,9 @@ error: layout_of(Result<[u32; 0], Packed>) = Layout { }, ), variants: Single { - index: 1, + index: Some( + 1, + ), }, max_repr_align: None, unadjusted_abi_align: Align(1 bytes), diff --git a/tests/ui/repr/repr-c-dead-variants.aarch64-unknown-linux-gnu.stderr b/tests/ui/repr/repr-c-dead-variants.aarch64-unknown-linux-gnu.stderr index 64a0cb7f31a1..08fd4237eeba 100644 --- a/tests/ui/repr/repr-c-dead-variants.aarch64-unknown-linux-gnu.stderr +++ b/tests/ui/repr/repr-c-dead-variants.aarch64-unknown-linux-gnu.stderr @@ -51,7 +51,9 @@ error: layout_of(Univariant) = Layout { }, largest_niche: None, variants: Single { - index: 0, + index: Some( + 0, + ), }, max_repr_align: None, unadjusted_abi_align: Align(4 bytes), @@ -133,7 +135,9 @@ error: layout_of(TwoVariants) = Layout { }, largest_niche: None, variants: Single { - index: 0, + index: Some( + 0, + ), }, max_repr_align: None, unadjusted_abi_align: Align(4 bytes), @@ -169,7 +173,9 @@ error: layout_of(TwoVariants) = Layout { }, largest_niche: None, variants: Single { - index: 1, + index: Some( + 1, + ), }, max_repr_align: None, unadjusted_abi_align: Align(4 bytes), @@ -241,7 +247,9 @@ error: layout_of(DeadBranchHasOtherField) = Layout { }, largest_niche: None, variants: Single { - index: 0, + index: Some( + 0, + ), }, max_repr_align: Some( Align(8 bytes), @@ -267,7 +275,9 @@ error: layout_of(DeadBranchHasOtherField) = Layout { }, largest_niche: None, variants: Single { - index: 1, + index: Some( + 1, + ), }, max_repr_align: None, unadjusted_abi_align: Align(8 bytes), diff --git a/tests/ui/repr/repr-c-dead-variants.armebv7r-none-eabi.stderr b/tests/ui/repr/repr-c-dead-variants.armebv7r-none-eabi.stderr index 5c4daa6d5197..473268cac1a6 100644 --- a/tests/ui/repr/repr-c-dead-variants.armebv7r-none-eabi.stderr +++ b/tests/ui/repr/repr-c-dead-variants.armebv7r-none-eabi.stderr @@ -51,7 +51,9 @@ error: layout_of(Univariant) = Layout { }, largest_niche: None, variants: Single { - index: 0, + index: Some( + 0, + ), }, max_repr_align: None, unadjusted_abi_align: Align(1 bytes), @@ -133,7 +135,9 @@ error: layout_of(TwoVariants) = Layout { }, largest_niche: None, variants: Single { - index: 0, + index: Some( + 0, + ), }, max_repr_align: None, unadjusted_abi_align: Align(1 bytes), @@ -169,7 +173,9 @@ error: layout_of(TwoVariants) = Layout { }, largest_niche: None, variants: Single { - index: 1, + index: Some( + 1, + ), }, max_repr_align: None, unadjusted_abi_align: Align(1 bytes), @@ -241,7 +247,9 @@ error: layout_of(DeadBranchHasOtherField) = Layout { }, largest_niche: None, variants: Single { - index: 0, + index: Some( + 0, + ), }, max_repr_align: Some( Align(8 bytes), @@ -267,7 +275,9 @@ error: layout_of(DeadBranchHasOtherField) = Layout { }, largest_niche: None, variants: Single { - index: 1, + index: Some( + 1, + ), }, max_repr_align: None, unadjusted_abi_align: Align(8 bytes), diff --git a/tests/ui/repr/repr-c-dead-variants.i686-pc-windows-msvc.stderr b/tests/ui/repr/repr-c-dead-variants.i686-pc-windows-msvc.stderr index 64a0cb7f31a1..08fd4237eeba 100644 --- a/tests/ui/repr/repr-c-dead-variants.i686-pc-windows-msvc.stderr +++ b/tests/ui/repr/repr-c-dead-variants.i686-pc-windows-msvc.stderr @@ -51,7 +51,9 @@ error: layout_of(Univariant) = Layout { }, largest_niche: None, variants: Single { - index: 0, + index: Some( + 0, + ), }, max_repr_align: None, unadjusted_abi_align: Align(4 bytes), @@ -133,7 +135,9 @@ error: layout_of(TwoVariants) = Layout { }, largest_niche: None, variants: Single { - index: 0, + index: Some( + 0, + ), }, max_repr_align: None, unadjusted_abi_align: Align(4 bytes), @@ -169,7 +173,9 @@ error: layout_of(TwoVariants) = Layout { }, largest_niche: None, variants: Single { - index: 1, + index: Some( + 1, + ), }, max_repr_align: None, unadjusted_abi_align: Align(4 bytes), @@ -241,7 +247,9 @@ error: layout_of(DeadBranchHasOtherField) = Layout { }, largest_niche: None, variants: Single { - index: 0, + index: Some( + 0, + ), }, max_repr_align: Some( Align(8 bytes), @@ -267,7 +275,9 @@ error: layout_of(DeadBranchHasOtherField) = Layout { }, largest_niche: None, variants: Single { - index: 1, + index: Some( + 1, + ), }, max_repr_align: None, unadjusted_abi_align: Align(8 bytes), diff --git a/tests/ui/repr/repr-c-dead-variants.x86_64-unknown-linux-gnu.stderr b/tests/ui/repr/repr-c-dead-variants.x86_64-unknown-linux-gnu.stderr index 64a0cb7f31a1..08fd4237eeba 100644 --- a/tests/ui/repr/repr-c-dead-variants.x86_64-unknown-linux-gnu.stderr +++ b/tests/ui/repr/repr-c-dead-variants.x86_64-unknown-linux-gnu.stderr @@ -51,7 +51,9 @@ error: layout_of(Univariant) = Layout { }, largest_niche: None, variants: Single { - index: 0, + index: Some( + 0, + ), }, max_repr_align: None, unadjusted_abi_align: Align(4 bytes), @@ -133,7 +135,9 @@ error: layout_of(TwoVariants) = Layout { }, largest_niche: None, variants: Single { - index: 0, + index: Some( + 0, + ), }, max_repr_align: None, unadjusted_abi_align: Align(4 bytes), @@ -169,7 +173,9 @@ error: layout_of(TwoVariants) = Layout { }, largest_niche: None, variants: Single { - index: 1, + index: Some( + 1, + ), }, max_repr_align: None, unadjusted_abi_align: Align(4 bytes), @@ -241,7 +247,9 @@ error: layout_of(DeadBranchHasOtherField) = Layout { }, largest_niche: None, variants: Single { - index: 0, + index: Some( + 0, + ), }, max_repr_align: Some( Align(8 bytes), @@ -267,7 +275,9 @@ error: layout_of(DeadBranchHasOtherField) = Layout { }, largest_niche: None, variants: Single { - index: 1, + index: Some( + 1, + ), }, max_repr_align: None, unadjusted_abi_align: Align(8 bytes), diff --git a/tests/ui/repr/repr-c-int-dead-variants.stderr b/tests/ui/repr/repr-c-int-dead-variants.stderr index 75005a64523a..1200f120d37b 100644 --- a/tests/ui/repr/repr-c-int-dead-variants.stderr +++ b/tests/ui/repr/repr-c-int-dead-variants.stderr @@ -51,7 +51,9 @@ error: layout_of(UnivariantU8) = Layout { }, largest_niche: None, variants: Single { - index: 0, + index: Some( + 0, + ), }, max_repr_align: None, unadjusted_abi_align: Align(1 bytes), @@ -133,7 +135,9 @@ error: layout_of(TwoVariantsU8) = Layout { }, largest_niche: None, variants: Single { - index: 0, + index: Some( + 0, + ), }, max_repr_align: None, unadjusted_abi_align: Align(1 bytes), @@ -169,7 +173,9 @@ error: layout_of(TwoVariantsU8) = Layout { }, largest_niche: None, variants: Single { - index: 1, + index: Some( + 1, + ), }, max_repr_align: None, unadjusted_abi_align: Align(1 bytes), @@ -241,7 +247,9 @@ error: layout_of(DeadBranchHasOtherFieldU8) = Layout { }, largest_niche: None, variants: Single { - index: 0, + index: Some( + 0, + ), }, max_repr_align: Some( Align(8 bytes), @@ -267,7 +275,9 @@ error: layout_of(DeadBranchHasOtherFieldU8) = Layout { }, largest_niche: None, variants: Single { - index: 1, + index: Some( + 1, + ), }, max_repr_align: None, unadjusted_abi_align: Align(8 bytes), diff --git a/tests/ui/type/pattern_types/range_patterns.stderr b/tests/ui/type/pattern_types/range_patterns.stderr index 0eed7c2ce1ce..9954471968de 100644 --- a/tests/ui/type/pattern_types/range_patterns.stderr +++ b/tests/ui/type/pattern_types/range_patterns.stderr @@ -32,7 +32,9 @@ error: layout_of(NonZero) = Layout { }, ), variants: Single { - index: 0, + index: Some( + 0, + ), }, max_repr_align: None, unadjusted_abi_align: Align(4 bytes), @@ -69,7 +71,9 @@ error: layout_of((u32) is 1..=) = Layout { }, ), variants: Single { - index: 0, + index: Some( + 0, + ), }, max_repr_align: None, unadjusted_abi_align: Align(4 bytes), @@ -133,7 +137,9 @@ error: layout_of(Option<(u32) is 1..=>) = Layout { }, largest_niche: None, variants: Single { - index: 0, + index: Some( + 0, + ), }, max_repr_align: None, unadjusted_abi_align: Align(1 bytes), @@ -172,7 +178,9 @@ error: layout_of(Option<(u32) is 1..=>) = Layout { }, ), variants: Single { - index: 1, + index: Some( + 1, + ), }, max_repr_align: None, unadjusted_abi_align: Align(4 bytes), @@ -241,7 +249,9 @@ error: layout_of(Option>) = Layout { }, largest_niche: None, variants: Single { - index: 0, + index: Some( + 0, + ), }, max_repr_align: None, unadjusted_abi_align: Align(1 bytes), @@ -280,7 +290,9 @@ error: layout_of(Option>) = Layout { }, ), variants: Single { - index: 1, + index: Some( + 1, + ), }, max_repr_align: None, unadjusted_abi_align: Align(4 bytes), @@ -329,7 +341,9 @@ error: layout_of(NonZeroU32New) = Layout { }, ), variants: Single { - index: 0, + index: Some( + 0, + ), }, max_repr_align: None, unadjusted_abi_align: Align(4 bytes), From e023590de407f417e0f3da675a372eca7acf60c6 Mon Sep 17 00:00:00 2001 From: Ralf Jung Date: Sun, 1 Dec 2024 17:33:01 +0100 Subject: [PATCH 45/92] make no-variant types a dedicated Variants variant --- compiler/rustc_abi/src/callconv.rs | 2 +- compiler/rustc_abi/src/layout.rs | 19 ++-- compiler/rustc_abi/src/lib.rs | 10 +- .../src/discriminant.rs | 7 +- compiler/rustc_codegen_gcc/src/type_of.rs | 6 +- .../src/debuginfo/metadata/enums/cpp_like.rs | 26 +++-- .../src/debuginfo/metadata/enums/mod.rs | 2 +- .../src/debuginfo/metadata/enums/native.rs | 4 +- compiler/rustc_codegen_llvm/src/type_of.rs | 6 +- .../rustc_codegen_ssa/src/debuginfo/mod.rs | 4 +- compiler/rustc_codegen_ssa/src/mir/place.rs | 8 +- .../src/interpret/discriminant.rs | 8 +- .../src/interpret/validity.rs | 9 +- .../rustc_const_eval/src/interpret/visitor.rs | 4 +- .../src/util/check_validity_requirement.rs | 1 + compiler/rustc_middle/src/ty/layout.rs | 24 ++--- .../rustc_mir_transform/src/large_enums.rs | 2 +- .../src/unreachable_enum_branching.rs | 4 +- .../rustc_smir/src/rustc_smir/convert/abi.rs | 7 +- .../rustc_target/src/callconv/loongarch.rs | 2 +- compiler/rustc_target/src/callconv/riscv.rs | 2 +- compiler/rustc_target/src/callconv/x86_64.rs | 2 +- compiler/rustc_transmute/src/layout/tree.rs | 15 ++- compiler/rustc_ty_utils/src/layout.rs | 26 +++-- .../rustc_ty_utils/src/layout/invariant.rs | 8 +- compiler/stable_mir/src/abi.rs | 4 +- src/tools/miri/src/helpers.rs | 2 +- .../rust-analyzer/crates/hir-ty/src/layout.rs | 8 +- .../crates/hir-ty/src/mir/eval.rs | 8 +- .../rust-analyzer/crates/hir-ty/src/utils.rs | 3 +- tests/ui/abi/c-zst.aarch64-darwin.stderr | 8 +- tests/ui/abi/c-zst.powerpc-linux.stderr | 8 +- tests/ui/abi/c-zst.s390x-linux.stderr | 8 +- tests/ui/abi/c-zst.sparc64-linux.stderr | 8 +- tests/ui/abi/c-zst.x86_64-linux.stderr | 8 +- .../ui/abi/c-zst.x86_64-pc-windows-gnu.stderr | 8 +- tests/ui/abi/debug.stderr | 96 +++++-------------- tests/ui/abi/sysv64-zst.stderr | 8 +- tests/ui/abi/win64-zst.x86_64-linux.stderr | 8 +- .../abi/win64-zst.x86_64-windows-gnu.stderr | 8 +- .../abi/win64-zst.x86_64-windows-msvc.stderr | 8 +- tests/ui/layout/debug.stderr | 64 ++++--------- tests/ui/layout/hexagon-enum.stderr | 20 +--- ...-scalarpair-payload-might-be-uninit.stderr | 48 +++------- .../issue-96185-overaligned-enum.stderr | 16 +--- tests/ui/layout/thumb-enum.stderr | 20 +--- .../layout/zero-sized-array-enum-niche.stderr | 36 ++----- ...-variants.aarch64-unknown-linux-gnu.stderr | 20 +--- ...-c-dead-variants.armebv7r-none-eabi.stderr | 20 +--- ...-dead-variants.i686-pc-windows-msvc.stderr | 20 +--- ...d-variants.x86_64-unknown-linux-gnu.stderr | 20 +--- tests/ui/repr/repr-c-int-dead-variants.stderr | 20 +--- .../type/pattern_types/range_patterns.stderr | 28 ++---- 53 files changed, 246 insertions(+), 495 deletions(-) diff --git a/compiler/rustc_abi/src/callconv.rs b/compiler/rustc_abi/src/callconv.rs index ee63e46e88c1..400395f99ff0 100644 --- a/compiler/rustc_abi/src/callconv.rs +++ b/compiler/rustc_abi/src/callconv.rs @@ -206,7 +206,7 @@ impl<'a, Ty> TyAndLayout<'a, Ty> { let (mut result, mut total) = from_fields_at(*self, Size::ZERO)?; match &self.variants { - abi::Variants::Single { .. } => {} + abi::Variants::Single { .. } | abi::Variants::Empty => {} abi::Variants::Multiple { variants, .. } => { // Treat enum variants like union members. // HACK(eddyb) pretend the `enum` field (discriminant) diff --git a/compiler/rustc_abi/src/layout.rs b/compiler/rustc_abi/src/layout.rs index f2b50ae408e9..226a46f605cc 100644 --- a/compiler/rustc_abi/src/layout.rs +++ b/compiler/rustc_abi/src/layout.rs @@ -120,7 +120,7 @@ impl LayoutCalculator { .max_by_key(|niche| niche.available(dl)); LayoutData { - variants: Variants::Single { index: Some(VariantIdx::new(0)) }, + variants: Variants::Single { index: VariantIdx::new(0) }, fields: FieldsShape::Arbitrary { offsets: [Size::ZERO, b_offset].into(), memory_index: [0, 1].into(), @@ -213,8 +213,9 @@ impl LayoutCalculator { &self, ) -> LayoutData { let dl = self.cx.data_layout(); + // This is also used for uninhabited enums, so we use `Variants::Empty`. LayoutData { - variants: Variants::Single { index: None }, + variants: Variants::Empty, fields: FieldsShape::Primitive, backend_repr: BackendRepr::Uninhabited, largest_niche: None, @@ -385,7 +386,7 @@ impl LayoutCalculator { }; Ok(LayoutData { - variants: Variants::Single { index: Some(only_variant_idx) }, + variants: Variants::Single { index: only_variant_idx }, fields: FieldsShape::Union(union_field_count), backend_repr: abi, largest_niche: None, @@ -424,7 +425,7 @@ impl LayoutCalculator { }; let mut st = self.univariant(&variants[v], repr, kind)?; - st.variants = Variants::Single { index: Some(v) }; + st.variants = Variants::Single { index: v }; if is_unsafe_cell { let hide_niches = |scalar: &mut _| match scalar { @@ -543,7 +544,7 @@ impl LayoutCalculator { .iter_enumerated() .map(|(j, v)| { let mut st = self.univariant(v, repr, StructKind::AlwaysSized).ok()?; - st.variants = Variants::Single { index: Some(j) }; + st.variants = Variants::Single { index: j }; align = align.max(st.align); max_repr_align = max_repr_align.max(st.max_repr_align); @@ -736,7 +737,7 @@ impl LayoutCalculator { repr, StructKind::Prefixed(min_ity.size(), prefix_align), )?; - st.variants = Variants::Single { index: Some(i) }; + st.variants = Variants::Single { index: i }; // Find the first field we can't move later // to make room for a larger discriminant. for field_idx in st.fields.index_by_increasing_offset() { @@ -1004,8 +1005,8 @@ impl LayoutCalculator { Variants::Multiple { tag, tag_encoding, tag_field, .. } => { Variants::Multiple { tag, tag_encoding, tag_field, variants: best_layout.variants } } - Variants::Single { .. } => { - panic!("encountered a single-variant enum during multi-variant layout") + Variants::Single { .. } | Variants::Empty => { + panic!("encountered a single-variant or empty enum during multi-variant layout") } }; Ok(best_layout.layout) @@ -1344,7 +1345,7 @@ impl LayoutCalculator { }; Ok(LayoutData { - variants: Variants::Single { index: Some(VariantIdx::new(0)) }, + variants: Variants::Single { index: VariantIdx::new(0) }, fields: FieldsShape::Arbitrary { offsets, memory_index }, backend_repr: abi, largest_niche, diff --git a/compiler/rustc_abi/src/lib.rs b/compiler/rustc_abi/src/lib.rs index 242e2cadd18a..ca15f7d99205 100644 --- a/compiler/rustc_abi/src/lib.rs +++ b/compiler/rustc_abi/src/lib.rs @@ -1504,11 +1504,13 @@ impl BackendRepr { #[derive(PartialEq, Eq, Hash, Clone, Debug)] #[cfg_attr(feature = "nightly", derive(HashStable_Generic))] pub enum Variants { + /// A type with no valid variants. Must be uninhabited. + Empty, + /// Single enum variants, structs/tuples, unions, and all non-ADTs. Single { - /// Always `Some(0)` for types without variants (i.e., everything except for `!`, enums, and - /// generators). `None` indicates an uninhabited type; this is used for zero-variant enums. - index: Option, + /// Always `0` for types that cannot have multiple variants. + index: VariantIdx, }, /// Enum-likes with more than one variant: each variant comes with @@ -1706,7 +1708,7 @@ impl LayoutData { let size = scalar.size(cx); let align = scalar.align(cx); LayoutData { - variants: Variants::Single { index: Some(VariantIdx::new(0)) }, + variants: Variants::Single { index: VariantIdx::new(0) }, fields: FieldsShape::Primitive, backend_repr: BackendRepr::Scalar(scalar), largest_niche, diff --git a/compiler/rustc_codegen_cranelift/src/discriminant.rs b/compiler/rustc_codegen_cranelift/src/discriminant.rs index 055063c876fa..4d0d5dc60eba 100644 --- a/compiler/rustc_codegen_cranelift/src/discriminant.rs +++ b/compiler/rustc_codegen_cranelift/src/discriminant.rs @@ -18,8 +18,9 @@ pub(crate) fn codegen_set_discriminant<'tcx>( return; } match layout.variants { + Variants::Empty => unreachable!("we already handled uninhabited types"), Variants::Single { index } => { - assert_eq!(index.unwrap(), variant_index); + assert_eq!(index, variant_index); } Variants::Multiple { tag: _, @@ -85,11 +86,11 @@ pub(crate) fn codegen_get_discriminant<'tcx>( } let (tag_scalar, tag_field, tag_encoding) = match &layout.variants { + Variants::Empty => unreachable!("we already handled uninhabited types"), Variants::Single { index } => { - let index = index.unwrap(); let discr_val = layout .ty - .discriminant_for_variant(fx.tcx, index) + .discriminant_for_variant(fx.tcx, *index) .map_or(u128::from(index.as_u32()), |discr| discr.val); let val = match dest_layout.ty.kind() { diff --git a/compiler/rustc_codegen_gcc/src/type_of.rs b/compiler/rustc_codegen_gcc/src/type_of.rs index 426d28f4ed78..0efdf36da485 100644 --- a/compiler/rustc_codegen_gcc/src/type_of.rs +++ b/compiler/rustc_codegen_gcc/src/type_of.rs @@ -99,14 +99,14 @@ fn uncached_gcc_type<'gcc, 'tcx>( if !cx.sess().fewer_names() => { let mut name = with_no_trimmed_paths!(layout.ty.to_string()); - if let (&ty::Adt(def, _), &Variants::Single { index: Some(index) }) = + if let (&ty::Adt(def, _), &Variants::Single { index }) = (layout.ty.kind(), &layout.variants) { if def.is_enum() && !def.variants().is_empty() { write!(&mut name, "::{}", def.variant(index).name).unwrap(); } } - if let (&ty::Coroutine(_, _), &Variants::Single { index: Some(index) }) = + if let (&ty::Coroutine(_, _), &Variants::Single { index }) = (layout.ty.kind(), &layout.variants) { write!(&mut name, "::{}", ty::CoroutineArgs::variant_name(index)).unwrap(); @@ -230,7 +230,7 @@ impl<'tcx> LayoutGccExt<'tcx> for TyAndLayout<'tcx> { // Check the cache. let variant_index = match self.variants { - Variants::Single { index } => index, + Variants::Single { index } => Some(index), _ => None, }; let cached_type = cx.types.borrow().get(&(self.ty, variant_index)).cloned(); diff --git a/compiler/rustc_codegen_llvm/src/debuginfo/metadata/enums/cpp_like.rs b/compiler/rustc_codegen_llvm/src/debuginfo/metadata/enums/cpp_like.rs index 8ec83fa7c92d..12a46184d108 100644 --- a/compiler/rustc_codegen_llvm/src/debuginfo/metadata/enums/cpp_like.rs +++ b/compiler/rustc_codegen_llvm/src/debuginfo/metadata/enums/cpp_like.rs @@ -212,21 +212,18 @@ pub(super) fn build_enum_type_di_node<'ll, 'tcx>( ), |cx, enum_type_di_node| { match enum_type_and_layout.variants { - Variants::Single { index: variant_index } => { - let Some(variant_index) = variant_index else { - // Uninhabited enums have Variants::Single. We don't generate - // any members for them. - return smallvec![]; - }; - - build_single_variant_union_fields( - cx, - enum_adt_def, - enum_type_and_layout, - enum_type_di_node, - variant_index, - ) + Variants::Empty => { + // Uninhabited enums have Variants::Single. We don't generate + // any members for them. + return smallvec![]; } + Variants::Single { index: variant_index } => build_single_variant_union_fields( + cx, + enum_adt_def, + enum_type_and_layout, + enum_type_di_node, + variant_index, + ), Variants::Multiple { tag_encoding: TagEncoding::Direct, ref variants, @@ -303,6 +300,7 @@ pub(super) fn build_coroutine_di_node<'ll, 'tcx>( ) } Variants::Single { .. } + | Variants::Empty | Variants::Multiple { tag_encoding: TagEncoding::Niche { .. }, .. } => { bug!( "Encountered coroutine with non-direct-tag layout: {:?}", diff --git a/compiler/rustc_codegen_llvm/src/debuginfo/metadata/enums/mod.rs b/compiler/rustc_codegen_llvm/src/debuginfo/metadata/enums/mod.rs index 65ab22ad89e8..9f6a5cc89e02 100644 --- a/compiler/rustc_codegen_llvm/src/debuginfo/metadata/enums/mod.rs +++ b/compiler/rustc_codegen_llvm/src/debuginfo/metadata/enums/mod.rs @@ -392,7 +392,7 @@ fn compute_discriminant_value<'ll, 'tcx>( variant_index: VariantIdx, ) -> DiscrResult { match enum_type_and_layout.layout.variants() { - &Variants::Single { .. } => DiscrResult::NoDiscriminant, + &Variants::Single { .. } | &Variants::Empty => DiscrResult::NoDiscriminant, &Variants::Multiple { tag_encoding: TagEncoding::Direct, .. } => DiscrResult::Value( enum_type_and_layout.ty.discriminant_for_variant(cx.tcx, variant_index).unwrap().val, ), diff --git a/compiler/rustc_codegen_llvm/src/debuginfo/metadata/enums/native.rs b/compiler/rustc_codegen_llvm/src/debuginfo/metadata/enums/native.rs index 241bf167a81a..11824398f243 100644 --- a/compiler/rustc_codegen_llvm/src/debuginfo/metadata/enums/native.rs +++ b/compiler/rustc_codegen_llvm/src/debuginfo/metadata/enums/native.rs @@ -358,8 +358,8 @@ fn build_discr_member_di_node<'ll, 'tcx>( let containing_scope = enum_or_coroutine_type_di_node; match enum_or_coroutine_type_and_layout.layout.variants() { - // A single-variant enum has no discriminant. - &Variants::Single { .. } => None, + // A single-variant or no-variant enum has no discriminant. + &Variants::Single { .. } | &Variants::Empty => None, &Variants::Multiple { tag_field, .. } => { let tag_base_type = tag_base_type(cx.tcx, enum_or_coroutine_type_and_layout); diff --git a/compiler/rustc_codegen_llvm/src/type_of.rs b/compiler/rustc_codegen_llvm/src/type_of.rs index 833a687fe742..b0b6da869da6 100644 --- a/compiler/rustc_codegen_llvm/src/type_of.rs +++ b/compiler/rustc_codegen_llvm/src/type_of.rs @@ -35,14 +35,14 @@ fn uncached_llvm_type<'a, 'tcx>( if !cx.sess().fewer_names() => { let mut name = with_no_visible_paths!(with_no_trimmed_paths!(layout.ty.to_string())); - if let (&ty::Adt(def, _), &Variants::Single { index: Some(index) }) = + if let (&ty::Adt(def, _), &Variants::Single { index }) = (layout.ty.kind(), &layout.variants) { if def.is_enum() { write!(&mut name, "::{}", def.variant(index).name).unwrap(); } } - if let (&ty::Coroutine(_, _), &Variants::Single { index: Some(index) }) = + if let (&ty::Coroutine(_, _), &Variants::Single { index }) = (layout.ty.kind(), &layout.variants) { write!(&mut name, "::{}", ty::CoroutineArgs::variant_name(index)).unwrap(); @@ -216,7 +216,7 @@ impl<'tcx> LayoutLlvmExt<'tcx> for TyAndLayout<'tcx> { // Check the cache. let variant_index = match self.variants { - Variants::Single { index } => index, + Variants::Single { index } => Some(index), _ => None, }; if let Some(llty) = cx.type_lowering.borrow().get(&(self.ty, variant_index)) { diff --git a/compiler/rustc_codegen_ssa/src/debuginfo/mod.rs b/compiler/rustc_codegen_ssa/src/debuginfo/mod.rs index 88d36b19da43..7c62c03d574c 100644 --- a/compiler/rustc_codegen_ssa/src/debuginfo/mod.rs +++ b/compiler/rustc_codegen_ssa/src/debuginfo/mod.rs @@ -65,8 +65,8 @@ fn tag_base_type_opt<'tcx>( }); match enum_type_and_layout.layout.variants() { - // A single-variant enum has no discriminant. - Variants::Single { .. } => None, + // A single-variant or no-variant enum has no discriminant. + Variants::Single { .. } | Variants::Empty => None, Variants::Multiple { tag_encoding: TagEncoding::Niche { .. }, tag, .. } => { // Niche tags are always normalized to unsized integers of the correct size. diff --git a/compiler/rustc_codegen_ssa/src/mir/place.rs b/compiler/rustc_codegen_ssa/src/mir/place.rs index cef3d8255a0e..c634f864ffb8 100644 --- a/compiler/rustc_codegen_ssa/src/mir/place.rs +++ b/compiler/rustc_codegen_ssa/src/mir/place.rs @@ -243,8 +243,8 @@ impl<'a, 'tcx, V: CodegenObject> PlaceRef<'tcx, V> { return bx.cx().const_poison(cast_to); } let (tag_scalar, tag_encoding, tag_field) = match self.layout.variants { + Variants::Empty => unreachable!("we already handled uninhabited types"), Variants::Single { index } => { - let index = index.unwrap(); // we already checked `is_uninhabited` let discr_val = self .layout .ty @@ -366,9 +366,9 @@ impl<'a, 'tcx, V: CodegenObject> PlaceRef<'tcx, V> { return; } match self.layout.variants { - Variants::Single { index } => { - assert_eq!(index.unwrap(), variant_index); - } + Variants::Empty => unreachable!("we already handled uninhabited types"), + Variants::Single { index } => assert_eq!(index, variant_index), + Variants::Multiple { tag_encoding: TagEncoding::Direct, tag_field, .. } => { let ptr = self.project_field(bx, tag_field); let to = diff --git a/compiler/rustc_const_eval/src/interpret/discriminant.rs b/compiler/rustc_const_eval/src/interpret/discriminant.rs index 6cfd1613229b..2f0b1cb6d1ee 100644 --- a/compiler/rustc_const_eval/src/interpret/discriminant.rs +++ b/compiler/rustc_const_eval/src/interpret/discriminant.rs @@ -65,15 +65,18 @@ impl<'tcx, M: Machine<'tcx>> InterpCx<'tcx, M> { // We use "tag" to refer to how the discriminant is encoded in memory, which can be either // straight-forward (`TagEncoding::Direct`) or with a niche (`TagEncoding::Niche`). let (tag_scalar_layout, tag_encoding, tag_field) = match op.layout().variants { + Variants::Empty => { + throw_ub!(UninhabitedEnumVariantRead(None)); + } Variants::Single { index } => { if op.layout().is_uninhabited() { // For consistency with `write_discriminant`, and to make sure that // `project_downcast` cannot fail due to strange layouts, we declare immediate UB // for uninhabited enums. - throw_ub!(UninhabitedEnumVariantRead(None)); + throw_ub!(UninhabitedEnumVariantRead(Some(index))); } // Since the type is inhabited, there must be an index. - return interp_ok(index.unwrap()); + return interp_ok(index); } Variants::Multiple { tag, ref tag_encoding, tag_field, .. } => { (tag, tag_encoding, tag_field) @@ -238,6 +241,7 @@ impl<'tcx, M: Machine<'tcx>> InterpCx<'tcx, M> { } match layout.variants { + abi::Variants::Empty => unreachable!("we already handled uninhabited types"), abi::Variants::Single { .. } => { // The tag of a `Single` enum is like the tag of the niched // variant: there's no tag as the discriminant is encoded diff --git a/compiler/rustc_const_eval/src/interpret/validity.rs b/compiler/rustc_const_eval/src/interpret/validity.rs index 832183b42dc4..6f101395ccf4 100644 --- a/compiler/rustc_const_eval/src/interpret/validity.rs +++ b/compiler/rustc_const_eval/src/interpret/validity.rs @@ -302,7 +302,7 @@ impl<'rt, 'tcx, M: Machine<'tcx>> ValidityVisitor<'rt, 'tcx, M> { }; } } - Variants::Single { .. } => {} + Variants::Single { .. } | Variants::Empty => {} } // Now we know we are projecting to a field, so figure out which one. @@ -342,10 +342,9 @@ impl<'rt, 'tcx, M: Machine<'tcx>> ValidityVisitor<'rt, 'tcx, M> { match layout.variants { Variants::Single { index } => { // Inside a variant - PathElem::Field( - def.variant(index.unwrap()).fields[FieldIdx::from_usize(field)].name, - ) + PathElem::Field(def.variant(index).fields[FieldIdx::from_usize(field)].name) } + Variants::Empty => panic!("there is no field in Variants::Empty types"), Variants::Multiple { .. } => bug!("we handled variants above"), } } @@ -1012,7 +1011,7 @@ impl<'rt, 'tcx, M: Machine<'tcx>> ValidityVisitor<'rt, 'tcx, M> { } // Don't forget potential other variants. match &layout.variants { - Variants::Single { .. } => { + Variants::Single { .. } | Variants::Empty => { // Fully handled above. } Variants::Multiple { variants, .. } => { diff --git a/compiler/rustc_const_eval/src/interpret/visitor.rs b/compiler/rustc_const_eval/src/interpret/visitor.rs index 76ab0bb544f0..3647c109a6ed 100644 --- a/compiler/rustc_const_eval/src/interpret/visitor.rs +++ b/compiler/rustc_const_eval/src/interpret/visitor.rs @@ -218,8 +218,8 @@ pub trait ValueVisitor<'tcx, M: Machine<'tcx>>: Sized { // recurse with the inner type self.visit_variant(v, idx, &inner)?; } - // For single-variant layouts, we already did anything there is to do. - Variants::Single { .. } => {} + // For single-variant layouts, we already did everything there is to do. + Variants::Single { .. } | Variants::Empty => {} } interp_ok(()) diff --git a/compiler/rustc_const_eval/src/util/check_validity_requirement.rs b/compiler/rustc_const_eval/src/util/check_validity_requirement.rs index 651a797e97cf..a729d9325c84 100644 --- a/compiler/rustc_const_eval/src/util/check_validity_requirement.rs +++ b/compiler/rustc_const_eval/src/util/check_validity_requirement.rs @@ -155,6 +155,7 @@ fn check_validity_requirement_lax<'tcx>( } match &this.variants { + Variants::Empty => return Ok(false), Variants::Single { .. } => { // All fields of this single variant have already been checked above, there is nothing // else to do. diff --git a/compiler/rustc_middle/src/ty/layout.rs b/compiler/rustc_middle/src/ty/layout.rs index 5f7b30b5d041..367b0c07f9bc 100644 --- a/compiler/rustc_middle/src/ty/layout.rs +++ b/compiler/rustc_middle/src/ty/layout.rs @@ -734,23 +734,22 @@ where let layout = match this.variants { Variants::Single { index } // If all variants but one are uninhabited, the variant layout is the enum layout. - if index == Some(variant_index) && - // Don't confuse variants of uninhabited enums with the enum itself. - // For more details see https://github.com/rust-lang/rust/issues/69763. - this.fields != FieldsShape::Primitive => + if index == variant_index => { this.layout } - Variants::Single { index } => { - // `Single` variant enums *can* have other variants, but those are uninhabited. + Variants::Single { .. } | Variants::Empty => { + // Single-variant and no-variant enums *can* have other variants, but those are + // uninhabited. Produce a layout that has the right fields for that variant, so that + // the rest of the compiler can project fields etc as usual. let tcx = cx.tcx(); let typing_env = cx.typing_env(); // Deny calling for_variant more than once for non-Single enums. if let Ok(original_layout) = tcx.layout_of(typing_env.as_query_input(this.ty)) { - assert_eq!(original_layout.variants, Variants::Single { index }); + assert_eq!(original_layout.variants, this.variants); } let fields = match this.ty.kind() { @@ -760,7 +759,7 @@ where _ => bug!("`ty_and_layout_for_variant` on unexpected type {}", this.ty), }; tcx.mk_layout(LayoutData { - variants: Variants::Single { index: Some(variant_index) }, + variants: Variants::Single { index: variant_index }, fields: match NonZero::new(fields) { Some(fields) => FieldsShape::Union(fields), None => FieldsShape::Arbitrary { offsets: IndexVec::new(), memory_index: IndexVec::new() }, @@ -777,7 +776,7 @@ where Variants::Multiple { ref variants, .. } => cx.tcx().mk_layout(variants[variant_index].clone()), }; - assert_eq!(*layout.variants(), Variants::Single { index: Some(variant_index) }); + assert_eq!(*layout.variants(), Variants::Single { index: variant_index }); TyAndLayout { ty: this.ty, layout } } @@ -904,10 +903,11 @@ where ), ty::Coroutine(def_id, args) => match this.variants { + Variants::Empty => unreachable!(), Variants::Single { index } => TyMaybeWithLayout::Ty( args.as_coroutine() .state_tys(def_id, tcx) - .nth(index.unwrap().as_usize()) + .nth(index.as_usize()) .unwrap() .nth(i) .unwrap(), @@ -926,10 +926,10 @@ where ty::Adt(def, args) => { match this.variants { Variants::Single { index } => { - let field = - &def.variant(index.unwrap()).fields[FieldIdx::from_usize(i)]; + let field = &def.variant(index).fields[FieldIdx::from_usize(i)]; TyMaybeWithLayout::Ty(field.ty(tcx, args)) } + Variants::Empty => panic!("there is no field in Variants::Empty types"), // Discriminant field for enums (where applicable). Variants::Multiple { tag, .. } => { diff --git a/compiler/rustc_mir_transform/src/large_enums.rs b/compiler/rustc_mir_transform/src/large_enums.rs index 8be5a63d0087..490e7dd8f7e0 100644 --- a/compiler/rustc_mir_transform/src/large_enums.rs +++ b/compiler/rustc_mir_transform/src/large_enums.rs @@ -216,7 +216,7 @@ impl EnumSizeOpt { }; let layout = tcx.layout_of(typing_env.as_query_input(ty)).ok()?; let variants = match &layout.variants { - Variants::Single { .. } => return None, + Variants::Single { .. } | Variants::Empty => return None, Variants::Multiple { tag_encoding: TagEncoding::Niche { .. }, .. } => return None, Variants::Multiple { variants, .. } if variants.len() <= 1 => return None, diff --git a/compiler/rustc_mir_transform/src/unreachable_enum_branching.rs b/compiler/rustc_mir_transform/src/unreachable_enum_branching.rs index 0ce3955163b8..55dcad0680a9 100644 --- a/compiler/rustc_mir_transform/src/unreachable_enum_branching.rs +++ b/compiler/rustc_mir_transform/src/unreachable_enum_branching.rs @@ -54,11 +54,11 @@ fn variant_discriminants<'tcx>( tcx: TyCtxt<'tcx>, ) -> FxHashSet { match &layout.variants { - Variants::Single { index: None } => { + Variants::Empty => { // Uninhabited, no valid discriminant. FxHashSet::default() } - Variants::Single { index: Some(index) } => { + Variants::Single { index } => { let mut res = FxHashSet::default(); res.insert( ty.discriminant_for_variant(tcx, *index) diff --git a/compiler/rustc_smir/src/rustc_smir/convert/abi.rs b/compiler/rustc_smir/src/rustc_smir/convert/abi.rs index 2717f4ab62f2..b39a15a86332 100644 --- a/compiler/rustc_smir/src/rustc_smir/convert/abi.rs +++ b/compiler/rustc_smir/src/rustc_smir/convert/abi.rs @@ -164,9 +164,10 @@ impl<'tcx> Stable<'tcx> for rustc_abi::Variants) -> Self::T { match self { - rustc_abi::Variants::Single { index } => VariantsShape::Single { - index: index.unwrap_or(rustc_abi::VariantIdx::from_u32(0)).stable(tables), - }, + rustc_abi::Variants::Single { index } => { + VariantsShape::Single { index: index.stable(tables) } + } + rustc_abi::Variants::Empty => VariantsShape::Empty, rustc_abi::Variants::Multiple { tag, tag_encoding, tag_field, variants } => { VariantsShape::Multiple { tag: tag.stable(tables), diff --git a/compiler/rustc_target/src/callconv/loongarch.rs b/compiler/rustc_target/src/callconv/loongarch.rs index d1234c3cc91d..8bf61cb13376 100644 --- a/compiler/rustc_target/src/callconv/loongarch.rs +++ b/compiler/rustc_target/src/callconv/loongarch.rs @@ -116,7 +116,7 @@ where FieldsShape::Arbitrary { .. } => { match arg_layout.variants { abi::Variants::Multiple { .. } => return Err(CannotUseFpConv), - abi::Variants::Single { .. } => (), + abi::Variants::Single { .. } | abi::Variants::Empty => (), } for i in arg_layout.fields.index_by_increasing_offset() { let field = arg_layout.field(cx, i); diff --git a/compiler/rustc_target/src/callconv/riscv.rs b/compiler/rustc_target/src/callconv/riscv.rs index c0298edb5ab7..4d858392c979 100644 --- a/compiler/rustc_target/src/callconv/riscv.rs +++ b/compiler/rustc_target/src/callconv/riscv.rs @@ -122,7 +122,7 @@ where FieldsShape::Arbitrary { .. } => { match arg_layout.variants { abi::Variants::Multiple { .. } => return Err(CannotUseFpConv), - abi::Variants::Single { .. } => (), + abi::Variants::Single { .. } | abi::Variants::Empty => (), } for i in arg_layout.fields.index_by_increasing_offset() { let field = arg_layout.field(cx, i); diff --git a/compiler/rustc_target/src/callconv/x86_64.rs b/compiler/rustc_target/src/callconv/x86_64.rs index bd101b23ea16..37aecf323a18 100644 --- a/compiler/rustc_target/src/callconv/x86_64.rs +++ b/compiler/rustc_target/src/callconv/x86_64.rs @@ -65,7 +65,7 @@ where } match &layout.variants { - abi::Variants::Single { .. } => {} + abi::Variants::Single { .. } | abi::Variants::Empty => {} abi::Variants::Multiple { variants, .. } => { // Treat enum variants like union members. for variant_idx in variants.indices() { diff --git a/compiler/rustc_transmute/src/layout/tree.rs b/compiler/rustc_transmute/src/layout/tree.rs index 049f4734e7b5..4cc6292a3ee3 100644 --- a/compiler/rustc_transmute/src/layout/tree.rs +++ b/compiler/rustc_transmute/src/layout/tree.rs @@ -338,14 +338,11 @@ pub(crate) mod rustc { }; match layout.variants() { + Variants::Empty => Ok(Self::uninhabited()), Variants::Single { index } => { - if let Some(index) = index { - // `Variants::Single` on enums with variants denotes that - // the enum delegates its layout to the variant at `index`. - layout_of_variant(*index, None) - } else { - Ok(Self::uninhabited()) - } + // `Variants::Single` on enums with variants denotes that + // the enum delegates its layout to the variant at `index`. + layout_of_variant(*index, None) } Variants::Multiple { tag, tag_encoding, tag_field, .. } => { // `Variants::Multiple` denotes an enum with multiple @@ -498,13 +495,15 @@ pub(crate) mod rustc { (ty, layout): (Ty<'tcx>, Layout<'tcx>), i: FieldIdx, ) -> Ty<'tcx> { + // FIXME: Why does this not just use `ty_and_layout_field`? match ty.kind() { ty::Adt(def, args) => { match layout.variants { Variants::Single { index } => { - let field = &def.variant(index.unwrap()).fields[i]; + let field = &def.variant(index).fields[i]; field.ty(cx.tcx(), args) } + Variants::Empty => panic!("there is no field in Variants::Empty types"), // Discriminant field for enums (where applicable). Variants::Multiple { tag, .. } => { assert_eq!(i.as_usize(), 0); diff --git a/compiler/rustc_ty_utils/src/layout.rs b/compiler/rustc_ty_utils/src/layout.rs index b393190a4932..a3b2ed07d4b3 100644 --- a/compiler/rustc_ty_utils/src/layout.rs +++ b/compiler/rustc_ty_utils/src/layout.rs @@ -339,7 +339,7 @@ fn layout_of_uncached<'tcx>( let largest_niche = if count != 0 { element.largest_niche } else { None }; tcx.mk_layout(LayoutData { - variants: Variants::Single { index: Some(FIRST_VARIANT) }, + variants: Variants::Single { index: FIRST_VARIANT }, fields: FieldsShape::Array { stride: element.size, count }, backend_repr: abi, largest_niche, @@ -352,7 +352,7 @@ fn layout_of_uncached<'tcx>( ty::Slice(element) => { let element = cx.layout_of(element)?; tcx.mk_layout(LayoutData { - variants: Variants::Single { index: Some(FIRST_VARIANT) }, + variants: Variants::Single { index: FIRST_VARIANT }, fields: FieldsShape::Array { stride: element.size, count: 0 }, backend_repr: BackendRepr::Memory { sized: false }, largest_niche: None, @@ -363,7 +363,7 @@ fn layout_of_uncached<'tcx>( }) } ty::Str => tcx.mk_layout(LayoutData { - variants: Variants::Single { index: Some(FIRST_VARIANT) }, + variants: Variants::Single { index: FIRST_VARIANT }, fields: FieldsShape::Array { stride: Size::from_bytes(1), count: 0 }, backend_repr: BackendRepr::Memory { sized: false }, largest_niche: None, @@ -534,7 +534,7 @@ fn layout_of_uncached<'tcx>( }; tcx.mk_layout(LayoutData { - variants: Variants::Single { index: Some(FIRST_VARIANT) }, + variants: Variants::Single { index: FIRST_VARIANT }, fields, backend_repr: abi, largest_niche: e_ly.largest_niche, @@ -926,7 +926,7 @@ fn coroutine_layout<'tcx>( &ReprOptions::default(), StructKind::Prefixed(prefix_size, prefix_align.abi), )?; - variant.variants = Variants::Single { index: Some(index) }; + variant.variants = Variants::Single { index }; let FieldsShape::Arbitrary { offsets, memory_index } = variant.fields else { bug!(); @@ -1104,17 +1104,13 @@ fn variant_info_for_adt<'tcx>( }; match layout.variants { + Variants::Empty => (vec![], None), + Variants::Single { index } => { - if let Some(index) = index - && layout.fields != FieldsShape::Primitive - { - debug!("print-type-size `{:#?}` variant {}", layout, adt_def.variant(index).name); - let variant_def = &adt_def.variant(index); - let fields: Vec<_> = variant_def.fields.iter().map(|f| f.name).collect(); - (vec![build_variant_info(Some(variant_def.name), &fields, layout)], None) - } else { - (vec![], None) - } + debug!("print-type-size `{:#?}` variant {}", layout, adt_def.variant(index).name); + let variant_def = &adt_def.variant(index); + let fields: Vec<_> = variant_def.fields.iter().map(|f| f.name).collect(); + (vec![build_variant_info(Some(variant_def.name), &fields, layout)], None) } Variants::Multiple { tag, ref tag_encoding, .. } => { diff --git a/compiler/rustc_ty_utils/src/layout/invariant.rs b/compiler/rustc_ty_utils/src/layout/invariant.rs index 7e2375154c09..8d5403ed3246 100644 --- a/compiler/rustc_ty_utils/src/layout/invariant.rs +++ b/compiler/rustc_ty_utils/src/layout/invariant.rs @@ -242,15 +242,15 @@ pub(super) fn layout_sanity_check<'tcx>(cx: &LayoutCx<'tcx>, layout: &TyAndLayou check_layout_abi(cx, layout); match &layout.variants { - Variants::Single { index: None } => { + Variants::Empty => { assert!(layout.is_uninhabited()); } - Variants::Single { index: Some(idx) } => { + Variants::Single { index } => { if let Some(variants) = layout.ty.variant_range(tcx) { - assert!(variants.contains(idx)); + assert!(variants.contains(index)); } else { // Types without variants use `0` as dummy variant index. - assert!(idx.as_u32() == 0); + assert!(index.as_u32() == 0); } } Variants::Multiple { variants, tag, tag_encoding, .. } => { diff --git a/compiler/stable_mir/src/abi.rs b/compiler/stable_mir/src/abi.rs index cf28a0c58856..17e6a852022d 100644 --- a/compiler/stable_mir/src/abi.rs +++ b/compiler/stable_mir/src/abi.rs @@ -180,8 +180,10 @@ impl FieldsShape { #[derive(Clone, Debug, PartialEq, Eq, Hash, Serialize)] pub enum VariantsShape { + /// A type with no valid variants. Must be uninhabited. + Empty, + /// Single enum variants, structs/tuples, unions, and all non-ADTs. - // FIXME: needs to become `Option` like in the internal type. Single { index: VariantIdx }, /// Enum-likes with more than one inhabited variant: each variant comes with diff --git a/src/tools/miri/src/helpers.rs b/src/tools/miri/src/helpers.rs index 1f7c60ad1bdf..ef4543dcee86 100644 --- a/src/tools/miri/src/helpers.rs +++ b/src/tools/miri/src/helpers.rs @@ -605,7 +605,7 @@ pub trait EvalContextExt<'tcx>: crate::MiriInterpCxExt<'tcx> { // `UnsafeCell` action. (self.unsafe_cell_action)(v) } - Variants::Single { .. } => { + Variants::Single { .. } | Variants::Empty => { // Proceed further, try to find where exactly that `UnsafeCell` // is hiding. self.walk_value(v) diff --git a/src/tools/rust-analyzer/crates/hir-ty/src/layout.rs b/src/tools/rust-analyzer/crates/hir-ty/src/layout.rs index 08026f11c832..0c1f63880cd2 100644 --- a/src/tools/rust-analyzer/crates/hir-ty/src/layout.rs +++ b/src/tools/rust-analyzer/crates/hir-ty/src/layout.rs @@ -189,7 +189,7 @@ fn layout_of_simd_ty( }; Ok(Arc::new(Layout { - variants: Variants::Single { index: Some(struct_variant_idx()) }, + variants: Variants::Single { index: struct_variant_idx() }, fields, backend_repr: BackendRepr::Vector { element: e_abi, count: e_len }, largest_niche: e_ly.largest_niche, @@ -305,7 +305,7 @@ pub fn layout_of_ty_query( let largest_niche = if count != 0 { element.largest_niche } else { None }; Layout { - variants: Variants::Single { index: Some(struct_variant_idx()) }, + variants: Variants::Single { index: struct_variant_idx() }, fields: FieldsShape::Array { stride: element.size, count }, backend_repr, largest_niche, @@ -318,7 +318,7 @@ pub fn layout_of_ty_query( TyKind::Slice(element) => { let element = db.layout_of_ty(element.clone(), trait_env)?; Layout { - variants: Variants::Single { index: Some(struct_variant_idx()) }, + variants: Variants::Single { index: struct_variant_idx() }, fields: FieldsShape::Array { stride: element.size, count: 0 }, backend_repr: BackendRepr::Memory { sized: false }, largest_niche: None, @@ -329,7 +329,7 @@ pub fn layout_of_ty_query( } } TyKind::Str => Layout { - variants: Variants::Single { index: Some(struct_variant_idx()) }, + variants: Variants::Single { index: struct_variant_idx() }, fields: FieldsShape::Array { stride: Size::from_bytes(1), count: 0 }, backend_repr: BackendRepr::Memory { sized: false }, largest_niche: None, diff --git a/src/tools/rust-analyzer/crates/hir-ty/src/mir/eval.rs b/src/tools/rust-analyzer/crates/hir-ty/src/mir/eval.rs index 9375853e9159..e3072d6ee797 100644 --- a/src/tools/rust-analyzer/crates/hir-ty/src/mir/eval.rs +++ b/src/tools/rust-analyzer/crates/hir-ty/src/mir/eval.rs @@ -813,7 +813,7 @@ impl Evaluator<'_> { ProjectionElem::Field(Either::Left(f)) => { let layout = self.layout(&prev_ty)?; let variant_layout = match &layout.variants { - Variants::Single { .. } => &layout, + Variants::Single { .. } | Variants::Empty => &layout, Variants::Multiple { variants, .. } => { &variants[match f.parent { hir_def::VariantId::EnumVariantId(it) => { @@ -1638,9 +1638,9 @@ impl Evaluator<'_> { return Ok(0); }; match &layout.variants { + Variants::Empty => unreachable!(), Variants::Single { index } => { - let r = self - .const_eval_discriminant(self.db.enum_data(e).variants[index.unwrap().0].0)?; + let r = self.const_eval_discriminant(self.db.enum_data(e).variants[index.0].0)?; Ok(r) } Variants::Multiple { tag, tag_encoding, variants, .. } => { @@ -1801,7 +1801,7 @@ impl Evaluator<'_> { } let layout = self.layout_adt(adt, subst)?; Ok(match &layout.variants { - Variants::Single { .. } => (layout.size.bytes_usize(), layout, None), + Variants::Single { .. } | Variants::Empty => (layout.size.bytes_usize(), layout, None), Variants::Multiple { variants, tag, tag_encoding, .. } => { let enum_variant_id = match it { VariantId::EnumVariantId(it) => it, diff --git a/src/tools/rust-analyzer/crates/hir-ty/src/utils.rs b/src/tools/rust-analyzer/crates/hir-ty/src/utils.rs index 43ed6a06f428..42e7edaf0f4f 100644 --- a/src/tools/rust-analyzer/crates/hir-ty/src/utils.rs +++ b/src/tools/rust-analyzer/crates/hir-ty/src/utils.rs @@ -334,8 +334,9 @@ pub(crate) fn detect_variant_from_bytes<'a>( e: EnumId, ) -> Option<(EnumVariantId, &'a Layout)> { let (var_id, var_layout) = match &layout.variants { + hir_def::layout::Variants::Empty => unreachable!(), hir_def::layout::Variants::Single { index } => { - (db.enum_data(e).variants[index.unwrap().0].0, layout) + (db.enum_data(e).variants[index.0].0, layout) } hir_def::layout::Variants::Multiple { tag, tag_encoding, variants, .. } => { let size = tag.size(target_data_layout).bytes_usize(); diff --git a/tests/ui/abi/c-zst.aarch64-darwin.stderr b/tests/ui/abi/c-zst.aarch64-darwin.stderr index aae92bd7dc9f..7d384bc875f9 100644 --- a/tests/ui/abi/c-zst.aarch64-darwin.stderr +++ b/tests/ui/abi/c-zst.aarch64-darwin.stderr @@ -18,9 +18,7 @@ error: fn_abi_of(pass_zst) = FnAbi { }, largest_niche: None, variants: Single { - index: Some( - 0, - ), + index: 0, }, max_repr_align: None, unadjusted_abi_align: $SOME_ALIGN, @@ -47,9 +45,7 @@ error: fn_abi_of(pass_zst) = FnAbi { }, largest_niche: None, variants: Single { - index: Some( - 0, - ), + index: 0, }, max_repr_align: None, unadjusted_abi_align: $SOME_ALIGN, diff --git a/tests/ui/abi/c-zst.powerpc-linux.stderr b/tests/ui/abi/c-zst.powerpc-linux.stderr index 4ff4a8b90cf7..7980710bab67 100644 --- a/tests/ui/abi/c-zst.powerpc-linux.stderr +++ b/tests/ui/abi/c-zst.powerpc-linux.stderr @@ -18,9 +18,7 @@ error: fn_abi_of(pass_zst) = FnAbi { }, largest_niche: None, variants: Single { - index: Some( - 0, - ), + index: 0, }, max_repr_align: None, unadjusted_abi_align: $SOME_ALIGN, @@ -58,9 +56,7 @@ error: fn_abi_of(pass_zst) = FnAbi { }, largest_niche: None, variants: Single { - index: Some( - 0, - ), + index: 0, }, max_repr_align: None, unadjusted_abi_align: $SOME_ALIGN, diff --git a/tests/ui/abi/c-zst.s390x-linux.stderr b/tests/ui/abi/c-zst.s390x-linux.stderr index 4ff4a8b90cf7..7980710bab67 100644 --- a/tests/ui/abi/c-zst.s390x-linux.stderr +++ b/tests/ui/abi/c-zst.s390x-linux.stderr @@ -18,9 +18,7 @@ error: fn_abi_of(pass_zst) = FnAbi { }, largest_niche: None, variants: Single { - index: Some( - 0, - ), + index: 0, }, max_repr_align: None, unadjusted_abi_align: $SOME_ALIGN, @@ -58,9 +56,7 @@ error: fn_abi_of(pass_zst) = FnAbi { }, largest_niche: None, variants: Single { - index: Some( - 0, - ), + index: 0, }, max_repr_align: None, unadjusted_abi_align: $SOME_ALIGN, diff --git a/tests/ui/abi/c-zst.sparc64-linux.stderr b/tests/ui/abi/c-zst.sparc64-linux.stderr index 4ff4a8b90cf7..7980710bab67 100644 --- a/tests/ui/abi/c-zst.sparc64-linux.stderr +++ b/tests/ui/abi/c-zst.sparc64-linux.stderr @@ -18,9 +18,7 @@ error: fn_abi_of(pass_zst) = FnAbi { }, largest_niche: None, variants: Single { - index: Some( - 0, - ), + index: 0, }, max_repr_align: None, unadjusted_abi_align: $SOME_ALIGN, @@ -58,9 +56,7 @@ error: fn_abi_of(pass_zst) = FnAbi { }, largest_niche: None, variants: Single { - index: Some( - 0, - ), + index: 0, }, max_repr_align: None, unadjusted_abi_align: $SOME_ALIGN, diff --git a/tests/ui/abi/c-zst.x86_64-linux.stderr b/tests/ui/abi/c-zst.x86_64-linux.stderr index aae92bd7dc9f..7d384bc875f9 100644 --- a/tests/ui/abi/c-zst.x86_64-linux.stderr +++ b/tests/ui/abi/c-zst.x86_64-linux.stderr @@ -18,9 +18,7 @@ error: fn_abi_of(pass_zst) = FnAbi { }, largest_niche: None, variants: Single { - index: Some( - 0, - ), + index: 0, }, max_repr_align: None, unadjusted_abi_align: $SOME_ALIGN, @@ -47,9 +45,7 @@ error: fn_abi_of(pass_zst) = FnAbi { }, largest_niche: None, variants: Single { - index: Some( - 0, - ), + index: 0, }, max_repr_align: None, unadjusted_abi_align: $SOME_ALIGN, diff --git a/tests/ui/abi/c-zst.x86_64-pc-windows-gnu.stderr b/tests/ui/abi/c-zst.x86_64-pc-windows-gnu.stderr index 4ff4a8b90cf7..7980710bab67 100644 --- a/tests/ui/abi/c-zst.x86_64-pc-windows-gnu.stderr +++ b/tests/ui/abi/c-zst.x86_64-pc-windows-gnu.stderr @@ -18,9 +18,7 @@ error: fn_abi_of(pass_zst) = FnAbi { }, largest_niche: None, variants: Single { - index: Some( - 0, - ), + index: 0, }, max_repr_align: None, unadjusted_abi_align: $SOME_ALIGN, @@ -58,9 +56,7 @@ error: fn_abi_of(pass_zst) = FnAbi { }, largest_niche: None, variants: Single { - index: Some( - 0, - ), + index: 0, }, max_repr_align: None, unadjusted_abi_align: $SOME_ALIGN, diff --git a/tests/ui/abi/debug.stderr b/tests/ui/abi/debug.stderr index 0cbdf366616c..aa51c42c58dc 100644 --- a/tests/ui/abi/debug.stderr +++ b/tests/ui/abi/debug.stderr @@ -21,9 +21,7 @@ error: fn_abi_of(test) = FnAbi { fields: Primitive, largest_niche: None, variants: Single { - index: Some( - 0, - ), + index: 0, }, max_repr_align: None, unadjusted_abi_align: $SOME_ALIGN, @@ -69,9 +67,7 @@ error: fn_abi_of(test) = FnAbi { }, ), variants: Single { - index: Some( - 0, - ), + index: 0, }, max_repr_align: None, unadjusted_abi_align: $SOME_ALIGN, @@ -128,9 +124,7 @@ error: fn_abi_of(TestFnPtr) = FnAbi { }, ), variants: Single { - index: Some( - 0, - ), + index: 0, }, max_repr_align: None, unadjusted_abi_align: $SOME_ALIGN, @@ -167,9 +161,7 @@ error: fn_abi_of(TestFnPtr) = FnAbi { fields: Primitive, largest_niche: None, variants: Single { - index: Some( - 0, - ), + index: 0, }, max_repr_align: None, unadjusted_abi_align: $SOME_ALIGN, @@ -218,9 +210,7 @@ error: fn_abi_of(test_generic) = FnAbi { fields: Primitive, largest_niche: None, variants: Single { - index: Some( - 0, - ), + index: 0, }, max_repr_align: None, unadjusted_abi_align: $SOME_ALIGN, @@ -254,9 +244,7 @@ error: fn_abi_of(test_generic) = FnAbi { }, largest_niche: None, variants: Single { - index: Some( - 0, - ), + index: 0, }, max_repr_align: None, unadjusted_abi_align: $SOME_ALIGN, @@ -304,9 +292,7 @@ error: ABIs are not compatible fields: Primitive, largest_niche: None, variants: Single { - index: Some( - 0, - ), + index: 0, }, max_repr_align: None, unadjusted_abi_align: $SOME_ALIGN, @@ -340,9 +326,7 @@ error: ABIs are not compatible }, largest_niche: None, variants: Single { - index: Some( - 0, - ), + index: 0, }, max_repr_align: None, unadjusted_abi_align: $SOME_ALIGN, @@ -378,9 +362,7 @@ error: ABIs are not compatible fields: Primitive, largest_niche: None, variants: Single { - index: Some( - 0, - ), + index: 0, }, max_repr_align: None, unadjusted_abi_align: $SOME_ALIGN, @@ -414,9 +396,7 @@ error: ABIs are not compatible }, largest_niche: None, variants: Single { - index: Some( - 0, - ), + index: 0, }, max_repr_align: None, unadjusted_abi_align: $SOME_ALIGN, @@ -455,9 +435,7 @@ error: ABIs are not compatible }, largest_niche: None, variants: Single { - index: Some( - 0, - ), + index: 0, }, max_repr_align: None, unadjusted_abi_align: $SOME_ALIGN, @@ -495,9 +473,7 @@ error: ABIs are not compatible }, largest_niche: None, variants: Single { - index: Some( - 0, - ), + index: 0, }, max_repr_align: None, unadjusted_abi_align: $SOME_ALIGN, @@ -530,9 +506,7 @@ error: ABIs are not compatible }, largest_niche: None, variants: Single { - index: Some( - 0, - ), + index: 0, }, max_repr_align: None, unadjusted_abi_align: $SOME_ALIGN, @@ -570,9 +544,7 @@ error: ABIs are not compatible }, largest_niche: None, variants: Single { - index: Some( - 0, - ), + index: 0, }, max_repr_align: None, unadjusted_abi_align: $SOME_ALIGN, @@ -613,9 +585,7 @@ error: ABIs are not compatible fields: Primitive, largest_niche: None, variants: Single { - index: Some( - 0, - ), + index: 0, }, max_repr_align: None, unadjusted_abi_align: $SOME_ALIGN, @@ -649,9 +619,7 @@ error: ABIs are not compatible }, largest_niche: None, variants: Single { - index: Some( - 0, - ), + index: 0, }, max_repr_align: None, unadjusted_abi_align: $SOME_ALIGN, @@ -687,9 +655,7 @@ error: ABIs are not compatible fields: Primitive, largest_niche: None, variants: Single { - index: Some( - 0, - ), + index: 0, }, max_repr_align: None, unadjusted_abi_align: $SOME_ALIGN, @@ -723,9 +689,7 @@ error: ABIs are not compatible }, largest_niche: None, variants: Single { - index: Some( - 0, - ), + index: 0, }, max_repr_align: None, unadjusted_abi_align: $SOME_ALIGN, @@ -767,9 +731,7 @@ error: ABIs are not compatible fields: Primitive, largest_niche: None, variants: Single { - index: Some( - 0, - ), + index: 0, }, max_repr_align: None, unadjusted_abi_align: $SOME_ALIGN, @@ -803,9 +765,7 @@ error: ABIs are not compatible }, largest_niche: None, variants: Single { - index: Some( - 0, - ), + index: 0, }, max_repr_align: None, unadjusted_abi_align: $SOME_ALIGN, @@ -841,9 +801,7 @@ error: ABIs are not compatible fields: Primitive, largest_niche: None, variants: Single { - index: Some( - 0, - ), + index: 0, }, max_repr_align: None, unadjusted_abi_align: $SOME_ALIGN, @@ -877,9 +835,7 @@ error: ABIs are not compatible }, largest_niche: None, variants: Single { - index: Some( - 0, - ), + index: 0, }, max_repr_align: None, unadjusted_abi_align: $SOME_ALIGN, @@ -946,9 +902,7 @@ error: fn_abi_of(assoc_test) = FnAbi { }, ), variants: Single { - index: Some( - 0, - ), + index: 0, }, max_repr_align: None, unadjusted_abi_align: $SOME_ALIGN, @@ -984,9 +938,7 @@ error: fn_abi_of(assoc_test) = FnAbi { }, largest_niche: None, variants: Single { - index: Some( - 0, - ), + index: 0, }, max_repr_align: None, unadjusted_abi_align: $SOME_ALIGN, diff --git a/tests/ui/abi/sysv64-zst.stderr b/tests/ui/abi/sysv64-zst.stderr index 920963c69874..8e1791e27d27 100644 --- a/tests/ui/abi/sysv64-zst.stderr +++ b/tests/ui/abi/sysv64-zst.stderr @@ -18,9 +18,7 @@ error: fn_abi_of(pass_zst) = FnAbi { }, largest_niche: None, variants: Single { - index: Some( - 0, - ), + index: 0, }, max_repr_align: None, unadjusted_abi_align: $SOME_ALIGN, @@ -47,9 +45,7 @@ error: fn_abi_of(pass_zst) = FnAbi { }, largest_niche: None, variants: Single { - index: Some( - 0, - ), + index: 0, }, max_repr_align: None, unadjusted_abi_align: $SOME_ALIGN, diff --git a/tests/ui/abi/win64-zst.x86_64-linux.stderr b/tests/ui/abi/win64-zst.x86_64-linux.stderr index 2752555b4f31..76d90670eb1d 100644 --- a/tests/ui/abi/win64-zst.x86_64-linux.stderr +++ b/tests/ui/abi/win64-zst.x86_64-linux.stderr @@ -18,9 +18,7 @@ error: fn_abi_of(pass_zst) = FnAbi { }, largest_niche: None, variants: Single { - index: Some( - 0, - ), + index: 0, }, max_repr_align: None, unadjusted_abi_align: $SOME_ALIGN, @@ -47,9 +45,7 @@ error: fn_abi_of(pass_zst) = FnAbi { }, largest_niche: None, variants: Single { - index: Some( - 0, - ), + index: 0, }, max_repr_align: None, unadjusted_abi_align: $SOME_ALIGN, diff --git a/tests/ui/abi/win64-zst.x86_64-windows-gnu.stderr b/tests/ui/abi/win64-zst.x86_64-windows-gnu.stderr index 19abb5930b15..7ee90e247441 100644 --- a/tests/ui/abi/win64-zst.x86_64-windows-gnu.stderr +++ b/tests/ui/abi/win64-zst.x86_64-windows-gnu.stderr @@ -18,9 +18,7 @@ error: fn_abi_of(pass_zst) = FnAbi { }, largest_niche: None, variants: Single { - index: Some( - 0, - ), + index: 0, }, max_repr_align: None, unadjusted_abi_align: $SOME_ALIGN, @@ -58,9 +56,7 @@ error: fn_abi_of(pass_zst) = FnAbi { }, largest_niche: None, variants: Single { - index: Some( - 0, - ), + index: 0, }, max_repr_align: None, unadjusted_abi_align: $SOME_ALIGN, diff --git a/tests/ui/abi/win64-zst.x86_64-windows-msvc.stderr b/tests/ui/abi/win64-zst.x86_64-windows-msvc.stderr index 2752555b4f31..76d90670eb1d 100644 --- a/tests/ui/abi/win64-zst.x86_64-windows-msvc.stderr +++ b/tests/ui/abi/win64-zst.x86_64-windows-msvc.stderr @@ -18,9 +18,7 @@ error: fn_abi_of(pass_zst) = FnAbi { }, largest_niche: None, variants: Single { - index: Some( - 0, - ), + index: 0, }, max_repr_align: None, unadjusted_abi_align: $SOME_ALIGN, @@ -47,9 +45,7 @@ error: fn_abi_of(pass_zst) = FnAbi { }, largest_niche: None, variants: Single { - index: Some( - 0, - ), + index: 0, }, max_repr_align: None, unadjusted_abi_align: $SOME_ALIGN, diff --git a/tests/ui/layout/debug.stderr b/tests/ui/layout/debug.stderr index 8ae2933c427e..bd31665dac1f 100644 --- a/tests/ui/layout/debug.stderr +++ b/tests/ui/layout/debug.stderr @@ -57,9 +57,7 @@ error: layout_of(E) = Layout { }, largest_niche: None, variants: Single { - index: Some( - 0, - ), + index: 0, }, max_repr_align: None, unadjusted_abi_align: Align(1 bytes), @@ -85,9 +83,7 @@ error: layout_of(E) = Layout { }, largest_niche: None, variants: Single { - index: Some( - 1, - ), + index: 1, }, max_repr_align: None, unadjusted_abi_align: Align(4 bytes), @@ -138,9 +134,7 @@ error: layout_of(S) = Layout { }, largest_niche: None, variants: Single { - index: Some( - 0, - ), + index: 0, }, max_repr_align: None, unadjusted_abi_align: Align(4 bytes), @@ -164,9 +158,7 @@ error: layout_of(U) = Layout { ), largest_niche: None, variants: Single { - index: Some( - 0, - ), + index: 0, }, max_repr_align: None, unadjusted_abi_align: Align(4 bytes), @@ -259,9 +251,7 @@ error: layout_of(Result) = Layout { }, largest_niche: None, variants: Single { - index: Some( - 0, - ), + index: 0, }, max_repr_align: None, unadjusted_abi_align: Align(4 bytes), @@ -298,9 +288,7 @@ error: layout_of(Result) = Layout { }, largest_niche: None, variants: Single { - index: Some( - 1, - ), + index: 1, }, max_repr_align: None, unadjusted_abi_align: Align(4 bytes), @@ -333,9 +321,7 @@ error: layout_of(i32) = Layout { fields: Primitive, largest_niche: None, variants: Single { - index: Some( - 0, - ), + index: 0, }, max_repr_align: None, unadjusted_abi_align: Align(4 bytes), @@ -359,9 +345,7 @@ error: layout_of(V) = Layout { ), largest_niche: None, variants: Single { - index: Some( - 0, - ), + index: 0, }, max_repr_align: None, unadjusted_abi_align: Align(2 bytes), @@ -385,9 +369,7 @@ error: layout_of(W) = Layout { ), largest_niche: None, variants: Single { - index: Some( - 0, - ), + index: 0, }, max_repr_align: None, unadjusted_abi_align: Align(2 bytes), @@ -411,9 +393,7 @@ error: layout_of(Y) = Layout { ), largest_niche: None, variants: Single { - index: Some( - 0, - ), + index: 0, }, max_repr_align: None, unadjusted_abi_align: Align(2 bytes), @@ -437,9 +417,7 @@ error: layout_of(P1) = Layout { ), largest_niche: None, variants: Single { - index: Some( - 0, - ), + index: 0, }, max_repr_align: None, unadjusted_abi_align: Align(1 bytes), @@ -463,9 +441,7 @@ error: layout_of(P2) = Layout { ), largest_niche: None, variants: Single { - index: Some( - 0, - ), + index: 0, }, max_repr_align: None, unadjusted_abi_align: Align(1 bytes), @@ -489,9 +465,7 @@ error: layout_of(P3) = Layout { ), largest_niche: None, variants: Single { - index: Some( - 0, - ), + index: 0, }, max_repr_align: None, unadjusted_abi_align: Align(1 bytes), @@ -515,9 +489,7 @@ error: layout_of(P4) = Layout { ), largest_niche: None, variants: Single { - index: Some( - 0, - ), + index: 0, }, max_repr_align: None, unadjusted_abi_align: Align(1 bytes), @@ -546,9 +518,7 @@ error: layout_of(P5) = Layout { ), largest_niche: None, variants: Single { - index: Some( - 0, - ), + index: 0, }, max_repr_align: None, unadjusted_abi_align: Align(1 bytes), @@ -577,9 +547,7 @@ error: layout_of(MaybeUninit) = Layout { ), largest_niche: None, variants: Single { - index: Some( - 0, - ), + index: 0, }, max_repr_align: None, unadjusted_abi_align: Align(1 bytes), diff --git a/tests/ui/layout/hexagon-enum.stderr b/tests/ui/layout/hexagon-enum.stderr index a934f270911b..59fe667923f1 100644 --- a/tests/ui/layout/hexagon-enum.stderr +++ b/tests/ui/layout/hexagon-enum.stderr @@ -57,9 +57,7 @@ error: layout_of(A) = Layout { }, largest_niche: None, variants: Single { - index: Some( - 0, - ), + index: 0, }, max_repr_align: None, unadjusted_abi_align: Align(1 bytes), @@ -133,9 +131,7 @@ error: layout_of(B) = Layout { }, largest_niche: None, variants: Single { - index: Some( - 0, - ), + index: 0, }, max_repr_align: None, unadjusted_abi_align: Align(1 bytes), @@ -209,9 +205,7 @@ error: layout_of(C) = Layout { }, largest_niche: None, variants: Single { - index: Some( - 0, - ), + index: 0, }, max_repr_align: None, unadjusted_abi_align: Align(2 bytes), @@ -285,9 +279,7 @@ error: layout_of(P) = Layout { }, largest_niche: None, variants: Single { - index: Some( - 0, - ), + index: 0, }, max_repr_align: None, unadjusted_abi_align: Align(4 bytes), @@ -361,9 +353,7 @@ error: layout_of(T) = Layout { }, largest_niche: None, variants: Single { - index: Some( - 0, - ), + index: 0, }, max_repr_align: None, unadjusted_abi_align: Align(4 bytes), diff --git a/tests/ui/layout/issue-96158-scalarpair-payload-might-be-uninit.stderr b/tests/ui/layout/issue-96158-scalarpair-payload-might-be-uninit.stderr index 8b4e46de8450..ca041fb539b9 100644 --- a/tests/ui/layout/issue-96158-scalarpair-payload-might-be-uninit.stderr +++ b/tests/ui/layout/issue-96158-scalarpair-payload-might-be-uninit.stderr @@ -79,9 +79,7 @@ error: layout_of(MissingPayloadField) = Layout { }, largest_niche: None, variants: Single { - index: Some( - 0, - ), + index: 0, }, max_repr_align: None, unadjusted_abi_align: Align(1 bytes), @@ -101,9 +99,7 @@ error: layout_of(MissingPayloadField) = Layout { }, largest_niche: None, variants: Single { - index: Some( - 1, - ), + index: 1, }, max_repr_align: None, unadjusted_abi_align: Align(1 bytes), @@ -201,9 +197,7 @@ error: layout_of(CommonPayloadField) = Layout { }, largest_niche: None, variants: Single { - index: Some( - 0, - ), + index: 0, }, max_repr_align: None, unadjusted_abi_align: Align(1 bytes), @@ -240,9 +234,7 @@ error: layout_of(CommonPayloadField) = Layout { }, largest_niche: None, variants: Single { - index: Some( - 1, - ), + index: 1, }, max_repr_align: None, unadjusted_abi_align: Align(1 bytes), @@ -338,9 +330,7 @@ error: layout_of(CommonPayloadFieldIsMaybeUninit) = Layout { }, largest_niche: None, variants: Single { - index: Some( - 0, - ), + index: 0, }, max_repr_align: None, unadjusted_abi_align: Align(1 bytes), @@ -376,9 +366,7 @@ error: layout_of(CommonPayloadFieldIsMaybeUninit) = Layout { }, largest_niche: None, variants: Single { - index: Some( - 1, - ), + index: 1, }, max_repr_align: None, unadjusted_abi_align: Align(1 bytes), @@ -490,9 +478,7 @@ error: layout_of(NicheFirst) = Layout { }, ), variants: Single { - index: Some( - 0, - ), + index: 0, }, max_repr_align: None, unadjusted_abi_align: Align(1 bytes), @@ -512,9 +498,7 @@ error: layout_of(NicheFirst) = Layout { }, largest_niche: None, variants: Single { - index: Some( - 1, - ), + index: 1, }, max_repr_align: None, unadjusted_abi_align: Align(1 bytes), @@ -534,9 +518,7 @@ error: layout_of(NicheFirst) = Layout { }, largest_niche: None, variants: Single { - index: Some( - 2, - ), + index: 2, }, max_repr_align: None, unadjusted_abi_align: Align(1 bytes), @@ -648,9 +630,7 @@ error: layout_of(NicheSecond) = Layout { }, ), variants: Single { - index: Some( - 0, - ), + index: 0, }, max_repr_align: None, unadjusted_abi_align: Align(1 bytes), @@ -670,9 +650,7 @@ error: layout_of(NicheSecond) = Layout { }, largest_niche: None, variants: Single { - index: Some( - 1, - ), + index: 1, }, max_repr_align: None, unadjusted_abi_align: Align(1 bytes), @@ -692,9 +670,7 @@ error: layout_of(NicheSecond) = Layout { }, largest_niche: None, variants: Single { - index: Some( - 2, - ), + index: 2, }, max_repr_align: None, unadjusted_abi_align: Align(1 bytes), diff --git a/tests/ui/layout/issue-96185-overaligned-enum.stderr b/tests/ui/layout/issue-96185-overaligned-enum.stderr index 926434455950..bc40a2aa482e 100644 --- a/tests/ui/layout/issue-96185-overaligned-enum.stderr +++ b/tests/ui/layout/issue-96185-overaligned-enum.stderr @@ -51,9 +51,7 @@ error: layout_of(Aligned1) = Layout { }, largest_niche: None, variants: Single { - index: Some( - 0, - ), + index: 0, }, max_repr_align: Some( Align(8 bytes), @@ -75,9 +73,7 @@ error: layout_of(Aligned1) = Layout { }, largest_niche: None, variants: Single { - index: Some( - 1, - ), + index: 1, }, max_repr_align: Some( Align(8 bytes), @@ -155,9 +151,7 @@ error: layout_of(Aligned2) = Layout { }, largest_niche: None, variants: Single { - index: Some( - 0, - ), + index: 0, }, max_repr_align: Some( Align(1 bytes), @@ -179,9 +173,7 @@ error: layout_of(Aligned2) = Layout { }, largest_niche: None, variants: Single { - index: Some( - 1, - ), + index: 1, }, max_repr_align: Some( Align(1 bytes), diff --git a/tests/ui/layout/thumb-enum.stderr b/tests/ui/layout/thumb-enum.stderr index f35cf0dab3da..bf043af586b1 100644 --- a/tests/ui/layout/thumb-enum.stderr +++ b/tests/ui/layout/thumb-enum.stderr @@ -57,9 +57,7 @@ error: layout_of(A) = Layout { }, largest_niche: None, variants: Single { - index: Some( - 0, - ), + index: 0, }, max_repr_align: None, unadjusted_abi_align: Align(1 bytes), @@ -133,9 +131,7 @@ error: layout_of(B) = Layout { }, largest_niche: None, variants: Single { - index: Some( - 0, - ), + index: 0, }, max_repr_align: None, unadjusted_abi_align: Align(1 bytes), @@ -209,9 +205,7 @@ error: layout_of(C) = Layout { }, largest_niche: None, variants: Single { - index: Some( - 0, - ), + index: 0, }, max_repr_align: None, unadjusted_abi_align: Align(2 bytes), @@ -285,9 +279,7 @@ error: layout_of(P) = Layout { }, largest_niche: None, variants: Single { - index: Some( - 0, - ), + index: 0, }, max_repr_align: None, unadjusted_abi_align: Align(4 bytes), @@ -361,9 +353,7 @@ error: layout_of(T) = Layout { }, largest_niche: None, variants: Single { - index: Some( - 0, - ), + index: 0, }, max_repr_align: None, unadjusted_abi_align: Align(4 bytes), diff --git a/tests/ui/layout/zero-sized-array-enum-niche.stderr b/tests/ui/layout/zero-sized-array-enum-niche.stderr index 4c6f636b267a..d61408098df7 100644 --- a/tests/ui/layout/zero-sized-array-enum-niche.stderr +++ b/tests/ui/layout/zero-sized-array-enum-niche.stderr @@ -55,9 +55,7 @@ error: layout_of(Result<[u32; 0], bool>) = Layout { }, largest_niche: None, variants: Single { - index: Some( - 0, - ), + index: 0, }, max_repr_align: None, unadjusted_abi_align: Align(4 bytes), @@ -90,9 +88,7 @@ error: layout_of(Result<[u32; 0], bool>) = Layout { }, ), variants: Single { - index: Some( - 1, - ), + index: 1, }, max_repr_align: None, unadjusted_abi_align: Align(1 bytes), @@ -164,9 +160,7 @@ error: layout_of(MultipleAlignments) = Layout { }, largest_niche: None, variants: Single { - index: Some( - 0, - ), + index: 0, }, max_repr_align: None, unadjusted_abi_align: Align(2 bytes), @@ -190,9 +184,7 @@ error: layout_of(MultipleAlignments) = Layout { }, largest_niche: None, variants: Single { - index: Some( - 1, - ), + index: 1, }, max_repr_align: None, unadjusted_abi_align: Align(4 bytes), @@ -225,9 +217,7 @@ error: layout_of(MultipleAlignments) = Layout { }, ), variants: Single { - index: Some( - 2, - ), + index: 2, }, max_repr_align: None, unadjusted_abi_align: Align(1 bytes), @@ -299,9 +289,7 @@ error: layout_of(Result<[u32; 0], Packed>>) = Layout { }, largest_niche: None, variants: Single { - index: Some( - 0, - ), + index: 0, }, max_repr_align: None, unadjusted_abi_align: Align(4 bytes), @@ -334,9 +322,7 @@ error: layout_of(Result<[u32; 0], Packed>>) = Layout { }, ), variants: Single { - index: Some( - 1, - ), + index: 1, }, max_repr_align: None, unadjusted_abi_align: Align(1 bytes), @@ -412,9 +398,7 @@ error: layout_of(Result<[u32; 0], Packed>) = Layout { }, largest_niche: None, variants: Single { - index: Some( - 0, - ), + index: 0, }, max_repr_align: None, unadjusted_abi_align: Align(4 bytes), @@ -447,9 +431,7 @@ error: layout_of(Result<[u32; 0], Packed>) = Layout { }, ), variants: Single { - index: Some( - 1, - ), + index: 1, }, max_repr_align: None, unadjusted_abi_align: Align(1 bytes), diff --git a/tests/ui/repr/repr-c-dead-variants.aarch64-unknown-linux-gnu.stderr b/tests/ui/repr/repr-c-dead-variants.aarch64-unknown-linux-gnu.stderr index 08fd4237eeba..64a0cb7f31a1 100644 --- a/tests/ui/repr/repr-c-dead-variants.aarch64-unknown-linux-gnu.stderr +++ b/tests/ui/repr/repr-c-dead-variants.aarch64-unknown-linux-gnu.stderr @@ -51,9 +51,7 @@ error: layout_of(Univariant) = Layout { }, largest_niche: None, variants: Single { - index: Some( - 0, - ), + index: 0, }, max_repr_align: None, unadjusted_abi_align: Align(4 bytes), @@ -135,9 +133,7 @@ error: layout_of(TwoVariants) = Layout { }, largest_niche: None, variants: Single { - index: Some( - 0, - ), + index: 0, }, max_repr_align: None, unadjusted_abi_align: Align(4 bytes), @@ -173,9 +169,7 @@ error: layout_of(TwoVariants) = Layout { }, largest_niche: None, variants: Single { - index: Some( - 1, - ), + index: 1, }, max_repr_align: None, unadjusted_abi_align: Align(4 bytes), @@ -247,9 +241,7 @@ error: layout_of(DeadBranchHasOtherField) = Layout { }, largest_niche: None, variants: Single { - index: Some( - 0, - ), + index: 0, }, max_repr_align: Some( Align(8 bytes), @@ -275,9 +267,7 @@ error: layout_of(DeadBranchHasOtherField) = Layout { }, largest_niche: None, variants: Single { - index: Some( - 1, - ), + index: 1, }, max_repr_align: None, unadjusted_abi_align: Align(8 bytes), diff --git a/tests/ui/repr/repr-c-dead-variants.armebv7r-none-eabi.stderr b/tests/ui/repr/repr-c-dead-variants.armebv7r-none-eabi.stderr index 473268cac1a6..5c4daa6d5197 100644 --- a/tests/ui/repr/repr-c-dead-variants.armebv7r-none-eabi.stderr +++ b/tests/ui/repr/repr-c-dead-variants.armebv7r-none-eabi.stderr @@ -51,9 +51,7 @@ error: layout_of(Univariant) = Layout { }, largest_niche: None, variants: Single { - index: Some( - 0, - ), + index: 0, }, max_repr_align: None, unadjusted_abi_align: Align(1 bytes), @@ -135,9 +133,7 @@ error: layout_of(TwoVariants) = Layout { }, largest_niche: None, variants: Single { - index: Some( - 0, - ), + index: 0, }, max_repr_align: None, unadjusted_abi_align: Align(1 bytes), @@ -173,9 +169,7 @@ error: layout_of(TwoVariants) = Layout { }, largest_niche: None, variants: Single { - index: Some( - 1, - ), + index: 1, }, max_repr_align: None, unadjusted_abi_align: Align(1 bytes), @@ -247,9 +241,7 @@ error: layout_of(DeadBranchHasOtherField) = Layout { }, largest_niche: None, variants: Single { - index: Some( - 0, - ), + index: 0, }, max_repr_align: Some( Align(8 bytes), @@ -275,9 +267,7 @@ error: layout_of(DeadBranchHasOtherField) = Layout { }, largest_niche: None, variants: Single { - index: Some( - 1, - ), + index: 1, }, max_repr_align: None, unadjusted_abi_align: Align(8 bytes), diff --git a/tests/ui/repr/repr-c-dead-variants.i686-pc-windows-msvc.stderr b/tests/ui/repr/repr-c-dead-variants.i686-pc-windows-msvc.stderr index 08fd4237eeba..64a0cb7f31a1 100644 --- a/tests/ui/repr/repr-c-dead-variants.i686-pc-windows-msvc.stderr +++ b/tests/ui/repr/repr-c-dead-variants.i686-pc-windows-msvc.stderr @@ -51,9 +51,7 @@ error: layout_of(Univariant) = Layout { }, largest_niche: None, variants: Single { - index: Some( - 0, - ), + index: 0, }, max_repr_align: None, unadjusted_abi_align: Align(4 bytes), @@ -135,9 +133,7 @@ error: layout_of(TwoVariants) = Layout { }, largest_niche: None, variants: Single { - index: Some( - 0, - ), + index: 0, }, max_repr_align: None, unadjusted_abi_align: Align(4 bytes), @@ -173,9 +169,7 @@ error: layout_of(TwoVariants) = Layout { }, largest_niche: None, variants: Single { - index: Some( - 1, - ), + index: 1, }, max_repr_align: None, unadjusted_abi_align: Align(4 bytes), @@ -247,9 +241,7 @@ error: layout_of(DeadBranchHasOtherField) = Layout { }, largest_niche: None, variants: Single { - index: Some( - 0, - ), + index: 0, }, max_repr_align: Some( Align(8 bytes), @@ -275,9 +267,7 @@ error: layout_of(DeadBranchHasOtherField) = Layout { }, largest_niche: None, variants: Single { - index: Some( - 1, - ), + index: 1, }, max_repr_align: None, unadjusted_abi_align: Align(8 bytes), diff --git a/tests/ui/repr/repr-c-dead-variants.x86_64-unknown-linux-gnu.stderr b/tests/ui/repr/repr-c-dead-variants.x86_64-unknown-linux-gnu.stderr index 08fd4237eeba..64a0cb7f31a1 100644 --- a/tests/ui/repr/repr-c-dead-variants.x86_64-unknown-linux-gnu.stderr +++ b/tests/ui/repr/repr-c-dead-variants.x86_64-unknown-linux-gnu.stderr @@ -51,9 +51,7 @@ error: layout_of(Univariant) = Layout { }, largest_niche: None, variants: Single { - index: Some( - 0, - ), + index: 0, }, max_repr_align: None, unadjusted_abi_align: Align(4 bytes), @@ -135,9 +133,7 @@ error: layout_of(TwoVariants) = Layout { }, largest_niche: None, variants: Single { - index: Some( - 0, - ), + index: 0, }, max_repr_align: None, unadjusted_abi_align: Align(4 bytes), @@ -173,9 +169,7 @@ error: layout_of(TwoVariants) = Layout { }, largest_niche: None, variants: Single { - index: Some( - 1, - ), + index: 1, }, max_repr_align: None, unadjusted_abi_align: Align(4 bytes), @@ -247,9 +241,7 @@ error: layout_of(DeadBranchHasOtherField) = Layout { }, largest_niche: None, variants: Single { - index: Some( - 0, - ), + index: 0, }, max_repr_align: Some( Align(8 bytes), @@ -275,9 +267,7 @@ error: layout_of(DeadBranchHasOtherField) = Layout { }, largest_niche: None, variants: Single { - index: Some( - 1, - ), + index: 1, }, max_repr_align: None, unadjusted_abi_align: Align(8 bytes), diff --git a/tests/ui/repr/repr-c-int-dead-variants.stderr b/tests/ui/repr/repr-c-int-dead-variants.stderr index 1200f120d37b..75005a64523a 100644 --- a/tests/ui/repr/repr-c-int-dead-variants.stderr +++ b/tests/ui/repr/repr-c-int-dead-variants.stderr @@ -51,9 +51,7 @@ error: layout_of(UnivariantU8) = Layout { }, largest_niche: None, variants: Single { - index: Some( - 0, - ), + index: 0, }, max_repr_align: None, unadjusted_abi_align: Align(1 bytes), @@ -135,9 +133,7 @@ error: layout_of(TwoVariantsU8) = Layout { }, largest_niche: None, variants: Single { - index: Some( - 0, - ), + index: 0, }, max_repr_align: None, unadjusted_abi_align: Align(1 bytes), @@ -173,9 +169,7 @@ error: layout_of(TwoVariantsU8) = Layout { }, largest_niche: None, variants: Single { - index: Some( - 1, - ), + index: 1, }, max_repr_align: None, unadjusted_abi_align: Align(1 bytes), @@ -247,9 +241,7 @@ error: layout_of(DeadBranchHasOtherFieldU8) = Layout { }, largest_niche: None, variants: Single { - index: Some( - 0, - ), + index: 0, }, max_repr_align: Some( Align(8 bytes), @@ -275,9 +267,7 @@ error: layout_of(DeadBranchHasOtherFieldU8) = Layout { }, largest_niche: None, variants: Single { - index: Some( - 1, - ), + index: 1, }, max_repr_align: None, unadjusted_abi_align: Align(8 bytes), diff --git a/tests/ui/type/pattern_types/range_patterns.stderr b/tests/ui/type/pattern_types/range_patterns.stderr index 9954471968de..0eed7c2ce1ce 100644 --- a/tests/ui/type/pattern_types/range_patterns.stderr +++ b/tests/ui/type/pattern_types/range_patterns.stderr @@ -32,9 +32,7 @@ error: layout_of(NonZero) = Layout { }, ), variants: Single { - index: Some( - 0, - ), + index: 0, }, max_repr_align: None, unadjusted_abi_align: Align(4 bytes), @@ -71,9 +69,7 @@ error: layout_of((u32) is 1..=) = Layout { }, ), variants: Single { - index: Some( - 0, - ), + index: 0, }, max_repr_align: None, unadjusted_abi_align: Align(4 bytes), @@ -137,9 +133,7 @@ error: layout_of(Option<(u32) is 1..=>) = Layout { }, largest_niche: None, variants: Single { - index: Some( - 0, - ), + index: 0, }, max_repr_align: None, unadjusted_abi_align: Align(1 bytes), @@ -178,9 +172,7 @@ error: layout_of(Option<(u32) is 1..=>) = Layout { }, ), variants: Single { - index: Some( - 1, - ), + index: 1, }, max_repr_align: None, unadjusted_abi_align: Align(4 bytes), @@ -249,9 +241,7 @@ error: layout_of(Option>) = Layout { }, largest_niche: None, variants: Single { - index: Some( - 0, - ), + index: 0, }, max_repr_align: None, unadjusted_abi_align: Align(1 bytes), @@ -290,9 +280,7 @@ error: layout_of(Option>) = Layout { }, ), variants: Single { - index: Some( - 1, - ), + index: 1, }, max_repr_align: None, unadjusted_abi_align: Align(4 bytes), @@ -341,9 +329,7 @@ error: layout_of(NonZeroU32New) = Layout { }, ), variants: Single { - index: Some( - 0, - ), + index: 0, }, max_repr_align: None, unadjusted_abi_align: Align(4 bytes), From 85f01386daef14e107cb87c27fc6271f1f2fa584 Mon Sep 17 00:00:00 2001 From: Ralf Jung Date: Mon, 2 Dec 2024 17:56:18 +0100 Subject: [PATCH 46/92] add comment explaining why ty_and_layout_field is not used Co-authored-by: Jack Wrenn --- compiler/rustc_transmute/src/layout/tree.rs | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/compiler/rustc_transmute/src/layout/tree.rs b/compiler/rustc_transmute/src/layout/tree.rs index 4cc6292a3ee3..6ce9969aefe9 100644 --- a/compiler/rustc_transmute/src/layout/tree.rs +++ b/compiler/rustc_transmute/src/layout/tree.rs @@ -495,7 +495,10 @@ pub(crate) mod rustc { (ty, layout): (Ty<'tcx>, Layout<'tcx>), i: FieldIdx, ) -> Ty<'tcx> { - // FIXME: Why does this not just use `ty_and_layout_field`? + // We cannot use `ty_and_layout_field` to retrieve the field type, since + // `ty_and_layout_field` erases regions in the returned type. We must + // not erase regions here, since we may need to ultimately emit outlives + // obligations as a consequence of the transmutability analysis. match ty.kind() { ty::Adt(def, args) => { match layout.variants { From 397ae3cdf641b8d303ab9d004013f956c2991727 Mon Sep 17 00:00:00 2001 From: Ralf Jung Date: Sat, 7 Dec 2024 18:37:33 +0100 Subject: [PATCH 47/92] fix outdated comment Co-authored-by: Camille Gillot --- .../src/debuginfo/metadata/enums/cpp_like.rs | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/compiler/rustc_codegen_llvm/src/debuginfo/metadata/enums/cpp_like.rs b/compiler/rustc_codegen_llvm/src/debuginfo/metadata/enums/cpp_like.rs index 12a46184d108..23e11748e527 100644 --- a/compiler/rustc_codegen_llvm/src/debuginfo/metadata/enums/cpp_like.rs +++ b/compiler/rustc_codegen_llvm/src/debuginfo/metadata/enums/cpp_like.rs @@ -213,8 +213,7 @@ pub(super) fn build_enum_type_di_node<'ll, 'tcx>( |cx, enum_type_di_node| { match enum_type_and_layout.variants { Variants::Empty => { - // Uninhabited enums have Variants::Single. We don't generate - // any members for them. + // We don't generate any members for uninhabited types. return smallvec![]; } Variants::Single { index: variant_index } => build_single_variant_union_fields( From 9ee1695885c0c82edd127e6d9519476707a6b6d3 Mon Sep 17 00:00:00 2001 From: Oli Scherer Date: Thu, 12 Dec 2024 19:13:26 +0000 Subject: [PATCH 48/92] Merge some patterns together --- compiler/rustc_lint/src/internal.rs | 26 +++++--------------------- 1 file changed, 5 insertions(+), 21 deletions(-) diff --git a/compiler/rustc_lint/src/internal.rs b/compiler/rustc_lint/src/internal.rs index d32666d88951..b31a4c74787f 100644 --- a/compiler/rustc_lint/src/internal.rs +++ b/compiler/rustc_lint/src/internal.rs @@ -170,27 +170,11 @@ impl<'tcx> LateLintPass<'tcx> for TyTyKind { | PatKind::TupleStruct(qpath, ..) | PatKind::Struct(qpath, ..), .. - }) => { - if let QPath::TypeRelative(qpath_ty, ..) = qpath - && qpath_ty.hir_id == ty.hir_id - { - Some(path.span) - } else { - None - } - } - Node::Expr(Expr { kind: ExprKind::Path(qpath), .. }) => { - if let QPath::TypeRelative(qpath_ty, ..) = qpath - && qpath_ty.hir_id == ty.hir_id - { - Some(path.span) - } else { - None - } - } - // Can't unify these two branches because qpath below is `&&` and above is `&` - // and `A | B` paths don't play well together with adjustments, apparently. - Node::Expr(Expr { kind: ExprKind::Struct(qpath, ..), .. }) => { + }) + | Node::Expr( + Expr { kind: ExprKind::Path(qpath), .. } + | &Expr { kind: ExprKind::Struct(qpath, ..), .. }, + ) => { if let QPath::TypeRelative(qpath_ty, ..) = qpath && qpath_ty.hir_id == ty.hir_id { From 8857b84078fe9c872b0969fc72fe47e4f62999ee Mon Sep 17 00:00:00 2001 From: Kajetan Puchalski Date: Tue, 10 Dec 2024 13:31:16 +0000 Subject: [PATCH 49/92] ci: Move dist-aarch64-linux to an aarch64 runner Move the dist-aarch64-linux CI job to an aarch64 runner instead of cross-compiling it from an x86 one. This will make it possible to perform optimisations such as LTO, PGO and BOLT later on. --- .../dist-aarch64-linux/Dockerfile | 98 +++++++++++++++++++ .../dist-aarch64-linux/build-clang.sh | 46 +++++++++ .../dist-aarch64-linux/build-gcc.sh | 51 ++++++++++ .../dist-aarch64-linux/build-zstd.sh | 29 ++++++ .../host-aarch64/dist-aarch64-linux/shared.sh | 16 +++ .../host-x86_64/dist-aarch64-linux/Dockerfile | 32 ------ .../aarch64-linux-gnu.defconfig | 10 -- src/ci/github-actions/jobs.yml | 10 +- 8 files changed, 245 insertions(+), 47 deletions(-) create mode 100644 src/ci/docker/host-aarch64/dist-aarch64-linux/Dockerfile create mode 100755 src/ci/docker/host-aarch64/dist-aarch64-linux/build-clang.sh create mode 100755 src/ci/docker/host-aarch64/dist-aarch64-linux/build-gcc.sh create mode 100755 src/ci/docker/host-aarch64/dist-aarch64-linux/build-zstd.sh create mode 100644 src/ci/docker/host-aarch64/dist-aarch64-linux/shared.sh delete mode 100644 src/ci/docker/host-x86_64/dist-aarch64-linux/Dockerfile delete mode 100644 src/ci/docker/host-x86_64/dist-aarch64-linux/aarch64-linux-gnu.defconfig diff --git a/src/ci/docker/host-aarch64/dist-aarch64-linux/Dockerfile b/src/ci/docker/host-aarch64/dist-aarch64-linux/Dockerfile new file mode 100644 index 000000000000..c7778dbf6bbf --- /dev/null +++ b/src/ci/docker/host-aarch64/dist-aarch64-linux/Dockerfile @@ -0,0 +1,98 @@ +# We document platform support for minimum glibc 2.17 and kernel 3.2. +# CentOS 7 has headers for kernel 3.10, but that's fine as long as we don't +# actually use newer APIs in rustc or std without a fallback. It's more +# important that we match glibc for ELF symbol versioning. +FROM centos:7 + +WORKDIR /build + +# CentOS 7 EOL is June 30, 2024, but the repos remain in the vault. +RUN sed -i /etc/yum.repos.d/*.repo -e 's!^mirrorlist!#mirrorlist!' \ + -e 's!^#baseurl=http://mirror.centos.org/!baseurl=https://vault.centos.org/!' +RUN sed -i 's/enabled=1/enabled=0/' /etc/yum/pluginconf.d/fastestmirror.conf + +RUN yum upgrade -y && \ + yum install -y \ + automake \ + bzip2 \ + file \ + gcc \ + gcc-c++ \ + git \ + glibc-devel \ + libedit-devel \ + libstdc++-devel \ + make \ + ncurses-devel \ + openssl-devel \ + patch \ + perl \ + perl-core \ + pkgconfig \ + python3 \ + unzip \ + wget \ + xz \ + zlib-devel \ + && yum clean all + +RUN mkdir -p /rustroot/bin + +ENV PATH=/rustroot/bin:$PATH +ENV LD_LIBRARY_PATH=/rustroot/lib64:/rustroot/lib32:/rustroot/lib +ENV PKG_CONFIG_PATH=/rustroot/lib/pkgconfig +WORKDIR /tmp +RUN mkdir /home/user +COPY host-aarch64/dist-aarch64-linux/shared.sh /tmp/ + +# Need at least GCC 5.1 to compile LLVM +COPY host-aarch64/dist-aarch64-linux/build-gcc.sh /tmp/ +RUN ./build-gcc.sh && yum remove -y gcc gcc-c++ + +ENV CC=gcc CXX=g++ + +# LLVM 17 needs cmake 3.20 or higher. +COPY scripts/cmake.sh /tmp/ +RUN ./cmake.sh + +# Build LLVM+Clang +COPY host-aarch64/dist-aarch64-linux/build-clang.sh /tmp/ +RUN ./build-clang.sh +ENV CC=clang CXX=clang++ + +# Build zstd to enable `llvm.libzstd`. +COPY host-aarch64/dist-aarch64-linux/build-zstd.sh /tmp/ +RUN ./build-zstd.sh + +COPY scripts/sccache.sh /scripts/ +RUN sh /scripts/sccache.sh + +ENV PGO_HOST=aarch64-unknown-linux-gnu +ENV HOSTS=aarch64-unknown-linux-gnu + +ENV CPATH=/usr/include/aarch64-linux-gnu/:$CPATH + +ENV RUST_CONFIGURE_ARGS \ + --build=aarch64-unknown-linux-gnu \ + --enable-full-tools \ + --enable-profiler \ + --enable-sanitizers \ + --enable-compiler-docs \ + --set target.aarch64-unknown-linux-gnu.linker=clang \ + --set target.aarch64-unknown-linux-gnu.ar=/rustroot/bin/llvm-ar \ + --set target.aarch64-unknown-linux-gnu.ranlib=/rustroot/bin/llvm-ranlib \ + --set llvm.link-shared=true \ + --set llvm.thin-lto=false \ + --set llvm.libzstd=true \ + --set llvm.ninja=false \ + --set rust.debug-assertions=false \ + --set rust.jemalloc \ + --set rust.use-lld=true \ + --set rust.codegen-units=1 + +ENV SCRIPT python3 ../x.py dist --host $HOSTS --target $HOSTS + +ENV CARGO_TARGET_AARCH64_UNKNOWN_LINUX_GNU_LINKER=clang +ENV DIST_SRC 1 +ENV LIBCURL_NO_PKG_CONFIG 1 +ENV DIST_REQUIRE_ALL_TOOLS 1 diff --git a/src/ci/docker/host-aarch64/dist-aarch64-linux/build-clang.sh b/src/ci/docker/host-aarch64/dist-aarch64-linux/build-clang.sh new file mode 100755 index 000000000000..fb5f4d8c4f79 --- /dev/null +++ b/src/ci/docker/host-aarch64/dist-aarch64-linux/build-clang.sh @@ -0,0 +1,46 @@ +#!/usr/bin/env bash + +set -ex + +source shared.sh + +# Try to keep the LLVM version here in sync with src/ci/scripts/install-clang.sh +LLVM=llvmorg-19.1.5 + +mkdir llvm-project +cd llvm-project + +curl -L https://github.com/llvm/llvm-project/archive/$LLVM.tar.gz | \ + tar xzf - --strip-components=1 + +mkdir clang-build +cd clang-build + +# For whatever reason the default set of include paths for clang is different +# than that of gcc. As a result we need to manually include our sysroot's +# include path, /rustroot/include, to clang's default include path. +INC="/rustroot/include:/usr/include" + +# We need compiler-rt for the profile runtime (used later to PGO the LLVM build) +# but sanitizers aren't currently building. Since we don't need those, just +# disable them. BOLT is used for optimizing LLVM. +hide_output \ + cmake ../llvm \ + -DCMAKE_BUILD_TYPE=Release \ + -DCMAKE_INSTALL_PREFIX=/rustroot \ + -DCOMPILER_RT_BUILD_SANITIZERS=OFF \ + -DCOMPILER_RT_BUILD_XRAY=OFF \ + -DCOMPILER_RT_BUILD_MEMPROF=OFF \ + -DCOMPILER_RT_BUILD_CTX_PROFILE=OFF \ + -DLLVM_TARGETS_TO_BUILD=AArch64 \ + -DLLVM_INCLUDE_BENCHMARKS=OFF \ + -DLLVM_INCLUDE_TESTS=OFF \ + -DLLVM_INCLUDE_EXAMPLES=OFF \ + -DLLVM_ENABLE_PROJECTS="clang;lld;compiler-rt;bolt" \ + -DC_INCLUDE_DIRS="$INC" + +hide_output make -j$(nproc) +hide_output make install + +cd ../.. +rm -rf llvm-project diff --git a/src/ci/docker/host-aarch64/dist-aarch64-linux/build-gcc.sh b/src/ci/docker/host-aarch64/dist-aarch64-linux/build-gcc.sh new file mode 100755 index 000000000000..ad33b21b9b5a --- /dev/null +++ b/src/ci/docker/host-aarch64/dist-aarch64-linux/build-gcc.sh @@ -0,0 +1,51 @@ +#!/usr/bin/env bash +set -ex + +source shared.sh + +# Note: in the future when bumping to version 10.1.0, also take care of the sed block below. +GCC=9.5.0 + +curl https://ftp.gnu.org/gnu/gcc/gcc-$GCC/gcc-$GCC.tar.xz | xzcat | tar xf - +cd gcc-$GCC + +# FIXME(#49246): Remove the `sed` below. +# +# On 2018 March 21st, two Travis builders' cache for Docker are suddenly invalidated. Normally this +# is fine, because we just need to rebuild the Docker image. However, it reveals a network issue: +# downloading from `ftp://gcc.gnu.org/` from Travis (using passive mode) often leads to "Connection +# timed out" error, and even when the download completed, the file is usually corrupted. This causes +# nothing to be landed that day. +# +# We observed that the `gcc-4.8.5.tar.bz2` above can be downloaded successfully, so as a stability +# improvement we try to download from the HTTPS mirror instead. Turns out this uncovered the third +# bug: the host `gcc.gnu.org` and `cygwin.com` share the same IP, and the TLS certificate of the +# latter host is presented to `wget`! Therefore, we choose to download from the insecure HTTP server +# instead here. +# +# Note: in version 10.1.0, the URL used in `download_prerequisites` has changed from using FTP to +# using HTTP. When bumping to that gcc version, we can likely remove the sed replacement below, or +# the expression will need to be updated. That new URL is available at: +# https://github.com/gcc-mirror/gcc/blob/6e6e3f144a33ae504149dc992453b4f6dea12fdb/contrib/download_prerequisites#L35 +# +sed -i'' 's|ftp://gcc\.gnu\.org/|https://gcc.gnu.org/|g' ./contrib/download_prerequisites + +./contrib/download_prerequisites +mkdir ../gcc-build +cd ../gcc-build + +# '-fno-reorder-blocks-and-partition' is required to +# enable BOLT optimization of the C++ standard library, +# which is included in librustc_driver.so +hide_output ../gcc-$GCC/configure \ + --prefix=/rustroot \ + --enable-languages=c,c++ \ + --disable-gnu-unique-object \ + --enable-cxx-flags='-fno-reorder-blocks-and-partition' +hide_output make -j$(nproc) +hide_output make install +ln -s gcc /rustroot/bin/cc + +cd .. +rm -rf gcc-build +rm -rf gcc-$GCC diff --git a/src/ci/docker/host-aarch64/dist-aarch64-linux/build-zstd.sh b/src/ci/docker/host-aarch64/dist-aarch64-linux/build-zstd.sh new file mode 100755 index 000000000000..a3d37ccc3112 --- /dev/null +++ b/src/ci/docker/host-aarch64/dist-aarch64-linux/build-zstd.sh @@ -0,0 +1,29 @@ +#!/bin/bash +set -ex + +hide_output() { + set +x + on_err=" +echo ERROR: An error was encountered with the build. +cat /tmp/zstd_build.log +exit 1 +" + trap "$on_err" ERR + bash -c "while true; do sleep 30; echo \$(date) - building ...; done" & + PING_LOOP_PID=$! + "$@" &> /tmp/zstd_build.log + trap - ERR + kill $PING_LOOP_PID + rm /tmp/zstd_build.log + set -x +} + +ZSTD=1.5.6 +curl -L https://github.com/facebook/zstd/releases/download/v$ZSTD/zstd-$ZSTD.tar.gz | tar xzf - + +cd zstd-$ZSTD +CFLAGS=-fPIC hide_output make -j$(nproc) VERBOSE=1 +hide_output make install + +cd .. +rm -rf zstd-$ZSTD diff --git a/src/ci/docker/host-aarch64/dist-aarch64-linux/shared.sh b/src/ci/docker/host-aarch64/dist-aarch64-linux/shared.sh new file mode 100644 index 000000000000..dc86dddd464f --- /dev/null +++ b/src/ci/docker/host-aarch64/dist-aarch64-linux/shared.sh @@ -0,0 +1,16 @@ +#!/bin/sh +hide_output() { + set +x + on_err=" +echo ERROR: An error was encountered with the build. +cat /tmp/build.log +exit 1 +" + trap "$on_err" ERR + bash -c "while true; do sleep 30; echo \$(date) - building ...; done" & + PING_LOOP_PID=$! + "$@" &> /tmp/build.log + trap - ERR + kill $PING_LOOP_PID + set -x +} diff --git a/src/ci/docker/host-x86_64/dist-aarch64-linux/Dockerfile b/src/ci/docker/host-x86_64/dist-aarch64-linux/Dockerfile deleted file mode 100644 index 18972387e34d..000000000000 --- a/src/ci/docker/host-x86_64/dist-aarch64-linux/Dockerfile +++ /dev/null @@ -1,32 +0,0 @@ -FROM ubuntu:22.04 - -COPY scripts/cross-apt-packages.sh /scripts/ -RUN sh /scripts/cross-apt-packages.sh - -COPY scripts/crosstool-ng.sh /scripts/ -RUN sh /scripts/crosstool-ng.sh - -COPY scripts/rustbuild-setup.sh /scripts/ -RUN sh /scripts/rustbuild-setup.sh -WORKDIR /tmp - -COPY scripts/crosstool-ng-build.sh /scripts/ -COPY host-x86_64/dist-aarch64-linux/aarch64-linux-gnu.defconfig /tmp/crosstool.defconfig -RUN /scripts/crosstool-ng-build.sh - -COPY scripts/sccache.sh /scripts/ -RUN sh /scripts/sccache.sh - -ENV PATH=$PATH:/x-tools/aarch64-unknown-linux-gnu/bin - -ENV CC_aarch64_unknown_linux_gnu=aarch64-unknown-linux-gnu-gcc \ - AR_aarch64_unknown_linux_gnu=aarch64-unknown-linux-gnu-ar \ - CXX_aarch64_unknown_linux_gnu=aarch64-unknown-linux-gnu-g++ - -ENV HOSTS=aarch64-unknown-linux-gnu - -ENV RUST_CONFIGURE_ARGS \ - --enable-full-tools \ - --enable-profiler \ - --enable-sanitizers -ENV SCRIPT python3 ../x.py dist --host $HOSTS --target $HOSTS diff --git a/src/ci/docker/host-x86_64/dist-aarch64-linux/aarch64-linux-gnu.defconfig b/src/ci/docker/host-x86_64/dist-aarch64-linux/aarch64-linux-gnu.defconfig deleted file mode 100644 index 520b1667c8be..000000000000 --- a/src/ci/docker/host-x86_64/dist-aarch64-linux/aarch64-linux-gnu.defconfig +++ /dev/null @@ -1,10 +0,0 @@ -CT_CONFIG_VERSION="4" -CT_PREFIX_DIR="/x-tools/${CT_TARGET}" -CT_USE_MIRROR=y -CT_MIRROR_BASE_URL="https://ci-mirrors.rust-lang.org/rustc" -CT_ARCH_ARM=y -CT_ARCH_64=y -CT_KERNEL_LINUX=y -CT_LINUX_V_4_1=y -CT_GLIBC_V_2_17=y -CT_CC_LANG_CXX=y diff --git a/src/ci/github-actions/jobs.yml b/src/ci/github-actions/jobs.yml index 24a9f843f336..d18eaa3e64b3 100644 --- a/src/ci/github-actions/jobs.yml +++ b/src/ci/github-actions/jobs.yml @@ -145,17 +145,17 @@ auto: - image: aarch64-gnu-debug <<: *job-linux-8c-aarch64 + - image: dist-aarch64-linux + env: + CODEGEN_BACKENDS: llvm,cranelift + <<: *job-linux-8c-aarch64 + - image: arm-android <<: *job-linux-4c - image: armhf-gnu <<: *job-linux-4c - - image: dist-aarch64-linux - env: - CODEGEN_BACKENDS: llvm,cranelift - <<: *job-linux-4c - - image: dist-android <<: *job-linux-4c From 3afda7e798220ce1f0764a53a3490b6614855c1c Mon Sep 17 00:00:00 2001 From: Kajetan Puchalski Date: Mon, 16 Dec 2024 15:11:37 +0000 Subject: [PATCH 50/92] ci: Organise shared helper scripts Move shared helper scripts used by Docker builds under docker/scripts. --- .../dist-aarch64-linux/Dockerfile | 11 ++-- .../dist-aarch64-linux/build-clang.sh | 46 ----------------- .../dist-aarch64-linux/build-gcc.sh | 51 ------------------- .../host-aarch64/dist-aarch64-linux/shared.sh | 16 ------ .../host-x86_64/dist-i686-linux/Dockerfile | 8 +-- .../dist-powerpc64le-linux/Dockerfile | 2 +- .../dist-powerpc64le-linux/shared.sh | 16 ------ .../host-x86_64/dist-x86_64-linux/Dockerfile | 9 ++-- .../dist-x86_64-linux/build-zstd.sh | 29 ----------- .../host-x86_64/dist-x86_64-linux/shared.sh | 16 ------ .../host-x86_64/x86_64-gnu-llvm-18/Dockerfile | 4 +- .../host-x86_64/x86_64-gnu-llvm-19/Dockerfile | 4 +- .../host-x86_64/x86_64-gnu-tools/Dockerfile | 4 +- .../build-clang.sh | 4 +- .../build-gcc.sh | 10 ++-- .../build-gccjit.sh | 0 .../build-zstd.sh | 0 17 files changed, 31 insertions(+), 199 deletions(-) delete mode 100755 src/ci/docker/host-aarch64/dist-aarch64-linux/build-clang.sh delete mode 100755 src/ci/docker/host-aarch64/dist-aarch64-linux/build-gcc.sh delete mode 100644 src/ci/docker/host-aarch64/dist-aarch64-linux/shared.sh delete mode 100644 src/ci/docker/host-x86_64/dist-powerpc64le-linux/shared.sh delete mode 100755 src/ci/docker/host-x86_64/dist-x86_64-linux/build-zstd.sh delete mode 100644 src/ci/docker/host-x86_64/dist-x86_64-linux/shared.sh rename src/ci/docker/{host-x86_64/dist-x86_64-linux => scripts}/build-clang.sh (95%) rename src/ci/docker/{host-x86_64/dist-x86_64-linux => scripts}/build-gcc.sh (87%) rename src/ci/docker/{host-x86_64/dist-x86_64-linux => scripts}/build-gccjit.sh (100%) rename src/ci/docker/{host-aarch64/dist-aarch64-linux => scripts}/build-zstd.sh (100%) diff --git a/src/ci/docker/host-aarch64/dist-aarch64-linux/Dockerfile b/src/ci/docker/host-aarch64/dist-aarch64-linux/Dockerfile index c7778dbf6bbf..4f4caa5fa50c 100644 --- a/src/ci/docker/host-aarch64/dist-aarch64-linux/Dockerfile +++ b/src/ci/docker/host-aarch64/dist-aarch64-linux/Dockerfile @@ -43,10 +43,10 @@ ENV LD_LIBRARY_PATH=/rustroot/lib64:/rustroot/lib32:/rustroot/lib ENV PKG_CONFIG_PATH=/rustroot/lib/pkgconfig WORKDIR /tmp RUN mkdir /home/user -COPY host-aarch64/dist-aarch64-linux/shared.sh /tmp/ +COPY scripts/shared.sh /tmp/ # Need at least GCC 5.1 to compile LLVM -COPY host-aarch64/dist-aarch64-linux/build-gcc.sh /tmp/ +COPY scripts/build-gcc.sh /tmp/ RUN ./build-gcc.sh && yum remove -y gcc gcc-c++ ENV CC=gcc CXX=g++ @@ -56,12 +56,13 @@ COPY scripts/cmake.sh /tmp/ RUN ./cmake.sh # Build LLVM+Clang -COPY host-aarch64/dist-aarch64-linux/build-clang.sh /tmp/ +COPY scripts/build-clang.sh /tmp/ +ENV LLVM_BUILD_TARGETS=AArch64 RUN ./build-clang.sh ENV CC=clang CXX=clang++ # Build zstd to enable `llvm.libzstd`. -COPY host-aarch64/dist-aarch64-linux/build-zstd.sh /tmp/ +COPY scripts/build-zstd.sh /tmp/ RUN ./build-zstd.sh COPY scripts/sccache.sh /scripts/ @@ -82,7 +83,7 @@ ENV RUST_CONFIGURE_ARGS \ --set target.aarch64-unknown-linux-gnu.ar=/rustroot/bin/llvm-ar \ --set target.aarch64-unknown-linux-gnu.ranlib=/rustroot/bin/llvm-ranlib \ --set llvm.link-shared=true \ - --set llvm.thin-lto=false \ + --set llvm.thin-lto=true \ --set llvm.libzstd=true \ --set llvm.ninja=false \ --set rust.debug-assertions=false \ diff --git a/src/ci/docker/host-aarch64/dist-aarch64-linux/build-clang.sh b/src/ci/docker/host-aarch64/dist-aarch64-linux/build-clang.sh deleted file mode 100755 index fb5f4d8c4f79..000000000000 --- a/src/ci/docker/host-aarch64/dist-aarch64-linux/build-clang.sh +++ /dev/null @@ -1,46 +0,0 @@ -#!/usr/bin/env bash - -set -ex - -source shared.sh - -# Try to keep the LLVM version here in sync with src/ci/scripts/install-clang.sh -LLVM=llvmorg-19.1.5 - -mkdir llvm-project -cd llvm-project - -curl -L https://github.com/llvm/llvm-project/archive/$LLVM.tar.gz | \ - tar xzf - --strip-components=1 - -mkdir clang-build -cd clang-build - -# For whatever reason the default set of include paths for clang is different -# than that of gcc. As a result we need to manually include our sysroot's -# include path, /rustroot/include, to clang's default include path. -INC="/rustroot/include:/usr/include" - -# We need compiler-rt for the profile runtime (used later to PGO the LLVM build) -# but sanitizers aren't currently building. Since we don't need those, just -# disable them. BOLT is used for optimizing LLVM. -hide_output \ - cmake ../llvm \ - -DCMAKE_BUILD_TYPE=Release \ - -DCMAKE_INSTALL_PREFIX=/rustroot \ - -DCOMPILER_RT_BUILD_SANITIZERS=OFF \ - -DCOMPILER_RT_BUILD_XRAY=OFF \ - -DCOMPILER_RT_BUILD_MEMPROF=OFF \ - -DCOMPILER_RT_BUILD_CTX_PROFILE=OFF \ - -DLLVM_TARGETS_TO_BUILD=AArch64 \ - -DLLVM_INCLUDE_BENCHMARKS=OFF \ - -DLLVM_INCLUDE_TESTS=OFF \ - -DLLVM_INCLUDE_EXAMPLES=OFF \ - -DLLVM_ENABLE_PROJECTS="clang;lld;compiler-rt;bolt" \ - -DC_INCLUDE_DIRS="$INC" - -hide_output make -j$(nproc) -hide_output make install - -cd ../.. -rm -rf llvm-project diff --git a/src/ci/docker/host-aarch64/dist-aarch64-linux/build-gcc.sh b/src/ci/docker/host-aarch64/dist-aarch64-linux/build-gcc.sh deleted file mode 100755 index ad33b21b9b5a..000000000000 --- a/src/ci/docker/host-aarch64/dist-aarch64-linux/build-gcc.sh +++ /dev/null @@ -1,51 +0,0 @@ -#!/usr/bin/env bash -set -ex - -source shared.sh - -# Note: in the future when bumping to version 10.1.0, also take care of the sed block below. -GCC=9.5.0 - -curl https://ftp.gnu.org/gnu/gcc/gcc-$GCC/gcc-$GCC.tar.xz | xzcat | tar xf - -cd gcc-$GCC - -# FIXME(#49246): Remove the `sed` below. -# -# On 2018 March 21st, two Travis builders' cache for Docker are suddenly invalidated. Normally this -# is fine, because we just need to rebuild the Docker image. However, it reveals a network issue: -# downloading from `ftp://gcc.gnu.org/` from Travis (using passive mode) often leads to "Connection -# timed out" error, and even when the download completed, the file is usually corrupted. This causes -# nothing to be landed that day. -# -# We observed that the `gcc-4.8.5.tar.bz2` above can be downloaded successfully, so as a stability -# improvement we try to download from the HTTPS mirror instead. Turns out this uncovered the third -# bug: the host `gcc.gnu.org` and `cygwin.com` share the same IP, and the TLS certificate of the -# latter host is presented to `wget`! Therefore, we choose to download from the insecure HTTP server -# instead here. -# -# Note: in version 10.1.0, the URL used in `download_prerequisites` has changed from using FTP to -# using HTTP. When bumping to that gcc version, we can likely remove the sed replacement below, or -# the expression will need to be updated. That new URL is available at: -# https://github.com/gcc-mirror/gcc/blob/6e6e3f144a33ae504149dc992453b4f6dea12fdb/contrib/download_prerequisites#L35 -# -sed -i'' 's|ftp://gcc\.gnu\.org/|https://gcc.gnu.org/|g' ./contrib/download_prerequisites - -./contrib/download_prerequisites -mkdir ../gcc-build -cd ../gcc-build - -# '-fno-reorder-blocks-and-partition' is required to -# enable BOLT optimization of the C++ standard library, -# which is included in librustc_driver.so -hide_output ../gcc-$GCC/configure \ - --prefix=/rustroot \ - --enable-languages=c,c++ \ - --disable-gnu-unique-object \ - --enable-cxx-flags='-fno-reorder-blocks-and-partition' -hide_output make -j$(nproc) -hide_output make install -ln -s gcc /rustroot/bin/cc - -cd .. -rm -rf gcc-build -rm -rf gcc-$GCC diff --git a/src/ci/docker/host-aarch64/dist-aarch64-linux/shared.sh b/src/ci/docker/host-aarch64/dist-aarch64-linux/shared.sh deleted file mode 100644 index dc86dddd464f..000000000000 --- a/src/ci/docker/host-aarch64/dist-aarch64-linux/shared.sh +++ /dev/null @@ -1,16 +0,0 @@ -#!/bin/sh -hide_output() { - set +x - on_err=" -echo ERROR: An error was encountered with the build. -cat /tmp/build.log -exit 1 -" - trap "$on_err" ERR - bash -c "while true; do sleep 30; echo \$(date) - building ...; done" & - PING_LOOP_PID=$! - "$@" &> /tmp/build.log - trap - ERR - kill $PING_LOOP_PID - set -x -} diff --git a/src/ci/docker/host-x86_64/dist-i686-linux/Dockerfile b/src/ci/docker/host-x86_64/dist-i686-linux/Dockerfile index 414bcc52484c..7cf1c80dfbc6 100644 --- a/src/ci/docker/host-x86_64/dist-i686-linux/Dockerfile +++ b/src/ci/docker/host-x86_64/dist-i686-linux/Dockerfile @@ -46,10 +46,11 @@ ENV LD_LIBRARY_PATH=/rustroot/lib64:/rustroot/lib32:/rustroot/lib ENV PKG_CONFIG_PATH=/rustroot/lib/pkgconfig WORKDIR /tmp RUN mkdir /home/user -COPY host-x86_64/dist-x86_64-linux/shared.sh /tmp/ +COPY scripts/shared.sh /tmp/ # Need at least GCC 5.1 to compile LLVM nowadays -COPY host-x86_64/dist-x86_64-linux/build-gcc.sh /tmp/ +COPY scripts/build-gcc.sh /tmp/ +ENV GCC_BUILD_TARGET=i686 RUN ./build-gcc.sh && yum remove -y gcc gcc-c++ COPY scripts/cmake.sh /tmp/ @@ -57,7 +58,8 @@ RUN ./cmake.sh # Now build LLVM+Clang, afterwards configuring further compilations to use the # clang/clang++ compilers. -COPY host-x86_64/dist-x86_64-linux/build-clang.sh /tmp/ +COPY scripts/build-clang.sh /tmp/ +ENV LLVM_BUILD_TARGETS=X86 RUN ./build-clang.sh ENV CC=clang CXX=clang++ diff --git a/src/ci/docker/host-x86_64/dist-powerpc64le-linux/Dockerfile b/src/ci/docker/host-x86_64/dist-powerpc64le-linux/Dockerfile index 9ef391892497..9d3be51d037d 100644 --- a/src/ci/docker/host-x86_64/dist-powerpc64le-linux/Dockerfile +++ b/src/ci/docker/host-x86_64/dist-powerpc64le-linux/Dockerfile @@ -18,7 +18,7 @@ RUN /scripts/crosstool-ng-build.sh WORKDIR /build RUN apt-get install -y --no-install-recommends rpm2cpio cpio -COPY host-x86_64/dist-powerpc64le-linux/shared.sh host-x86_64/dist-powerpc64le-linux/build-powerpc64le-toolchain.sh /build/ +COPY scripts/shared.sh host-x86_64/dist-powerpc64le-linux/build-powerpc64le-toolchain.sh /build/ RUN ./build-powerpc64le-toolchain.sh COPY scripts/sccache.sh /scripts/ diff --git a/src/ci/docker/host-x86_64/dist-powerpc64le-linux/shared.sh b/src/ci/docker/host-x86_64/dist-powerpc64le-linux/shared.sh deleted file mode 100644 index dc86dddd464f..000000000000 --- a/src/ci/docker/host-x86_64/dist-powerpc64le-linux/shared.sh +++ /dev/null @@ -1,16 +0,0 @@ -#!/bin/sh -hide_output() { - set +x - on_err=" -echo ERROR: An error was encountered with the build. -cat /tmp/build.log -exit 1 -" - trap "$on_err" ERR - bash -c "while true; do sleep 30; echo \$(date) - building ...; done" & - PING_LOOP_PID=$! - "$@" &> /tmp/build.log - trap - ERR - kill $PING_LOOP_PID - set -x -} diff --git a/src/ci/docker/host-x86_64/dist-x86_64-linux/Dockerfile b/src/ci/docker/host-x86_64/dist-x86_64-linux/Dockerfile index e857f38e68a8..c13c340871c9 100644 --- a/src/ci/docker/host-x86_64/dist-x86_64-linux/Dockerfile +++ b/src/ci/docker/host-x86_64/dist-x86_64-linux/Dockerfile @@ -46,10 +46,10 @@ ENV LD_LIBRARY_PATH=/rustroot/lib64:/rustroot/lib32:/rustroot/lib ENV PKG_CONFIG_PATH=/rustroot/lib/pkgconfig WORKDIR /tmp RUN mkdir /home/user -COPY host-x86_64/dist-x86_64-linux/shared.sh /tmp/ +COPY scripts/shared.sh /tmp/ # Need at least GCC 5.1 to compile LLVM nowadays -COPY host-x86_64/dist-x86_64-linux/build-gcc.sh /tmp/ +COPY scripts/build-gcc.sh /tmp/ RUN ./build-gcc.sh && yum remove -y gcc gcc-c++ # LLVM 17 needs cmake 3.20 or higher. @@ -58,12 +58,13 @@ RUN ./cmake.sh # Now build LLVM+Clang, afterwards configuring further compilations to use the # clang/clang++ compilers. -COPY host-x86_64/dist-x86_64-linux/build-clang.sh /tmp/ +COPY scripts/build-clang.sh /tmp/ +ENV LLVM_BUILD_TARGETS=X86 RUN ./build-clang.sh ENV CC=clang CXX=clang++ # Build zstd to enable `llvm.libzstd`. -COPY host-x86_64/dist-x86_64-linux/build-zstd.sh /tmp/ +COPY scripts/build-zstd.sh /tmp/ RUN ./build-zstd.sh COPY scripts/sccache.sh /scripts/ diff --git a/src/ci/docker/host-x86_64/dist-x86_64-linux/build-zstd.sh b/src/ci/docker/host-x86_64/dist-x86_64-linux/build-zstd.sh deleted file mode 100755 index a3d37ccc3112..000000000000 --- a/src/ci/docker/host-x86_64/dist-x86_64-linux/build-zstd.sh +++ /dev/null @@ -1,29 +0,0 @@ -#!/bin/bash -set -ex - -hide_output() { - set +x - on_err=" -echo ERROR: An error was encountered with the build. -cat /tmp/zstd_build.log -exit 1 -" - trap "$on_err" ERR - bash -c "while true; do sleep 30; echo \$(date) - building ...; done" & - PING_LOOP_PID=$! - "$@" &> /tmp/zstd_build.log - trap - ERR - kill $PING_LOOP_PID - rm /tmp/zstd_build.log - set -x -} - -ZSTD=1.5.6 -curl -L https://github.com/facebook/zstd/releases/download/v$ZSTD/zstd-$ZSTD.tar.gz | tar xzf - - -cd zstd-$ZSTD -CFLAGS=-fPIC hide_output make -j$(nproc) VERBOSE=1 -hide_output make install - -cd .. -rm -rf zstd-$ZSTD diff --git a/src/ci/docker/host-x86_64/dist-x86_64-linux/shared.sh b/src/ci/docker/host-x86_64/dist-x86_64-linux/shared.sh deleted file mode 100644 index dc86dddd464f..000000000000 --- a/src/ci/docker/host-x86_64/dist-x86_64-linux/shared.sh +++ /dev/null @@ -1,16 +0,0 @@ -#!/bin/sh -hide_output() { - set +x - on_err=" -echo ERROR: An error was encountered with the build. -cat /tmp/build.log -exit 1 -" - trap "$on_err" ERR - bash -c "while true; do sleep 30; echo \$(date) - building ...; done" & - PING_LOOP_PID=$! - "$@" &> /tmp/build.log - trap - ERR - kill $PING_LOOP_PID - set -x -} diff --git a/src/ci/docker/host-x86_64/x86_64-gnu-llvm-18/Dockerfile b/src/ci/docker/host-x86_64/x86_64-gnu-llvm-18/Dockerfile index 42df58517caf..1cfa22734434 100644 --- a/src/ci/docker/host-x86_64/x86_64-gnu-llvm-18/Dockerfile +++ b/src/ci/docker/host-x86_64/x86_64-gnu-llvm-18/Dockerfile @@ -54,8 +54,8 @@ ENV RUST_CONFIGURE_ARGS \ --set rust.randomize-layout=true \ --set rust.thin-lto-import-instr-limit=10 -COPY host-x86_64/dist-x86_64-linux/shared.sh /scripts/ -COPY host-x86_64/dist-x86_64-linux/build-gccjit.sh /scripts/ +COPY scripts/shared.sh /scripts/ +COPY scripts/build-gccjit.sh /scripts/ RUN /scripts/build-gccjit.sh /scripts diff --git a/src/ci/docker/host-x86_64/x86_64-gnu-llvm-19/Dockerfile b/src/ci/docker/host-x86_64/x86_64-gnu-llvm-19/Dockerfile index f2aadbe87cfe..b33cb6478afa 100644 --- a/src/ci/docker/host-x86_64/x86_64-gnu-llvm-19/Dockerfile +++ b/src/ci/docker/host-x86_64/x86_64-gnu-llvm-19/Dockerfile @@ -54,8 +54,8 @@ ENV RUST_CONFIGURE_ARGS \ --set rust.randomize-layout=true \ --set rust.thin-lto-import-instr-limit=10 -COPY host-x86_64/dist-x86_64-linux/shared.sh /scripts/ -COPY host-x86_64/dist-x86_64-linux/build-gccjit.sh /scripts/ +COPY scripts/shared.sh /scripts/ +COPY scripts/build-gccjit.sh /scripts/ RUN /scripts/build-gccjit.sh /scripts diff --git a/src/ci/docker/host-x86_64/x86_64-gnu-tools/Dockerfile b/src/ci/docker/host-x86_64/x86_64-gnu-tools/Dockerfile index 2a09cd54b139..ab749b3fdd5a 100644 --- a/src/ci/docker/host-x86_64/x86_64-gnu-tools/Dockerfile +++ b/src/ci/docker/host-x86_64/x86_64-gnu-tools/Dockerfile @@ -89,8 +89,8 @@ ENV HOST_TARGET x86_64-unknown-linux-gnu # assertions enabled! Therefore, we cannot force download CI rustc. #ENV FORCE_CI_RUSTC 1 -COPY host-x86_64/dist-x86_64-linux/shared.sh /scripts/ -COPY host-x86_64/dist-x86_64-linux/build-gccjit.sh /scripts/ +COPY scripts/shared.sh /scripts/ +COPY scripts/build-gccjit.sh /scripts/ RUN /scripts/build-gccjit.sh /scripts diff --git a/src/ci/docker/host-x86_64/dist-x86_64-linux/build-clang.sh b/src/ci/docker/scripts/build-clang.sh similarity index 95% rename from src/ci/docker/host-x86_64/dist-x86_64-linux/build-clang.sh rename to src/ci/docker/scripts/build-clang.sh index 2e08c87f278c..47bfcfbecab3 100755 --- a/src/ci/docker/host-x86_64/dist-x86_64-linux/build-clang.sh +++ b/src/ci/docker/scripts/build-clang.sh @@ -1,6 +1,6 @@ #!/usr/bin/env bash -set -ex +set -exu source shared.sh @@ -34,7 +34,7 @@ hide_output \ -DCOMPILER_RT_BUILD_XRAY=OFF \ -DCOMPILER_RT_BUILD_MEMPROF=OFF \ -DCOMPILER_RT_BUILD_CTX_PROFILE=OFF \ - -DLLVM_TARGETS_TO_BUILD=X86 \ + -DLLVM_TARGETS_TO_BUILD=$LLVM_BUILD_TARGETS \ -DLLVM_INCLUDE_BENCHMARKS=OFF \ -DLLVM_INCLUDE_TESTS=OFF \ -DLLVM_INCLUDE_EXAMPLES=OFF \ diff --git a/src/ci/docker/host-x86_64/dist-x86_64-linux/build-gcc.sh b/src/ci/docker/scripts/build-gcc.sh similarity index 87% rename from src/ci/docker/host-x86_64/dist-x86_64-linux/build-gcc.sh rename to src/ci/docker/scripts/build-gcc.sh index e939a5d7eac4..78a038215e4b 100755 --- a/src/ci/docker/host-x86_64/dist-x86_64-linux/build-gcc.sh +++ b/src/ci/docker/scripts/build-gcc.sh @@ -50,7 +50,9 @@ cd .. rm -rf gcc-build rm -rf gcc-$GCC -# FIXME: clang doesn't find 32-bit libraries in /rustroot/lib, -# but it does look all the way under /rustroot/lib/[...]/32, -# so we can link stuff there to help it out. -ln /rustroot/lib/*.{a,so} -rst /rustroot/lib/gcc/x86_64-pc-linux-gnu/$GCC/32/ +if [[ $GCC_BUILD_TARGET == "i686" ]]; then + # FIXME: clang doesn't find 32-bit libraries in /rustroot/lib, + # but it does look all the way under /rustroot/lib/[...]/32, + # so we can link stuff there to help it out. + ln /rustroot/lib/*.{a,so} -rst /rustroot/lib/gcc/x86_64-pc-linux-gnu/$GCC/32/ +fi diff --git a/src/ci/docker/host-x86_64/dist-x86_64-linux/build-gccjit.sh b/src/ci/docker/scripts/build-gccjit.sh similarity index 100% rename from src/ci/docker/host-x86_64/dist-x86_64-linux/build-gccjit.sh rename to src/ci/docker/scripts/build-gccjit.sh diff --git a/src/ci/docker/host-aarch64/dist-aarch64-linux/build-zstd.sh b/src/ci/docker/scripts/build-zstd.sh similarity index 100% rename from src/ci/docker/host-aarch64/dist-aarch64-linux/build-zstd.sh rename to src/ci/docker/scripts/build-zstd.sh From 3218476c1283af9510b284fb6e0ffad72da278cd Mon Sep 17 00:00:00 2001 From: Santiago Pastorino Date: Wed, 11 Dec 2024 18:01:19 -0300 Subject: [PATCH 51/92] Do not do if ! else, use unnegated cond and swap the branches instead --- compiler/rustc_mir_build/src/builder/misc.rs | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/compiler/rustc_mir_build/src/builder/misc.rs b/compiler/rustc_mir_build/src/builder/misc.rs index a53ae05e84f3..9ea56a9574fd 100644 --- a/compiler/rustc_mir_build/src/builder/misc.rs +++ b/compiler/rustc_mir_build/src/builder/misc.rs @@ -56,10 +56,10 @@ impl<'a, 'tcx> Builder<'a, 'tcx> { pub(crate) fn consume_by_copy_or_move(&self, place: Place<'tcx>) -> Operand<'tcx> { let tcx = self.tcx; let ty = place.ty(&self.local_decls, tcx).ty; - if !self.infcx.type_is_copy_modulo_regions(self.param_env, ty) { - Operand::Move(place) - } else { + if self.infcx.type_is_copy_modulo_regions(self.param_env, ty) { Operand::Copy(place) + } else { + Operand::Move(place) } } } From b103347753f69e1ac23ea7b8e393628352cdfb13 Mon Sep 17 00:00:00 2001 From: Oli Scherer Date: Thu, 12 Dec 2024 20:07:58 +0000 Subject: [PATCH 52/92] Remove a redundant write_ty call --- compiler/rustc_hir_typeck/src/fn_ctxt/_impl.rs | 1 - 1 file changed, 1 deletion(-) diff --git a/compiler/rustc_hir_typeck/src/fn_ctxt/_impl.rs b/compiler/rustc_hir_typeck/src/fn_ctxt/_impl.rs index d6948081505c..c3fe716163e5 100644 --- a/compiler/rustc_hir_typeck/src/fn_ctxt/_impl.rs +++ b/compiler/rustc_hir_typeck/src/fn_ctxt/_impl.rs @@ -1104,7 +1104,6 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { if let Res::Local(hid) = res { let ty = self.local_ty(span, hid); let ty = self.normalize(span, ty); - self.write_ty(hir_id, ty); return (ty, res); } From 45920d2f52e7d3025466b6207f78189d0c347d82 Mon Sep 17 00:00:00 2001 From: Oli Scherer Date: Thu, 12 Dec 2024 20:17:32 +0000 Subject: [PATCH 53/92] Remove redundant tainting. We already taint the first time we set the value --- compiler/rustc_hir_typeck/src/fn_ctxt/_impl.rs | 7 +------ 1 file changed, 1 insertion(+), 6 deletions(-) diff --git a/compiler/rustc_hir_typeck/src/fn_ctxt/_impl.rs b/compiler/rustc_hir_typeck/src/fn_ctxt/_impl.rs index c3fe716163e5..2a4914348a96 100644 --- a/compiler/rustc_hir_typeck/src/fn_ctxt/_impl.rs +++ b/compiler/rustc_hir_typeck/src/fn_ctxt/_impl.rs @@ -147,13 +147,8 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { let mut typeck = self.typeck_results.borrow_mut(); let mut node_ty = typeck.node_types_mut(); if let Some(ty) = node_ty.get(id) - && let Err(e) = ty.error_reported() + && ty.references_error() { - // Do not overwrite nodes that were already marked as `{type error}`. This allows us to - // silence unnecessary errors from obligations that were set earlier than a type error - // was produced, but that is overwritten by later analysis. This happens in particular - // for `Sized` obligations introduced in gather_locals. (#117846) - self.set_tainted_by_errors(e); return; } From 7a0b78da910a99ef07e88fb4dcc41af2367db2bd Mon Sep 17 00:00:00 2001 From: DianQK Date: Wed, 25 Sep 2024 06:42:05 +0800 Subject: [PATCH 54/92] Reapply "Auto merge of #129047 - DianQK:early_otherwise_branch_scalar, r=cjgillot" This reverts commit 16a02664e66afbfcd738b600d4a409e809040695. --- .../src/early_otherwise_branch.rs | 260 ++++++++++++------ ...wise_branch.opt5.EarlyOtherwiseBranch.diff | 77 ++++++ ...anch.opt5_failed.EarlyOtherwiseBranch.diff | 61 ++++ ...opt5_failed_type.EarlyOtherwiseBranch.diff | 61 ++++ tests/mir-opt/early_otherwise_branch.rs | 48 ++++ 5 files changed, 422 insertions(+), 85 deletions(-) create mode 100644 tests/mir-opt/early_otherwise_branch.opt5.EarlyOtherwiseBranch.diff create mode 100644 tests/mir-opt/early_otherwise_branch.opt5_failed.EarlyOtherwiseBranch.diff create mode 100644 tests/mir-opt/early_otherwise_branch.opt5_failed_type.EarlyOtherwiseBranch.diff diff --git a/compiler/rustc_mir_transform/src/early_otherwise_branch.rs b/compiler/rustc_mir_transform/src/early_otherwise_branch.rs index 17c8348140a3..2f2d07c739c6 100644 --- a/compiler/rustc_mir_transform/src/early_otherwise_branch.rs +++ b/compiler/rustc_mir_transform/src/early_otherwise_branch.rs @@ -129,18 +129,29 @@ impl<'tcx> crate::MirPass<'tcx> for EarlyOtherwiseBranch { let mut patch = MirPatch::new(body); - // create temp to store second discriminant in, `_s` in example above - let second_discriminant_temp = - patch.new_temp(opt_data.child_ty, opt_data.child_source.span); + let (second_discriminant_temp, second_operand) = if opt_data.need_hoist_discriminant { + // create temp to store second discriminant in, `_s` in example above + let second_discriminant_temp = + patch.new_temp(opt_data.child_ty, opt_data.child_source.span); - patch.add_statement(parent_end, StatementKind::StorageLive(second_discriminant_temp)); + patch.add_statement( + parent_end, + StatementKind::StorageLive(second_discriminant_temp), + ); - // create assignment of discriminant - patch.add_assign( - parent_end, - Place::from(second_discriminant_temp), - Rvalue::Discriminant(opt_data.child_place), - ); + // create assignment of discriminant + patch.add_assign( + parent_end, + Place::from(second_discriminant_temp), + Rvalue::Discriminant(opt_data.child_place), + ); + ( + Some(second_discriminant_temp), + Operand::Move(Place::from(second_discriminant_temp)), + ) + } else { + (None, Operand::Copy(opt_data.child_place)) + }; // create temp to store inequality comparison between the two discriminants, `_t` in // example above @@ -149,11 +160,9 @@ impl<'tcx> crate::MirPass<'tcx> for EarlyOtherwiseBranch { let comp_temp = patch.new_temp(comp_res_type, opt_data.child_source.span); patch.add_statement(parent_end, StatementKind::StorageLive(comp_temp)); - // create inequality comparison between the two discriminants - let comp_rvalue = Rvalue::BinaryOp( - nequal, - Box::new((parent_op.clone(), Operand::Move(Place::from(second_discriminant_temp)))), - ); + // create inequality comparison + let comp_rvalue = + Rvalue::BinaryOp(nequal, Box::new((parent_op.clone(), second_operand))); patch.add_statement( parent_end, StatementKind::Assign(Box::new((Place::from(comp_temp), comp_rvalue))), @@ -189,8 +198,13 @@ impl<'tcx> crate::MirPass<'tcx> for EarlyOtherwiseBranch { TerminatorKind::if_(Operand::Move(Place::from(comp_temp)), true_case, false_case), ); - // generate StorageDead for the second_discriminant_temp not in use anymore - patch.add_statement(parent_end, StatementKind::StorageDead(second_discriminant_temp)); + if let Some(second_discriminant_temp) = second_discriminant_temp { + // generate StorageDead for the second_discriminant_temp not in use anymore + patch.add_statement( + parent_end, + StatementKind::StorageDead(second_discriminant_temp), + ); + } // Generate a StorageDead for comp_temp in each of the targets, since we moved it into // the switch @@ -218,6 +232,7 @@ struct OptimizationData<'tcx> { child_place: Place<'tcx>, child_ty: Ty<'tcx>, child_source: SourceInfo, + need_hoist_discriminant: bool, } fn evaluate_candidate<'tcx>( @@ -231,44 +246,12 @@ fn evaluate_candidate<'tcx>( return None; }; let parent_ty = parent_discr.ty(body.local_decls(), tcx); - if !bbs[targets.otherwise()].is_empty_unreachable() { - // Someone could write code like this: - // ```rust - // let Q = val; - // if discriminant(P) == otherwise { - // let ptr = &mut Q as *mut _ as *mut u8; - // // It may be difficult for us to effectively determine whether values are valid. - // // Invalid values can come from all sorts of corners. - // unsafe { *ptr = 10; } - // } - // - // match P { - // A => match Q { - // A => { - // // code - // } - // _ => { - // // don't use Q - // } - // } - // _ => { - // // don't use Q - // } - // }; - // ``` - // - // Hoisting the `discriminant(Q)` out of the `A` arm causes us to compute the discriminant - // of an invalid value, which is UB. - // In order to fix this, **we would either need to show that the discriminant computation of - // `place` is computed in all branches**. - // FIXME(#95162) For the moment, we adopt a conservative approach and - // consider only the `otherwise` branch has no statements and an unreachable terminator. - return None; - } let (_, child) = targets.iter().next()?; - let child_terminator = &bbs[child].terminator(); - let TerminatorKind::SwitchInt { targets: child_targets, discr: child_discr } = - &child_terminator.kind + + let Terminator { + kind: TerminatorKind::SwitchInt { targets: child_targets, discr: child_discr }, + source_info, + } = bbs[child].terminator() else { return None; }; @@ -276,25 +259,115 @@ fn evaluate_candidate<'tcx>( if child_ty != parent_ty { return None; } - let Some(StatementKind::Assign(boxed)) = &bbs[child].statements.first().map(|x| &x.kind) else { + + // We only handle: + // ``` + // bb4: { + // _8 = discriminant((_3.1: Enum1)); + // switchInt(move _8) -> [2: bb7, otherwise: bb1]; + // } + // ``` + // and + // ``` + // bb2: { + // switchInt((_3.1: u64)) -> [1: bb5, otherwise: bb1]; + // } + // ``` + if bbs[child].statements.len() > 1 { return None; + } + + // When thie BB has exactly one statement, this statement should be discriminant. + let need_hoist_discriminant = bbs[child].statements.len() == 1; + let child_place = if need_hoist_discriminant { + if !bbs[targets.otherwise()].is_empty_unreachable() { + // Someone could write code like this: + // ```rust + // let Q = val; + // if discriminant(P) == otherwise { + // let ptr = &mut Q as *mut _ as *mut u8; + // // It may be difficult for us to effectively determine whether values are valid. + // // Invalid values can come from all sorts of corners. + // unsafe { *ptr = 10; } + // } + // + // match P { + // A => match Q { + // A => { + // // code + // } + // _ => { + // // don't use Q + // } + // } + // _ => { + // // don't use Q + // } + // }; + // ``` + // + // Hoisting the `discriminant(Q)` out of the `A` arm causes us to compute the discriminant of an + // invalid value, which is UB. + // In order to fix this, **we would either need to show that the discriminant computation of + // `place` is computed in all branches**. + // FIXME(#95162) For the moment, we adopt a conservative approach and + // consider only the `otherwise` branch has no statements and an unreachable terminator. + return None; + } + // Handle: + // ``` + // bb4: { + // _8 = discriminant((_3.1: Enum1)); + // switchInt(move _8) -> [2: bb7, otherwise: bb1]; + // } + // ``` + let [ + Statement { + kind: StatementKind::Assign(box (_, Rvalue::Discriminant(child_place))), + .. + }, + ] = bbs[child].statements.as_slice() + else { + return None; + }; + *child_place + } else { + // Handle: + // ``` + // bb2: { + // switchInt((_3.1: u64)) -> [1: bb5, otherwise: bb1]; + // } + // ``` + let Operand::Copy(child_place) = child_discr else { + return None; + }; + *child_place }; - let (_, Rvalue::Discriminant(child_place)) = &**boxed else { - return None; + let destination = if need_hoist_discriminant || bbs[targets.otherwise()].is_empty_unreachable() + { + child_targets.otherwise() + } else { + targets.otherwise() }; - let destination = child_targets.otherwise(); // Verify that the optimization is legal for each branch for (value, child) in targets.iter() { - if !verify_candidate_branch(&bbs[child], value, *child_place, destination) { + if !verify_candidate_branch( + &bbs[child], + value, + child_place, + destination, + need_hoist_discriminant, + ) { return None; } } Some(OptimizationData { destination, - child_place: *child_place, + child_place, child_ty, - child_source: child_terminator.source_info, + child_source: *source_info, + need_hoist_discriminant, }) } @@ -303,31 +376,48 @@ fn verify_candidate_branch<'tcx>( value: u128, place: Place<'tcx>, destination: BasicBlock, + need_hoist_discriminant: bool, ) -> bool { - // In order for the optimization to be correct, the branch must... - // ...have exactly one statement - if let [statement] = branch.statements.as_slice() - // ...assign the discriminant of `place` in that statement - && let StatementKind::Assign(boxed) = &statement.kind - && let (discr_place, Rvalue::Discriminant(from_place)) = &**boxed - && *from_place == place - // ...make that assignment to a local - && discr_place.projection.is_empty() - // ...terminate on a `SwitchInt` that invalidates that local - && let TerminatorKind::SwitchInt { discr: switch_op, targets, .. } = - &branch.terminator().kind - && *switch_op == Operand::Move(*discr_place) - // ...fall through to `destination` if the switch misses - && destination == targets.otherwise() - // ...have a branch for value `value` - && let mut iter = targets.iter() - && let Some((target_value, _)) = iter.next() - && target_value == value - // ...and have no more branches - && iter.next().is_none() - { - true + // In order for the optimization to be correct, the terminator must be a `SwitchInt`. + let TerminatorKind::SwitchInt { discr: switch_op, targets } = &branch.terminator().kind else { + return false; + }; + if need_hoist_discriminant { + // If we need hoist discriminant, the branch must have exactly one statement. + let [statement] = branch.statements.as_slice() else { + return false; + }; + // The statement must assign the discriminant of `place`. + let StatementKind::Assign(box (discr_place, Rvalue::Discriminant(from_place))) = + statement.kind + else { + return false; + }; + if from_place != place { + return false; + } + // The assignment must invalidate a local that terminate on a `SwitchInt`. + if !discr_place.projection.is_empty() || *switch_op != Operand::Move(discr_place) { + return false; + } } else { - false + // If we don't need hoist discriminant, the branch must not have any statements. + if !branch.statements.is_empty() { + return false; + } + // The place on `SwitchInt` must be the same. + if *switch_op != Operand::Copy(place) { + return false; + } } + // It must fall through to `destination` if the switch misses. + if destination != targets.otherwise() { + return false; + } + // It must have exactly one branch for value `value` and have no more branches. + let mut iter = targets.iter(); + let (Some((target_value, _)), None) = (iter.next(), iter.next()) else { + return false; + }; + target_value == value } diff --git a/tests/mir-opt/early_otherwise_branch.opt5.EarlyOtherwiseBranch.diff b/tests/mir-opt/early_otherwise_branch.opt5.EarlyOtherwiseBranch.diff new file mode 100644 index 000000000000..b7447ef0c469 --- /dev/null +++ b/tests/mir-opt/early_otherwise_branch.opt5.EarlyOtherwiseBranch.diff @@ -0,0 +1,77 @@ +- // MIR for `opt5` before EarlyOtherwiseBranch ++ // MIR for `opt5` after EarlyOtherwiseBranch + + fn opt5(_1: u32, _2: u32) -> u32 { + debug x => _1; + debug y => _2; + let mut _0: u32; + let mut _3: (u32, u32); + let mut _4: u32; + let mut _5: u32; ++ let mut _6: bool; + + bb0: { + StorageLive(_3); + StorageLive(_4); + _4 = copy _1; + StorageLive(_5); + _5 = copy _2; + _3 = (move _4, move _5); + StorageDead(_5); + StorageDead(_4); +- switchInt(copy (_3.0: u32)) -> [1: bb2, 2: bb3, 3: bb4, otherwise: bb1]; ++ StorageLive(_6); ++ _6 = Ne(copy (_3.0: u32), copy (_3.1: u32)); ++ switchInt(move _6) -> [0: bb6, otherwise: bb1]; + } + + bb1: { ++ StorageDead(_6); + _0 = const 0_u32; +- goto -> bb8; ++ goto -> bb5; + } + + bb2: { +- switchInt(copy (_3.1: u32)) -> [1: bb7, otherwise: bb1]; ++ _0 = const 6_u32; ++ goto -> bb5; + } + + bb3: { +- switchInt(copy (_3.1: u32)) -> [2: bb6, otherwise: bb1]; ++ _0 = const 5_u32; ++ goto -> bb5; + } + + bb4: { +- switchInt(copy (_3.1: u32)) -> [3: bb5, otherwise: bb1]; ++ _0 = const 4_u32; ++ goto -> bb5; + } + + bb5: { +- _0 = const 6_u32; +- goto -> bb8; ++ StorageDead(_3); ++ return; + } + + bb6: { +- _0 = const 5_u32; +- goto -> bb8; +- } +- +- bb7: { +- _0 = const 4_u32; +- goto -> bb8; +- } +- +- bb8: { +- StorageDead(_3); +- return; ++ StorageDead(_6); ++ switchInt(copy (_3.0: u32)) -> [1: bb4, 2: bb3, 3: bb2, otherwise: bb1]; + } + } + diff --git a/tests/mir-opt/early_otherwise_branch.opt5_failed.EarlyOtherwiseBranch.diff b/tests/mir-opt/early_otherwise_branch.opt5_failed.EarlyOtherwiseBranch.diff new file mode 100644 index 000000000000..af16271f8b1a --- /dev/null +++ b/tests/mir-opt/early_otherwise_branch.opt5_failed.EarlyOtherwiseBranch.diff @@ -0,0 +1,61 @@ +- // MIR for `opt5_failed` before EarlyOtherwiseBranch ++ // MIR for `opt5_failed` after EarlyOtherwiseBranch + + fn opt5_failed(_1: u32, _2: u32) -> u32 { + debug x => _1; + debug y => _2; + let mut _0: u32; + let mut _3: (u32, u32); + let mut _4: u32; + let mut _5: u32; + + bb0: { + StorageLive(_3); + StorageLive(_4); + _4 = copy _1; + StorageLive(_5); + _5 = copy _2; + _3 = (move _4, move _5); + StorageDead(_5); + StorageDead(_4); + switchInt(copy (_3.0: u32)) -> [1: bb2, 2: bb3, 3: bb4, otherwise: bb1]; + } + + bb1: { + _0 = const 0_u32; + goto -> bb8; + } + + bb2: { + switchInt(copy (_3.1: u32)) -> [1: bb7, otherwise: bb1]; + } + + bb3: { + switchInt(copy (_3.1: u32)) -> [2: bb6, otherwise: bb1]; + } + + bb4: { + switchInt(copy (_3.1: u32)) -> [2: bb5, otherwise: bb1]; + } + + bb5: { + _0 = const 6_u32; + goto -> bb8; + } + + bb6: { + _0 = const 5_u32; + goto -> bb8; + } + + bb7: { + _0 = const 4_u32; + goto -> bb8; + } + + bb8: { + StorageDead(_3); + return; + } + } + diff --git a/tests/mir-opt/early_otherwise_branch.opt5_failed_type.EarlyOtherwiseBranch.diff b/tests/mir-opt/early_otherwise_branch.opt5_failed_type.EarlyOtherwiseBranch.diff new file mode 100644 index 000000000000..23f14b843b37 --- /dev/null +++ b/tests/mir-opt/early_otherwise_branch.opt5_failed_type.EarlyOtherwiseBranch.diff @@ -0,0 +1,61 @@ +- // MIR for `opt5_failed_type` before EarlyOtherwiseBranch ++ // MIR for `opt5_failed_type` after EarlyOtherwiseBranch + + fn opt5_failed_type(_1: u32, _2: u64) -> u32 { + debug x => _1; + debug y => _2; + let mut _0: u32; + let mut _3: (u32, u64); + let mut _4: u32; + let mut _5: u64; + + bb0: { + StorageLive(_3); + StorageLive(_4); + _4 = copy _1; + StorageLive(_5); + _5 = copy _2; + _3 = (move _4, move _5); + StorageDead(_5); + StorageDead(_4); + switchInt(copy (_3.0: u32)) -> [1: bb2, 2: bb3, 3: bb4, otherwise: bb1]; + } + + bb1: { + _0 = const 0_u32; + goto -> bb8; + } + + bb2: { + switchInt(copy (_3.1: u64)) -> [1: bb7, otherwise: bb1]; + } + + bb3: { + switchInt(copy (_3.1: u64)) -> [2: bb6, otherwise: bb1]; + } + + bb4: { + switchInt(copy (_3.1: u64)) -> [3: bb5, otherwise: bb1]; + } + + bb5: { + _0 = const 6_u32; + goto -> bb8; + } + + bb6: { + _0 = const 5_u32; + goto -> bb8; + } + + bb7: { + _0 = const 4_u32; + goto -> bb8; + } + + bb8: { + StorageDead(_3); + return; + } + } + diff --git a/tests/mir-opt/early_otherwise_branch.rs b/tests/mir-opt/early_otherwise_branch.rs index 47bd4be295b0..382c38ceb3ab 100644 --- a/tests/mir-opt/early_otherwise_branch.rs +++ b/tests/mir-opt/early_otherwise_branch.rs @@ -78,9 +78,57 @@ fn opt4(x: Option2, y: Option2) -> u32 { } } +// EMIT_MIR early_otherwise_branch.opt5.EarlyOtherwiseBranch.diff +fn opt5(x: u32, y: u32) -> u32 { + // CHECK-LABEL: fn opt5( + // CHECK: let mut [[CMP_LOCAL:_.*]]: bool; + // CHECK: bb0: { + // CHECK: [[CMP_LOCAL]] = Ne( + // CHECK: switchInt(move [[CMP_LOCAL]]) -> [ + // CHECK-NEXT: } + match (x, y) { + (1, 1) => 4, + (2, 2) => 5, + (3, 3) => 6, + _ => 0, + } +} + +// EMIT_MIR early_otherwise_branch.opt5_failed.EarlyOtherwiseBranch.diff +fn opt5_failed(x: u32, y: u32) -> u32 { + // CHECK-LABEL: fn opt5_failed( + // CHECK: bb0: { + // CHECK-NOT: Ne( + // CHECK: switchInt( + // CHECK-NEXT: } + match (x, y) { + (1, 1) => 4, + (2, 2) => 5, + (3, 2) => 6, + _ => 0, + } +} + +// EMIT_MIR early_otherwise_branch.opt5_failed_type.EarlyOtherwiseBranch.diff +fn opt5_failed_type(x: u32, y: u64) -> u32 { + // CHECK-LABEL: fn opt5_failed_type( + // CHECK: bb0: { + // CHECK-NOT: Ne( + // CHECK: switchInt( + // CHECK-NEXT: } + match (x, y) { + (1, 1) => 4, + (2, 2) => 5, + (3, 3) => 6, + _ => 0, + } +} + fn main() { opt1(None, Some(0)); opt2(None, Some(0)); opt3(Option2::None, Option2::Some(false)); opt4(Option2::None, Option2::Some(0)); + opt5(0, 0); + opt5_failed(0, 0); } From 15fa788cc3968d3ee3d41282bcdc1d2542f35859 Mon Sep 17 00:00:00 2001 From: DianQK Date: Tue, 24 Sep 2024 22:51:36 +0800 Subject: [PATCH 55/92] mir-opt: a sub-BB of a cleanup BB must also be a cleanup BB --- .../src/early_otherwise_branch.rs | 3 +- ...anch_unwind.poll.EarlyOtherwiseBranch.diff | 142 ++++++++++++++++++ .../mir-opt/early_otherwise_branch_unwind.rs | 43 ++++++ ...ch_unwind.unwind.EarlyOtherwiseBranch.diff | 135 +++++++++++++++++ 4 files changed, 322 insertions(+), 1 deletion(-) create mode 100644 tests/mir-opt/early_otherwise_branch_unwind.poll.EarlyOtherwiseBranch.diff create mode 100644 tests/mir-opt/early_otherwise_branch_unwind.rs create mode 100644 tests/mir-opt/early_otherwise_branch_unwind.unwind.EarlyOtherwiseBranch.diff diff --git a/compiler/rustc_mir_transform/src/early_otherwise_branch.rs b/compiler/rustc_mir_transform/src/early_otherwise_branch.rs index 2f2d07c739c6..be6056250fde 100644 --- a/compiler/rustc_mir_transform/src/early_otherwise_branch.rs +++ b/compiler/rustc_mir_transform/src/early_otherwise_branch.rs @@ -179,7 +179,7 @@ impl<'tcx> crate::MirPass<'tcx> for EarlyOtherwiseBranch { let eq_targets = SwitchTargets::new(eq_new_targets, parent_targets.otherwise()); // Create `bbEq` in example above - let eq_switch = BasicBlockData::new(Some(Terminator { + let mut eq_switch = BasicBlockData::new(Some(Terminator { source_info: bbs[parent].terminator().source_info, kind: TerminatorKind::SwitchInt { // switch on the first discriminant, so we can mark the second one as dead @@ -187,6 +187,7 @@ impl<'tcx> crate::MirPass<'tcx> for EarlyOtherwiseBranch { targets: eq_targets, }, })); + eq_switch.is_cleanup = bbs[parent].is_cleanup; let eq_bb = patch.new_block(eq_switch); diff --git a/tests/mir-opt/early_otherwise_branch_unwind.poll.EarlyOtherwiseBranch.diff b/tests/mir-opt/early_otherwise_branch_unwind.poll.EarlyOtherwiseBranch.diff new file mode 100644 index 000000000000..5f03b94ccb8d --- /dev/null +++ b/tests/mir-opt/early_otherwise_branch_unwind.poll.EarlyOtherwiseBranch.diff @@ -0,0 +1,142 @@ +- // MIR for `poll` before EarlyOtherwiseBranch ++ // MIR for `poll` after EarlyOtherwiseBranch + + fn poll(_1: Poll>, u8>>) -> () { + debug val => _1; + let mut _0: (); + let mut _2: isize; + let mut _3: isize; + let mut _4: isize; + let _5: std::vec::Vec; + let _6: u8; + let mut _7: bool; + let mut _8: bool; + let mut _9: isize; ++ let mut _10: bool; + scope 1 { + debug _trailers => _5; + } + scope 2 { + debug _err => _6; + } + + bb0: { + _7 = const false; + _8 = const false; + _7 = const true; + _8 = const true; + _4 = discriminant(_1); + switchInt(copy _4) -> [0: bb2, 1: bb4, otherwise: bb1]; + } + + bb1: { + unreachable; + } + + bb2: { + _3 = discriminant(((_1 as Ready).0: std::result::Result>, u8>)); + switchInt(copy _3) -> [0: bb3, 1: bb6, otherwise: bb1]; + } + + bb3: { + _2 = discriminant(((((_1 as Ready).0: std::result::Result>, u8>) as Ok).0: std::option::Option>)); + switchInt(copy _2) -> [0: bb5, 1: bb7, otherwise: bb1]; + } + + bb4: { + _0 = const (); +- goto -> bb17; ++ goto -> bb15; + } + + bb5: { + _0 = const (); +- goto -> bb17; ++ goto -> bb15; + } + + bb6: { + StorageLive(_6); + _6 = copy ((((_1 as Ready).0: std::result::Result>, u8>) as Err).0: u8); + _0 = const (); + StorageDead(_6); +- goto -> bb17; ++ goto -> bb15; + } + + bb7: { + StorageLive(_5); + _5 = move ((((((_1 as Ready).0: std::result::Result>, u8>) as Ok).0: std::option::Option>) as Some).0: std::vec::Vec); + _0 = const (); +- drop(_5) -> [return: bb8, unwind: bb20]; ++ drop(_5) -> [return: bb8, unwind: bb16]; + } + + bb8: { + StorageDead(_5); +- goto -> bb17; ++ goto -> bb15; + } + + bb9 (cleanup): { ++ StorageDead(_10); + resume; + } + + bb10: { + return; + } + + bb11: { +- switchInt(copy _7) -> [0: bb12, otherwise: bb16]; ++ switchInt(copy _7) -> [0: bb12, otherwise: bb14]; + } + + bb12: { + _7 = const false; + goto -> bb10; + } + + bb13: { +- switchInt(copy _8) -> [0: bb14, otherwise: bb15]; +- } +- +- bb14: { + _8 = const false; + goto -> bb12; + } + +- bb15: { +- goto -> bb14; +- } +- +- bb16: { ++ bb14: { + _9 = discriminant(((_1 as Ready).0: std::result::Result>, u8>)); + switchInt(move _9) -> [0: bb13, otherwise: bb12]; + } + +- bb17: { ++ bb15: { + switchInt(copy _4) -> [0: bb11, otherwise: bb10]; + } + +- bb18 (cleanup): { +- switchInt(copy _3) -> [0: bb19, otherwise: bb9]; ++ bb16 (cleanup): { ++ StorageLive(_10); ++ _10 = Ne(copy _4, copy _3); ++ switchInt(move _10) -> [0: bb17, otherwise: bb9]; + } + +- bb19 (cleanup): { ++ bb17 (cleanup): { ++ StorageDead(_10); + goto -> bb9; +- } +- +- bb20 (cleanup): { +- switchInt(copy _4) -> [0: bb18, otherwise: bb9]; + } + } + diff --git a/tests/mir-opt/early_otherwise_branch_unwind.rs b/tests/mir-opt/early_otherwise_branch_unwind.rs new file mode 100644 index 000000000000..7df58c7a64fb --- /dev/null +++ b/tests/mir-opt/early_otherwise_branch_unwind.rs @@ -0,0 +1,43 @@ +//@ test-mir-pass: EarlyOtherwiseBranch +//@ compile-flags: -Zmir-enable-passes=+GVN,+SimplifyLocals-after-value-numbering +//@ needs-unwind + +use std::task::Poll; + +// We find a matching pattern in the unwind path, +// and we need to create a cleanup BB for this case to meet the unwind invariants rule. + +// EMIT_MIR early_otherwise_branch_unwind.unwind.EarlyOtherwiseBranch.diff +fn unwind(val: Option>>) { + // CHECK-LABEL: fn unwind( + // CHECK: drop({{.*}}) -> [return: bb{{.*}}, unwind: [[PARENT_UNWIND_BB:bb.*]]]; + // CHECK: [[PARENT_UNWIND_BB]] (cleanup): { + // CHECK-NEXT: StorageLive + // CHECK-NEXT: [[CMP_LOCAL:_.*]] = Ne + // CHECK-NEXT: switchInt(move [[CMP_LOCAL]]) -> [0: [[NEW_UNWIND_BB:bb.*]], otherwise + // CHECK: [[NEW_UNWIND_BB]] (cleanup): { + match val { + Some(Some(Some(_v))) => {} + Some(Some(None)) => {} + Some(None) => {} + None => {} + } +} + +// From https://github.com/rust-lang/rust/issues/130769#issuecomment-2370443086. +// EMIT_MIR early_otherwise_branch_unwind.poll.EarlyOtherwiseBranch.diff +pub fn poll(val: Poll>, u8>>) { + // CHECK-LABEL: fn poll( + // CHECK: drop({{.*}}) -> [return: bb{{.*}}, unwind: [[PARENT_UNWIND_BB:bb.*]]]; + // CHECK: [[PARENT_UNWIND_BB]] (cleanup): { + // CHECK-NEXT: StorageLive + // CHECK-NEXT: [[CMP_LOCAL:_.*]] = Ne + // CHECK-NEXT: switchInt(move [[CMP_LOCAL]]) -> [0: [[NEW_UNWIND_BB:bb.*]], otherwise + // CHECK: [[NEW_UNWIND_BB]] (cleanup): { + match val { + Poll::Ready(Ok(Some(_trailers))) => {} + Poll::Ready(Err(_err)) => {} + Poll::Ready(Ok(None)) => {} + Poll::Pending => {} + } +} diff --git a/tests/mir-opt/early_otherwise_branch_unwind.unwind.EarlyOtherwiseBranch.diff b/tests/mir-opt/early_otherwise_branch_unwind.unwind.EarlyOtherwiseBranch.diff new file mode 100644 index 000000000000..1405b9d314a3 --- /dev/null +++ b/tests/mir-opt/early_otherwise_branch_unwind.unwind.EarlyOtherwiseBranch.diff @@ -0,0 +1,135 @@ +- // MIR for `unwind` before EarlyOtherwiseBranch ++ // MIR for `unwind` after EarlyOtherwiseBranch + + fn unwind(_1: Option>>) -> () { + debug val => _1; + let mut _0: (); + let mut _2: isize; + let mut _3: isize; + let mut _4: isize; + let _5: T; + let mut _6: bool; + let mut _7: bool; + let mut _8: isize; ++ let mut _9: bool; + scope 1 { + debug _v => _5; + } + + bb0: { + _6 = const false; + _7 = const false; + _6 = const true; + _7 = const true; + _4 = discriminant(_1); + switchInt(copy _4) -> [0: bb4, 1: bb2, otherwise: bb1]; + } + + bb1: { + unreachable; + } + + bb2: { + _3 = discriminant(((_1 as Some).0: std::option::Option>)); + switchInt(copy _3) -> [0: bb5, 1: bb3, otherwise: bb1]; + } + + bb3: { + _2 = discriminant(((((_1 as Some).0: std::option::Option>) as Some).0: std::option::Option)); + switchInt(copy _2) -> [0: bb6, 1: bb7, otherwise: bb1]; + } + + bb4: { + _0 = const (); +- goto -> bb17; ++ goto -> bb15; + } + + bb5: { + _0 = const (); +- goto -> bb17; ++ goto -> bb15; + } + + bb6: { + _0 = const (); +- goto -> bb17; ++ goto -> bb15; + } + + bb7: { + StorageLive(_5); + _5 = move ((((((_1 as Some).0: std::option::Option>) as Some).0: std::option::Option) as Some).0: T); + _0 = const (); +- drop(_5) -> [return: bb8, unwind: bb20]; ++ drop(_5) -> [return: bb8, unwind: bb16]; + } + + bb8: { + StorageDead(_5); +- goto -> bb17; ++ goto -> bb15; + } + + bb9 (cleanup): { ++ StorageDead(_9); + resume; + } + + bb10: { + return; + } + + bb11: { +- switchInt(copy _6) -> [0: bb12, otherwise: bb16]; ++ switchInt(copy _6) -> [0: bb12, otherwise: bb14]; + } + + bb12: { + _6 = const false; + goto -> bb10; + } + + bb13: { +- switchInt(copy _7) -> [0: bb14, otherwise: bb15]; +- } +- +- bb14: { + _7 = const false; + goto -> bb12; + } + +- bb15: { +- goto -> bb14; +- } +- +- bb16: { ++ bb14: { + _8 = discriminant(((_1 as Some).0: std::option::Option>)); + switchInt(move _8) -> [1: bb13, otherwise: bb12]; + } + +- bb17: { ++ bb15: { + switchInt(copy _4) -> [1: bb11, otherwise: bb10]; + } + +- bb18 (cleanup): { +- switchInt(copy _3) -> [1: bb19, otherwise: bb9]; ++ bb16 (cleanup): { ++ StorageLive(_9); ++ _9 = Ne(copy _4, copy _3); ++ switchInt(move _9) -> [0: bb17, otherwise: bb9]; + } + +- bb19 (cleanup): { ++ bb17 (cleanup): { ++ StorageDead(_9); + goto -> bb9; +- } +- +- bb20 (cleanup): { +- switchInt(copy _4) -> [1: bb18, otherwise: bb9]; + } + } + From 93aea1d0feee7342ef199af44c1e12f7274a3fc6 Mon Sep 17 00:00:00 2001 From: DianQK Date: Tue, 24 Sep 2024 22:26:19 +0800 Subject: [PATCH 56/92] mir: require `is_cleanup` when creating `BasicBlockData` --- compiler/rustc_middle/src/mir/mod.rs | 4 ++-- compiler/rustc_mir_build/src/builder/cfg.rs | 2 +- .../rustc_mir_build/src/builder/custom/mod.rs | 2 +- .../src/builder/custom/parse.rs | 13 ++++++------ .../src/early_otherwise_branch.rs | 20 ++++++++++--------- compiler/rustc_mir_transform/src/inline.rs | 12 ++++++----- .../src/shim/async_destructor_ctor.rs | 2 +- 7 files changed, 30 insertions(+), 25 deletions(-) diff --git a/compiler/rustc_middle/src/mir/mod.rs b/compiler/rustc_middle/src/mir/mod.rs index 7f3239fa57ae..98ef7d58a502 100644 --- a/compiler/rustc_middle/src/mir/mod.rs +++ b/compiler/rustc_middle/src/mir/mod.rs @@ -1348,8 +1348,8 @@ pub struct BasicBlockData<'tcx> { } impl<'tcx> BasicBlockData<'tcx> { - pub fn new(terminator: Option>) -> BasicBlockData<'tcx> { - BasicBlockData { statements: vec![], terminator, is_cleanup: false } + pub fn new(terminator: Option>, is_cleanup: bool) -> BasicBlockData<'tcx> { + BasicBlockData { statements: vec![], terminator, is_cleanup } } /// Accessor for terminator. diff --git a/compiler/rustc_mir_build/src/builder/cfg.rs b/compiler/rustc_mir_build/src/builder/cfg.rs index cca309115ba8..42212f2518b0 100644 --- a/compiler/rustc_mir_build/src/builder/cfg.rs +++ b/compiler/rustc_mir_build/src/builder/cfg.rs @@ -19,7 +19,7 @@ impl<'tcx> CFG<'tcx> { // it as #[inline(never)] to keep rustc's stack use in check. #[inline(never)] pub(crate) fn start_new_block(&mut self) -> BasicBlock { - self.basic_blocks.push(BasicBlockData::new(None)) + self.basic_blocks.push(BasicBlockData::new(None, false)) } pub(crate) fn start_new_cleanup_block(&mut self) -> BasicBlock { diff --git a/compiler/rustc_mir_build/src/builder/custom/mod.rs b/compiler/rustc_mir_build/src/builder/custom/mod.rs index 34cdc288f0ba..ca2e1dd7a1a8 100644 --- a/compiler/rustc_mir_build/src/builder/custom/mod.rs +++ b/compiler/rustc_mir_build/src/builder/custom/mod.rs @@ -64,7 +64,7 @@ pub(super) fn build_custom_mir<'tcx>( }; body.local_decls.push(LocalDecl::new(return_ty, return_ty_span)); - body.basic_blocks_mut().push(BasicBlockData::new(None)); + body.basic_blocks_mut().push(BasicBlockData::new(None, false)); body.source_scopes.push(SourceScopeData { span, parent_scope: None, diff --git a/compiler/rustc_mir_build/src/builder/custom/parse.rs b/compiler/rustc_mir_build/src/builder/custom/parse.rs index 538068e1fac8..91e284604b68 100644 --- a/compiler/rustc_mir_build/src/builder/custom/parse.rs +++ b/compiler/rustc_mir_build/src/builder/custom/parse.rs @@ -199,10 +199,12 @@ impl<'a, 'tcx> ParseCtxt<'a, 'tcx> { match &self.thir[stmt].kind { StmtKind::Let { pattern, initializer: Some(initializer), .. } => { let (var, ..) = self.parse_var(pattern)?; - let mut data = BasicBlockData::new(None); - data.is_cleanup = parse_by_kind!(self, *initializer, _, "basic block declaration", - @variant(mir_basic_block, Normal) => false, - @variant(mir_basic_block, Cleanup) => true, + let data = BasicBlockData::new( + None, + parse_by_kind!(self, *initializer, _, "basic block declaration", + @variant(mir_basic_block, Normal) => false, + @variant(mir_basic_block, Cleanup) => true, + ), ); let block = self.body.basic_blocks_mut().push(data); self.block_map.insert(var, block); @@ -308,8 +310,7 @@ impl<'a, 'tcx> ParseCtxt<'a, 'tcx> { ExprKind::Block { block } => &self.thir[*block], ); - let mut data = BasicBlockData::new(None); - data.is_cleanup = is_cleanup; + let mut data = BasicBlockData::new(None, is_cleanup); for stmt_id in &*block.stmts { let stmt = self.statement_as_expr(*stmt_id)?; let span = self.thir[stmt].span; diff --git a/compiler/rustc_mir_transform/src/early_otherwise_branch.rs b/compiler/rustc_mir_transform/src/early_otherwise_branch.rs index be6056250fde..6dae6ec09abb 100644 --- a/compiler/rustc_mir_transform/src/early_otherwise_branch.rs +++ b/compiler/rustc_mir_transform/src/early_otherwise_branch.rs @@ -179,15 +179,17 @@ impl<'tcx> crate::MirPass<'tcx> for EarlyOtherwiseBranch { let eq_targets = SwitchTargets::new(eq_new_targets, parent_targets.otherwise()); // Create `bbEq` in example above - let mut eq_switch = BasicBlockData::new(Some(Terminator { - source_info: bbs[parent].terminator().source_info, - kind: TerminatorKind::SwitchInt { - // switch on the first discriminant, so we can mark the second one as dead - discr: parent_op, - targets: eq_targets, - }, - })); - eq_switch.is_cleanup = bbs[parent].is_cleanup; + let eq_switch = BasicBlockData::new( + Some(Terminator { + source_info: bbs[parent].terminator().source_info, + kind: TerminatorKind::SwitchInt { + // switch on the first discriminant, so we can mark the second one as dead + discr: parent_op, + targets: eq_targets, + }, + }), + bbs[parent].is_cleanup, + ); let eq_bb = patch.new_block(eq_switch); diff --git a/compiler/rustc_mir_transform/src/inline.rs b/compiler/rustc_mir_transform/src/inline.rs index f0acbaf56b63..35699acb318d 100644 --- a/compiler/rustc_mir_transform/src/inline.rs +++ b/compiler/rustc_mir_transform/src/inline.rs @@ -572,11 +572,13 @@ impl<'tcx> Inliner<'tcx> { let return_block = if let Some(block) = target { // Prepare a new block for code that should execute when call returns. We don't use // target block directly since it might have other predecessors. - let mut data = BasicBlockData::new(Some(Terminator { - source_info: terminator.source_info, - kind: TerminatorKind::Goto { target: block }, - })); - data.is_cleanup = caller_body[block].is_cleanup; + let data = BasicBlockData::new( + Some(Terminator { + source_info: terminator.source_info, + kind: TerminatorKind::Goto { target: block }, + }), + caller_body[block].is_cleanup, + ); Some(caller_body.basic_blocks_mut().push(data)) } else { None diff --git a/compiler/rustc_mir_transform/src/shim/async_destructor_ctor.rs b/compiler/rustc_mir_transform/src/shim/async_destructor_ctor.rs index 139b25be0ab2..f01bab75c4a1 100644 --- a/compiler/rustc_mir_transform/src/shim/async_destructor_ctor.rs +++ b/compiler/rustc_mir_transform/src/shim/async_destructor_ctor.rs @@ -96,7 +96,7 @@ impl<'tcx> AsyncDestructorCtorShimBuilder<'tcx> { typing_env, stack: Vec::with_capacity(Self::MAX_STACK_LEN), - last_bb: bbs.push(BasicBlockData::new(None)), + last_bb: bbs.push(BasicBlockData::new(None, false)), top_cleanup_bb: match tcx.sess.panic_strategy() { PanicStrategy::Unwind => { // Don't drop input arg because it's just a pointer From d08738c39785970f897621845e5aa2802d53fdd4 Mon Sep 17 00:00:00 2001 From: DianQK Date: Wed, 27 Nov 2024 06:40:02 +0800 Subject: [PATCH 57/92] mir-opt: Do not handle the cleanup BB in the EarlyOtherwiseBranch --- .../src/early_otherwise_branch.rs | 4 ++ ...anch_unwind.poll.EarlyOtherwiseBranch.diff | 62 +++++++------------ .../mir-opt/early_otherwise_branch_unwind.rs | 11 +--- ...ch_unwind.unwind.EarlyOtherwiseBranch.diff | 62 +++++++------------ 4 files changed, 53 insertions(+), 86 deletions(-) diff --git a/compiler/rustc_mir_transform/src/early_otherwise_branch.rs b/compiler/rustc_mir_transform/src/early_otherwise_branch.rs index 6dae6ec09abb..91e1395e7641 100644 --- a/compiler/rustc_mir_transform/src/early_otherwise_branch.rs +++ b/compiler/rustc_mir_transform/src/early_otherwise_branch.rs @@ -244,6 +244,10 @@ fn evaluate_candidate<'tcx>( parent: BasicBlock, ) -> Option> { let bbs = &body.basic_blocks; + // NB: If this BB is a cleanup, we may need to figure out what else needs to be handled. + if bbs[parent].is_cleanup { + return None; + } let TerminatorKind::SwitchInt { targets, discr: parent_discr } = &bbs[parent].terminator().kind else { return None; diff --git a/tests/mir-opt/early_otherwise_branch_unwind.poll.EarlyOtherwiseBranch.diff b/tests/mir-opt/early_otherwise_branch_unwind.poll.EarlyOtherwiseBranch.diff index 5f03b94ccb8d..b6450e43b09e 100644 --- a/tests/mir-opt/early_otherwise_branch_unwind.poll.EarlyOtherwiseBranch.diff +++ b/tests/mir-opt/early_otherwise_branch_unwind.poll.EarlyOtherwiseBranch.diff @@ -12,7 +12,6 @@ let mut _7: bool; let mut _8: bool; let mut _9: isize; -+ let mut _10: bool; scope 1 { debug _trailers => _5; } @@ -45,14 +44,12 @@ bb4: { _0 = const (); -- goto -> bb17; -+ goto -> bb15; + goto -> bb17; } bb5: { _0 = const (); -- goto -> bb17; -+ goto -> bb15; + goto -> bb17; } bb6: { @@ -60,26 +57,22 @@ _6 = copy ((((_1 as Ready).0: std::result::Result>, u8>) as Err).0: u8); _0 = const (); StorageDead(_6); -- goto -> bb17; -+ goto -> bb15; + goto -> bb17; } bb7: { StorageLive(_5); _5 = move ((((((_1 as Ready).0: std::result::Result>, u8>) as Ok).0: std::option::Option>) as Some).0: std::vec::Vec); _0 = const (); -- drop(_5) -> [return: bb8, unwind: bb20]; -+ drop(_5) -> [return: bb8, unwind: bb16]; + drop(_5) -> [return: bb8, unwind: bb20]; } bb8: { StorageDead(_5); -- goto -> bb17; -+ goto -> bb15; + goto -> bb17; } bb9 (cleanup): { -+ StorageDead(_10); resume; } @@ -88,8 +81,7 @@ } bb11: { -- switchInt(copy _7) -> [0: bb12, otherwise: bb16]; -+ switchInt(copy _7) -> [0: bb12, otherwise: bb14]; + switchInt(copy _7) -> [0: bb12, otherwise: bb16]; } bb12: { @@ -98,45 +90,37 @@ } bb13: { -- switchInt(copy _8) -> [0: bb14, otherwise: bb15]; -- } -- -- bb14: { + switchInt(copy _8) -> [0: bb14, otherwise: bb15]; + } + + bb14: { _8 = const false; goto -> bb12; } -- bb15: { -- goto -> bb14; -- } -- -- bb16: { -+ bb14: { + bb15: { + goto -> bb14; + } + + bb16: { _9 = discriminant(((_1 as Ready).0: std::result::Result>, u8>)); switchInt(move _9) -> [0: bb13, otherwise: bb12]; } -- bb17: { -+ bb15: { + bb17: { switchInt(copy _4) -> [0: bb11, otherwise: bb10]; } -- bb18 (cleanup): { -- switchInt(copy _3) -> [0: bb19, otherwise: bb9]; -+ bb16 (cleanup): { -+ StorageLive(_10); -+ _10 = Ne(copy _4, copy _3); -+ switchInt(move _10) -> [0: bb17, otherwise: bb9]; + bb18 (cleanup): { + switchInt(copy _3) -> [0: bb19, otherwise: bb9]; } -- bb19 (cleanup): { -+ bb17 (cleanup): { -+ StorageDead(_10); + bb19 (cleanup): { goto -> bb9; -- } -- -- bb20 (cleanup): { -- switchInt(copy _4) -> [0: bb18, otherwise: bb9]; + } + + bb20 (cleanup): { + switchInt(copy _4) -> [0: bb18, otherwise: bb9]; } } diff --git a/tests/mir-opt/early_otherwise_branch_unwind.rs b/tests/mir-opt/early_otherwise_branch_unwind.rs index 7df58c7a64fb..cbccf11729ab 100644 --- a/tests/mir-opt/early_otherwise_branch_unwind.rs +++ b/tests/mir-opt/early_otherwise_branch_unwind.rs @@ -6,16 +6,14 @@ use std::task::Poll; // We find a matching pattern in the unwind path, // and we need to create a cleanup BB for this case to meet the unwind invariants rule. +// NB: This transform is not happening currently. // EMIT_MIR early_otherwise_branch_unwind.unwind.EarlyOtherwiseBranch.diff fn unwind(val: Option>>) { // CHECK-LABEL: fn unwind( // CHECK: drop({{.*}}) -> [return: bb{{.*}}, unwind: [[PARENT_UNWIND_BB:bb.*]]]; // CHECK: [[PARENT_UNWIND_BB]] (cleanup): { - // CHECK-NEXT: StorageLive - // CHECK-NEXT: [[CMP_LOCAL:_.*]] = Ne - // CHECK-NEXT: switchInt(move [[CMP_LOCAL]]) -> [0: [[NEW_UNWIND_BB:bb.*]], otherwise - // CHECK: [[NEW_UNWIND_BB]] (cleanup): { + // CHECK-NEXT: switchInt match val { Some(Some(Some(_v))) => {} Some(Some(None)) => {} @@ -30,10 +28,7 @@ pub fn poll(val: Poll>, u8>>) { // CHECK-LABEL: fn poll( // CHECK: drop({{.*}}) -> [return: bb{{.*}}, unwind: [[PARENT_UNWIND_BB:bb.*]]]; // CHECK: [[PARENT_UNWIND_BB]] (cleanup): { - // CHECK-NEXT: StorageLive - // CHECK-NEXT: [[CMP_LOCAL:_.*]] = Ne - // CHECK-NEXT: switchInt(move [[CMP_LOCAL]]) -> [0: [[NEW_UNWIND_BB:bb.*]], otherwise - // CHECK: [[NEW_UNWIND_BB]] (cleanup): { + // CHECK-NEXT: switchInt match val { Poll::Ready(Ok(Some(_trailers))) => {} Poll::Ready(Err(_err)) => {} diff --git a/tests/mir-opt/early_otherwise_branch_unwind.unwind.EarlyOtherwiseBranch.diff b/tests/mir-opt/early_otherwise_branch_unwind.unwind.EarlyOtherwiseBranch.diff index 1405b9d314a3..2b2c007e082a 100644 --- a/tests/mir-opt/early_otherwise_branch_unwind.unwind.EarlyOtherwiseBranch.diff +++ b/tests/mir-opt/early_otherwise_branch_unwind.unwind.EarlyOtherwiseBranch.diff @@ -11,7 +11,6 @@ let mut _6: bool; let mut _7: bool; let mut _8: isize; -+ let mut _9: bool; scope 1 { debug _v => _5; } @@ -41,38 +40,32 @@ bb4: { _0 = const (); -- goto -> bb17; -+ goto -> bb15; + goto -> bb17; } bb5: { _0 = const (); -- goto -> bb17; -+ goto -> bb15; + goto -> bb17; } bb6: { _0 = const (); -- goto -> bb17; -+ goto -> bb15; + goto -> bb17; } bb7: { StorageLive(_5); _5 = move ((((((_1 as Some).0: std::option::Option>) as Some).0: std::option::Option) as Some).0: T); _0 = const (); -- drop(_5) -> [return: bb8, unwind: bb20]; -+ drop(_5) -> [return: bb8, unwind: bb16]; + drop(_5) -> [return: bb8, unwind: bb20]; } bb8: { StorageDead(_5); -- goto -> bb17; -+ goto -> bb15; + goto -> bb17; } bb9 (cleanup): { -+ StorageDead(_9); resume; } @@ -81,8 +74,7 @@ } bb11: { -- switchInt(copy _6) -> [0: bb12, otherwise: bb16]; -+ switchInt(copy _6) -> [0: bb12, otherwise: bb14]; + switchInt(copy _6) -> [0: bb12, otherwise: bb16]; } bb12: { @@ -91,45 +83,37 @@ } bb13: { -- switchInt(copy _7) -> [0: bb14, otherwise: bb15]; -- } -- -- bb14: { + switchInt(copy _7) -> [0: bb14, otherwise: bb15]; + } + + bb14: { _7 = const false; goto -> bb12; } -- bb15: { -- goto -> bb14; -- } -- -- bb16: { -+ bb14: { + bb15: { + goto -> bb14; + } + + bb16: { _8 = discriminant(((_1 as Some).0: std::option::Option>)); switchInt(move _8) -> [1: bb13, otherwise: bb12]; } -- bb17: { -+ bb15: { + bb17: { switchInt(copy _4) -> [1: bb11, otherwise: bb10]; } -- bb18 (cleanup): { -- switchInt(copy _3) -> [1: bb19, otherwise: bb9]; -+ bb16 (cleanup): { -+ StorageLive(_9); -+ _9 = Ne(copy _4, copy _3); -+ switchInt(move _9) -> [0: bb17, otherwise: bb9]; + bb18 (cleanup): { + switchInt(copy _3) -> [1: bb19, otherwise: bb9]; } -- bb19 (cleanup): { -+ bb17 (cleanup): { -+ StorageDead(_9); + bb19 (cleanup): { goto -> bb9; -- } -- -- bb20 (cleanup): { -- switchInt(copy _4) -> [1: bb18, otherwise: bb9]; + } + + bb20 (cleanup): { + switchInt(copy _4) -> [1: bb18, otherwise: bb9]; } } From 085d93181093c1daf9ef595cd08d73633062e635 Mon Sep 17 00:00:00 2001 From: lcnr Date: Fri, 6 Dec 2024 14:46:28 +0100 Subject: [PATCH 58/92] introduce `LateParamRegionKind` --- .../src/diagnostics/region_errors.rs | 2 +- .../src/diagnostics/region_name.rs | 12 +-- .../rustc_borrowck/src/universal_regions.rs | 18 +++-- .../src/check/compare_impl_item.rs | 8 +- .../src/check/compare_impl_item/refine.rs | 11 ++- .../rustc_hir_analysis/src/check/wfcheck.rs | 5 +- .../src/hir_ty_lowering/mod.rs | 2 +- .../rustc_lint/src/impl_trait_overcaptures.rs | 6 +- compiler/rustc_middle/src/ty/context.rs | 2 +- compiler/rustc_middle/src/ty/fold.rs | 3 +- compiler/rustc_middle/src/ty/mod.rs | 3 +- compiler/rustc_middle/src/ty/print/pretty.rs | 9 ++- compiler/rustc_middle/src/ty/region.rs | 81 +++++++++++++++++-- .../rustc_middle/src/ty/structural_impls.rs | 18 ++++- .../nice_region_error/named_anon_conflict.rs | 6 +- .../infer/nice_region_error/util.rs | 12 +-- .../src/error_reporting/infer/region.rs | 8 +- .../src/errors/note_and_explain.rs | 8 +- src/tools/clippy/clippy_lints/src/ptr.rs | 2 +- 19 files changed, 157 insertions(+), 59 deletions(-) diff --git a/compiler/rustc_borrowck/src/diagnostics/region_errors.rs b/compiler/rustc_borrowck/src/diagnostics/region_errors.rs index 4e6d349d761b..3555009c63f4 100644 --- a/compiler/rustc_borrowck/src/diagnostics/region_errors.rs +++ b/compiler/rustc_borrowck/src/diagnostics/region_errors.rs @@ -188,7 +188,7 @@ impl<'infcx, 'tcx> MirBorrowckCtxt<'_, 'infcx, 'tcx> { /// Returns `true` if a closure is inferred to be an `FnMut` closure. fn is_closure_fn_mut(&self, fr: RegionVid) -> bool { if let Some(ty::ReLateParam(late_param)) = self.to_error_region(fr).as_deref() - && let ty::BoundRegionKind::ClosureEnv = late_param.bound_region + && let ty::LateParamRegionKind::ClosureEnv = late_param.kind && let DefiningTy::Closure(_, args) = self.regioncx.universal_regions().defining_ty { return args.as_closure().kind() == ty::ClosureKind::FnMut; diff --git a/compiler/rustc_borrowck/src/diagnostics/region_name.rs b/compiler/rustc_borrowck/src/diagnostics/region_name.rs index 34680c2d0afa..bdb880b2bced 100644 --- a/compiler/rustc_borrowck/src/diagnostics/region_name.rs +++ b/compiler/rustc_borrowck/src/diagnostics/region_name.rs @@ -299,17 +299,17 @@ impl<'tcx> MirBorrowckCtxt<'_, '_, 'tcx> { Some(RegionName { name: kw::StaticLifetime, source: RegionNameSource::Static }) } - ty::ReLateParam(late_param) => match late_param.bound_region { - ty::BoundRegionKind::Named(region_def_id, name) => { + ty::ReLateParam(late_param) => match late_param.kind { + ty::LateParamRegionKind::Named(region_def_id, name) => { // Get the span to point to, even if we don't use the name. let span = tcx.hir().span_if_local(region_def_id).unwrap_or(DUMMY_SP); debug!( "bound region named: {:?}, is_named: {:?}", name, - late_param.bound_region.is_named() + late_param.kind.is_named() ); - if late_param.bound_region.is_named() { + if late_param.kind.is_named() { // A named region that is actually named. Some(RegionName { name, @@ -331,7 +331,7 @@ impl<'tcx> MirBorrowckCtxt<'_, '_, 'tcx> { } } - ty::BoundRegionKind::ClosureEnv => { + ty::LateParamRegionKind::ClosureEnv => { let def_ty = self.regioncx.universal_regions().defining_ty; let closure_kind = match def_ty { @@ -368,7 +368,7 @@ impl<'tcx> MirBorrowckCtxt<'_, '_, 'tcx> { }) } - ty::BoundRegionKind::Anon => None, + ty::LateParamRegionKind::Anon(_) => None, }, ty::ReBound(..) diff --git a/compiler/rustc_borrowck/src/universal_regions.rs b/compiler/rustc_borrowck/src/universal_regions.rs index 6b7bf7187664..fb2bd5521573 100644 --- a/compiler/rustc_borrowck/src/universal_regions.rs +++ b/compiler/rustc_borrowck/src/universal_regions.rs @@ -842,8 +842,9 @@ impl<'tcx> BorrowckInferCtxt<'tcx> { { let (value, _map) = self.tcx.instantiate_bound_regions(value, |br| { debug!(?br); + let kind = ty::LateParamRegionKind::from_bound(br.var, br.kind); let liberated_region = - ty::Region::new_late_param(self.tcx, all_outlive_scope.to_def_id(), br.kind); + ty::Region::new_late_param(self.tcx, all_outlive_scope.to_def_id(), kind); let region_vid = { let name = match br.kind.get_name() { Some(name) => name, @@ -941,12 +942,13 @@ fn for_each_late_bound_region_in_item<'tcx>( return; } - for bound_var in tcx.late_bound_vars(tcx.local_def_id_to_hir_id(mir_def_id)) { - let ty::BoundVariableKind::Region(bound_region) = bound_var else { - continue; - }; - let liberated_region = - ty::Region::new_late_param(tcx, mir_def_id.to_def_id(), bound_region); - f(liberated_region); + for (idx, bound_var) in + tcx.late_bound_vars(tcx.local_def_id_to_hir_id(mir_def_id)).iter().enumerate() + { + if let ty::BoundVariableKind::Region(kind) = bound_var { + let kind = ty::LateParamRegionKind::from_bound(ty::BoundVar::from_usize(idx), kind); + let liberated_region = ty::Region::new_late_param(tcx, mir_def_id.to_def_id(), kind); + f(liberated_region); + } } } diff --git a/compiler/rustc_hir_analysis/src/check/compare_impl_item.rs b/compiler/rustc_hir_analysis/src/check/compare_impl_item.rs index e176fc589995..a6b504de3dac 100644 --- a/compiler/rustc_hir_analysis/src/check/compare_impl_item.rs +++ b/compiler/rustc_hir_analysis/src/check/compare_impl_item.rs @@ -430,12 +430,12 @@ fn compare_method_predicate_entailment<'tcx>( Ok(()) } -struct RemapLateBound<'a, 'tcx> { +struct RemapLateParam<'a, 'tcx> { tcx: TyCtxt<'tcx>, - mapping: &'a FxIndexMap, + mapping: &'a FxIndexMap, } -impl<'tcx> TypeFolder> for RemapLateBound<'_, 'tcx> { +impl<'tcx> TypeFolder> for RemapLateParam<'_, 'tcx> { fn cx(&self) -> TyCtxt<'tcx> { self.tcx } @@ -445,7 +445,7 @@ impl<'tcx> TypeFolder> for RemapLateBound<'_, 'tcx> { ty::Region::new_late_param( self.tcx, fr.scope, - self.mapping.get(&fr.bound_region).copied().unwrap_or(fr.bound_region), + self.mapping.get(&fr.kind).copied().unwrap_or(fr.kind), ) } else { r diff --git a/compiler/rustc_hir_analysis/src/check/compare_impl_item/refine.rs b/compiler/rustc_hir_analysis/src/check/compare_impl_item/refine.rs index 6eac4ac3baf8..2b14594ea1bf 100644 --- a/compiler/rustc_hir_analysis/src/check/compare_impl_item/refine.rs +++ b/compiler/rustc_hir_analysis/src/check/compare_impl_item/refine.rs @@ -289,11 +289,16 @@ fn report_mismatched_rpitit_signature<'tcx>( tcx.fn_sig(trait_m_def_id).skip_binder().bound_vars(), tcx.fn_sig(impl_m_def_id).skip_binder().bound_vars(), ) - .filter_map(|(impl_bv, trait_bv)| { + .enumerate() + .filter_map(|(idx, (impl_bv, trait_bv))| { if let ty::BoundVariableKind::Region(impl_bv) = impl_bv && let ty::BoundVariableKind::Region(trait_bv) = trait_bv { - Some((impl_bv, trait_bv)) + let var = ty::BoundVar::from_usize(idx); + Some(( + ty::LateParamRegionKind::from_bound(var, impl_bv), + ty::LateParamRegionKind::from_bound(var, trait_bv), + )) } else { None } @@ -301,7 +306,7 @@ fn report_mismatched_rpitit_signature<'tcx>( .collect(); let mut return_ty = - trait_m_sig.output().fold_with(&mut super::RemapLateBound { tcx, mapping: &mapping }); + trait_m_sig.output().fold_with(&mut super::RemapLateParam { tcx, mapping: &mapping }); if tcx.asyncness(impl_m_def_id).is_async() && tcx.asyncness(trait_m_def_id).is_async() { let ty::Alias(ty::Projection, future_ty) = return_ty.kind() else { diff --git a/compiler/rustc_hir_analysis/src/check/wfcheck.rs b/compiler/rustc_hir_analysis/src/check/wfcheck.rs index 059b8dcd9754..3cddc9642bae 100644 --- a/compiler/rustc_hir_analysis/src/check/wfcheck.rs +++ b/compiler/rustc_hir_analysis/src/check/wfcheck.rs @@ -2339,8 +2339,11 @@ fn lint_redundant_lifetimes<'tcx>( ); // If we are in a function, add its late-bound lifetimes too. if matches!(def_kind, DefKind::Fn | DefKind::AssocFn) { - for var in tcx.fn_sig(owner_id).instantiate_identity().bound_vars() { + for (idx, var) in + tcx.fn_sig(owner_id).instantiate_identity().bound_vars().iter().enumerate() + { let ty::BoundVariableKind::Region(kind) = var else { continue }; + let kind = ty::LateParamRegionKind::from_bound(ty::BoundVar::from_usize(idx), kind); lifetimes.push(ty::Region::new_late_param(tcx, owner_id.to_def_id(), kind)); } } diff --git a/compiler/rustc_hir_analysis/src/hir_ty_lowering/mod.rs b/compiler/rustc_hir_analysis/src/hir_ty_lowering/mod.rs index 78057d5a9970..b56222763d03 100644 --- a/compiler/rustc_hir_analysis/src/hir_ty_lowering/mod.rs +++ b/compiler/rustc_hir_analysis/src/hir_ty_lowering/mod.rs @@ -355,7 +355,7 @@ impl<'tcx> dyn HirTyLowerer<'tcx> + '_ { ty::Region::new_late_param( tcx, scope.to_def_id(), - ty::BoundRegionKind::Named(id.to_def_id(), name), + ty::LateParamRegionKind::Named(id.to_def_id(), name), ) // (*) -- not late-bound, won't change diff --git a/compiler/rustc_lint/src/impl_trait_overcaptures.rs b/compiler/rustc_lint/src/impl_trait_overcaptures.rs index 1aacdbd448cc..c2c247279f15 100644 --- a/compiler/rustc_lint/src/impl_trait_overcaptures.rs +++ b/compiler/rustc_lint/src/impl_trait_overcaptures.rs @@ -325,7 +325,7 @@ where ParamKind::Free(def_id, name) => ty::Region::new_late_param( self.tcx, self.parent_def_id.to_def_id(), - ty::BoundRegionKind::Named(def_id, name), + ty::LateParamRegionKind::Named(def_id, name), ), // Totally ignore late bound args from binders. ParamKind::Late => return true, @@ -475,7 +475,7 @@ fn extract_def_id_from_arg<'tcx>( ) | ty::ReLateParam(ty::LateParamRegion { scope: _, - bound_region: ty::BoundRegionKind::Named(def_id, ..), + kind: ty::LateParamRegionKind::Named(def_id, ..), }) => def_id, _ => unreachable!(), }, @@ -544,7 +544,7 @@ impl<'tcx> TypeRelation> for FunctionalVariances<'tcx> { ) | ty::ReLateParam(ty::LateParamRegion { scope: _, - bound_region: ty::BoundRegionKind::Named(def_id, ..), + kind: ty::LateParamRegionKind::Named(def_id, ..), }) => def_id, _ => { return Ok(a); diff --git a/compiler/rustc_middle/src/ty/context.rs b/compiler/rustc_middle/src/ty/context.rs index 54ee582f4de2..977e62becf16 100644 --- a/compiler/rustc_middle/src/ty/context.rs +++ b/compiler/rustc_middle/src/ty/context.rs @@ -3091,7 +3091,7 @@ impl<'tcx> TyCtxt<'tcx> { return ty::Region::new_late_param( self, new_parent.to_def_id(), - ty::BoundRegionKind::Named( + ty::LateParamRegionKind::Named( lbv.to_def_id(), self.item_name(lbv.to_def_id()), ), diff --git a/compiler/rustc_middle/src/ty/fold.rs b/compiler/rustc_middle/src/ty/fold.rs index 1b073d3c466d..067516917ef7 100644 --- a/compiler/rustc_middle/src/ty/fold.rs +++ b/compiler/rustc_middle/src/ty/fold.rs @@ -270,7 +270,8 @@ impl<'tcx> TyCtxt<'tcx> { T: TypeFoldable>, { self.instantiate_bound_regions_uncached(value, |br| { - ty::Region::new_late_param(self, all_outlive_scope, br.kind) + let kind = ty::LateParamRegionKind::from_bound(br.var, br.kind); + ty::Region::new_late_param(self, all_outlive_scope, kind) }) } diff --git a/compiler/rustc_middle/src/ty/mod.rs b/compiler/rustc_middle/src/ty/mod.rs index 25d0d7b71da6..9845598a64b2 100644 --- a/compiler/rustc_middle/src/ty/mod.rs +++ b/compiler/rustc_middle/src/ty/mod.rs @@ -83,7 +83,8 @@ pub use self::predicate::{ TypeOutlivesPredicate, }; pub use self::region::{ - BoundRegion, BoundRegionKind, EarlyParamRegion, LateParamRegion, Region, RegionKind, RegionVid, + BoundRegion, BoundRegionKind, EarlyParamRegion, LateParamRegion, LateParamRegionKind, Region, + RegionKind, RegionVid, }; pub use self::rvalue_scopes::RvalueScopes; pub use self::sty::{ diff --git a/compiler/rustc_middle/src/ty/print/pretty.rs b/compiler/rustc_middle/src/ty/print/pretty.rs index 83508d97cf8d..a089eac5d7e1 100644 --- a/compiler/rustc_middle/src/ty/print/pretty.rs +++ b/compiler/rustc_middle/src/ty/print/pretty.rs @@ -2374,8 +2374,8 @@ impl<'tcx> PrettyPrinter<'tcx> for FmtPrinter<'_, 'tcx> { match *region { ty::ReEarlyParam(ref data) => data.has_name(), + ty::ReLateParam(ty::LateParamRegion { kind, .. }) => kind.is_named(), ty::ReBound(_, ty::BoundRegion { kind: br, .. }) - | ty::ReLateParam(ty::LateParamRegion { bound_region: br, .. }) | ty::RePlaceholder(ty::Placeholder { bound: ty::BoundRegion { kind: br, .. }, .. }) => { @@ -2448,8 +2448,13 @@ impl<'tcx> FmtPrinter<'_, 'tcx> { return Ok(()); } } + ty::ReLateParam(ty::LateParamRegion { kind, .. }) => { + if let Some(name) = kind.get_name() { + p!(write("{}", name)); + return Ok(()); + } + } ty::ReBound(_, ty::BoundRegion { kind: br, .. }) - | ty::ReLateParam(ty::LateParamRegion { bound_region: br, .. }) | ty::RePlaceholder(ty::Placeholder { bound: ty::BoundRegion { kind: br, .. }, .. }) => { diff --git a/compiler/rustc_middle/src/ty/region.rs b/compiler/rustc_middle/src/ty/region.rs index 0eb2aafdf2ed..14a2e5befe69 100644 --- a/compiler/rustc_middle/src/ty/region.rs +++ b/compiler/rustc_middle/src/ty/region.rs @@ -69,9 +69,10 @@ impl<'tcx> Region<'tcx> { pub fn new_late_param( tcx: TyCtxt<'tcx>, scope: DefId, - bound_region: ty::BoundRegionKind, + kind: LateParamRegionKind, ) -> Region<'tcx> { - tcx.intern_region(ty::ReLateParam(ty::LateParamRegion { scope, bound_region })) + let data = LateParamRegion { scope, kind }; + tcx.intern_region(ty::ReLateParam(data)) } #[inline] @@ -124,8 +125,8 @@ impl<'tcx> Region<'tcx> { match kind { ty::ReEarlyParam(region) => Region::new_early_param(tcx, region), ty::ReBound(debruijn, region) => Region::new_bound(tcx, debruijn, region), - ty::ReLateParam(ty::LateParamRegion { scope, bound_region }) => { - Region::new_late_param(tcx, scope, bound_region) + ty::ReLateParam(ty::LateParamRegion { scope, kind }) => { + Region::new_late_param(tcx, scope, kind) } ty::ReStatic => tcx.lifetimes.re_static, ty::ReVar(vid) => Region::new_var(tcx, vid), @@ -165,7 +166,7 @@ impl<'tcx> Region<'tcx> { match *self { ty::ReEarlyParam(ebr) => Some(ebr.name), ty::ReBound(_, br) => br.kind.get_name(), - ty::ReLateParam(fr) => fr.bound_region.get_name(), + ty::ReLateParam(fr) => fr.kind.get_name(), ty::ReStatic => Some(kw::StaticLifetime), ty::RePlaceholder(placeholder) => placeholder.bound.kind.get_name(), _ => None, @@ -187,7 +188,7 @@ impl<'tcx> Region<'tcx> { match *self { ty::ReEarlyParam(ebr) => ebr.has_name(), ty::ReBound(_, br) => br.kind.is_named(), - ty::ReLateParam(fr) => fr.bound_region.is_named(), + ty::ReLateParam(fr) => fr.kind.is_named(), ty::ReStatic => true, ty::ReVar(..) => false, ty::RePlaceholder(placeholder) => placeholder.bound.kind.is_named(), @@ -310,7 +311,7 @@ impl<'tcx> Region<'tcx> { Some(tcx.generics_of(binding_item).region_param(ebr, tcx).def_id) } ty::ReLateParam(ty::LateParamRegion { - bound_region: ty::BoundRegionKind::Named(def_id, _), + kind: ty::LateParamRegionKind::Named(def_id, _), .. }) => Some(def_id), _ => None, @@ -358,7 +359,71 @@ impl std::fmt::Debug for EarlyParamRegion { /// different parameters apart. pub struct LateParamRegion { pub scope: DefId, - pub bound_region: BoundRegionKind, + pub kind: LateParamRegionKind, +} + +/// When liberating bound regions, we map their [`BoundRegionKind`] +/// to this as we need to track the index of anonymous regions. We +/// otherwise end up liberating multiple bound regions to the same +/// late-bound region. +#[derive(Clone, PartialEq, Eq, Hash, TyEncodable, TyDecodable, Copy)] +#[derive(HashStable)] +pub enum LateParamRegionKind { + /// An anonymous region parameter for a given fn (&T) + /// + /// Unlike [`BoundRegionKind::Anon`], this tracks the index of the + /// liberated bound region. + /// + /// We should ideally never liberate anonymous regions, but do so for the + /// sake of diagnostics in `FnCtxt::sig_of_closure_with_expectation`. + Anon(u32), + + /// Named region parameters for functions (a in &'a T) + /// + /// The `DefId` is needed to distinguish free regions in + /// the event of shadowing. + Named(DefId, Symbol), + + /// Anonymous region for the implicit env pointer parameter + /// to a closure + ClosureEnv, +} + +impl LateParamRegionKind { + pub fn from_bound(var: BoundVar, br: BoundRegionKind) -> LateParamRegionKind { + match br { + BoundRegionKind::Anon => LateParamRegionKind::Anon(var.as_u32()), + BoundRegionKind::Named(def_id, name) => LateParamRegionKind::Named(def_id, name), + BoundRegionKind::ClosureEnv => LateParamRegionKind::ClosureEnv, + } + } + + pub fn is_named(&self) -> bool { + match *self { + LateParamRegionKind::Named(_, name) => { + name != kw::UnderscoreLifetime && name != kw::Empty + } + _ => false, + } + } + + pub fn get_name(&self) -> Option { + if self.is_named() { + match *self { + LateParamRegionKind::Named(_, name) => return Some(name), + _ => unreachable!(), + } + } + + None + } + + pub fn get_id(&self) -> Option { + match *self { + LateParamRegionKind::Named(id, _) => Some(id), + _ => None, + } + } } #[derive(Clone, PartialEq, Eq, Hash, TyEncodable, TyDecodable, Copy)] diff --git a/compiler/rustc_middle/src/ty/structural_impls.rs b/compiler/rustc_middle/src/ty/structural_impls.rs index ec4fb93bdb37..f38454ceac01 100644 --- a/compiler/rustc_middle/src/ty/structural_impls.rs +++ b/compiler/rustc_middle/src/ty/structural_impls.rs @@ -77,7 +77,23 @@ impl fmt::Debug for ty::BoundRegionKind { impl fmt::Debug for ty::LateParamRegion { fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { - write!(f, "ReLateParam({:?}, {:?})", self.scope, self.bound_region) + write!(f, "ReLateParam({:?}, {:?})", self.scope, self.kind) + } +} + +impl fmt::Debug for ty::LateParamRegionKind { + fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { + match *self { + ty::LateParamRegionKind::Anon(idx) => write!(f, "BrAnon({idx})"), + ty::LateParamRegionKind::Named(did, name) => { + if did.is_crate_root() { + write!(f, "BrNamed({name})") + } else { + write!(f, "BrNamed({did:?}, {name})") + } + } + ty::LateParamRegionKind::ClosureEnv => write!(f, "BrEnv"), + } } } diff --git a/compiler/rustc_trait_selection/src/error_reporting/infer/nice_region_error/named_anon_conflict.rs b/compiler/rustc_trait_selection/src/error_reporting/infer/nice_region_error/named_anon_conflict.rs index 5befd81467b0..aa7935a29f0b 100644 --- a/compiler/rustc_trait_selection/src/error_reporting/infer/nice_region_error/named_anon_conflict.rs +++ b/compiler/rustc_trait_selection/src/error_reporting/infer/nice_region_error/named_anon_conflict.rs @@ -54,13 +54,13 @@ impl<'a, 'tcx> NiceRegionError<'a, 'tcx> { let param = anon_param_info.param; let new_ty = anon_param_info.param_ty; let new_ty_span = anon_param_info.param_ty_span; - let br = anon_param_info.br; let is_first = anon_param_info.is_first; let scope_def_id = region_info.scope; let is_impl_item = region_info.is_impl_item; - match br { - ty::BoundRegionKind::Named(_, kw::UnderscoreLifetime) | ty::BoundRegionKind::Anon => {} + match anon_param_info.kind { + ty::LateParamRegionKind::Named(_, kw::UnderscoreLifetime) + | ty::LateParamRegionKind::Anon(_) => {} _ => { /* not an anonymous region */ debug!("try_report_named_anon_conflict: not an anonymous region"); diff --git a/compiler/rustc_trait_selection/src/error_reporting/infer/nice_region_error/util.rs b/compiler/rustc_trait_selection/src/error_reporting/infer/nice_region_error/util.rs index a2150dc7c8cd..445937ad1692 100644 --- a/compiler/rustc_trait_selection/src/error_reporting/infer/nice_region_error/util.rs +++ b/compiler/rustc_trait_selection/src/error_reporting/infer/nice_region_error/util.rs @@ -17,8 +17,8 @@ pub struct AnonymousParamInfo<'tcx> { pub param: &'tcx hir::Param<'tcx>, /// The type corresponding to the anonymous region parameter. pub param_ty: Ty<'tcx>, - /// The `ty::BoundRegionKind` corresponding to the anonymous region. - pub br: ty::BoundRegionKind, + /// The `ty::LateParamRegionKind` corresponding to the anonymous region. + pub kind: ty::LateParamRegionKind, /// The `Span` of the parameter type. pub param_ty_span: Span, /// Signals that the argument is the first parameter in the declaration. @@ -43,11 +43,11 @@ pub fn find_param_with_region<'tcx>( anon_region: Region<'tcx>, replace_region: Region<'tcx>, ) -> Option> { - let (id, br) = match *anon_region { - ty::ReLateParam(late_param) => (late_param.scope, late_param.bound_region), + let (id, kind) = match *anon_region { + ty::ReLateParam(late_param) => (late_param.scope, late_param.kind), ty::ReEarlyParam(ebr) => { let region_def = tcx.generics_of(generic_param_scope).region_param(ebr, tcx).def_id; - (tcx.parent(region_def), ty::BoundRegionKind::Named(region_def, ebr.name)) + (tcx.parent(region_def), ty::LateParamRegionKind::Named(region_def, ebr.name)) } _ => return None, // not a free region }; @@ -96,7 +96,7 @@ pub fn find_param_with_region<'tcx>( let ty_hir_id = fn_decl.inputs[index].hir_id; let param_ty_span = hir.span(ty_hir_id); let is_first = index == 0; - AnonymousParamInfo { param, param_ty: new_param_ty, param_ty_span, br, is_first } + AnonymousParamInfo { param, param_ty: new_param_ty, param_ty_span, kind, is_first } }) }) } diff --git a/compiler/rustc_trait_selection/src/error_reporting/infer/region.rs b/compiler/rustc_trait_selection/src/error_reporting/infer/region.rs index babf3ebc5a34..98b5fb2052f1 100644 --- a/compiler/rustc_trait_selection/src/error_reporting/infer/region.rs +++ b/compiler/rustc_trait_selection/src/error_reporting/infer/region.rs @@ -1095,13 +1095,13 @@ fn msg_span_from_named_region<'tcx>( (text, Some(span)) } ty::ReLateParam(ref fr) => { - if !fr.bound_region.is_named() + if !fr.kind.is_named() && let Some((ty, _)) = find_anon_type(tcx, generic_param_scope, region) { ("the anonymous lifetime defined here".to_string(), Some(ty.span)) } else { - match fr.bound_region { - ty::BoundRegionKind::Named(param_def_id, name) => { + match fr.kind { + ty::LateParamRegionKind::Named(param_def_id, name) => { let span = tcx.def_span(param_def_id); let text = if name == kw::UnderscoreLifetime { "the anonymous lifetime as defined here".to_string() @@ -1110,7 +1110,7 @@ fn msg_span_from_named_region<'tcx>( }; (text, Some(span)) } - ty::BoundRegionKind::Anon => ( + ty::LateParamRegionKind::Anon(_) => ( "the anonymous lifetime as defined here".to_string(), Some(tcx.def_span(generic_param_scope)), ), diff --git a/compiler/rustc_trait_selection/src/errors/note_and_explain.rs b/compiler/rustc_trait_selection/src/errors/note_and_explain.rs index 1ce5e6ba917f..b752dbf3093b 100644 --- a/compiler/rustc_trait_selection/src/errors/note_and_explain.rs +++ b/compiler/rustc_trait_selection/src/errors/note_and_explain.rs @@ -39,14 +39,14 @@ impl<'a> DescriptionCtx<'a> { } } ty::ReLateParam(ref fr) => { - if !fr.bound_region.is_named() + if !fr.kind.is_named() && let Some((ty, _)) = find_anon_type(tcx, generic_param_scope, region) { (Some(ty.span), "defined_here", String::new()) } else { let scope = fr.scope.expect_local(); - match fr.bound_region { - ty::BoundRegionKind::Named(_, name) => { + match fr.kind { + ty::LateParamRegionKind::Named(_, name) => { let span = if let Some(param) = tcx .hir() .get_generics(scope) @@ -62,7 +62,7 @@ impl<'a> DescriptionCtx<'a> { (Some(span), "as_defined", name.to_string()) } } - ty::BoundRegionKind::Anon => { + ty::LateParamRegionKind::Anon(_) => { let span = Some(tcx.def_span(scope)); (span, "defined_here", String::new()) } diff --git a/src/tools/clippy/clippy_lints/src/ptr.rs b/src/tools/clippy/clippy_lints/src/ptr.rs index 44a8789462b0..b674b01406d3 100644 --- a/src/tools/clippy/clippy_lints/src/ptr.rs +++ b/src/tools/clippy/clippy_lints/src/ptr.rs @@ -475,7 +475,7 @@ fn check_fn_args<'cx, 'tcx: 'cx>( .def_id, ), ty::ReBound(_, r) => r.kind.get_id(), - ty::ReLateParam(r) => r.bound_region.get_id(), + ty::ReLateParam(r) => r.kind.get_id(), ty::ReStatic | ty::ReVar(_) | ty::RePlaceholder(_) From 4d5aaa0f30534943847c84eaf7baffa7fbb9cfe6 Mon Sep 17 00:00:00 2001 From: lcnr Date: Fri, 6 Dec 2024 15:03:13 +0100 Subject: [PATCH 59/92] fix crashes --- .../rustc_borrowck/src/region_infer/mod.rs | 2 +- tests/crashes/124021.rs | 6 ------ .../overwrite-anon-late-param-regions.rs | 15 +++++++++++++ .../overwrite-anon-late-param-regions.stderr | 21 +++++++++++++++++++ 4 files changed, 37 insertions(+), 7 deletions(-) delete mode 100644 tests/crashes/124021.rs create mode 100644 tests/ui/borrowck/overwrite-anon-late-param-regions.rs create mode 100644 tests/ui/borrowck/overwrite-anon-late-param-regions.stderr diff --git a/compiler/rustc_borrowck/src/region_infer/mod.rs b/compiler/rustc_borrowck/src/region_infer/mod.rs index 0eecf98a6ede..d39fbf32921a 100644 --- a/compiler/rustc_borrowck/src/region_infer/mod.rs +++ b/compiler/rustc_borrowck/src/region_infer/mod.rs @@ -2230,7 +2230,7 @@ impl<'tcx> RegionDefinition<'tcx> { fn new(universe: ty::UniverseIndex, rv_origin: RegionVariableOrigin) -> Self { // Create a new region definition. Note that, for free // regions, the `external_name` field gets updated later in - // `init_universal_regions`. + // `init_free_and_bound_regions`. let origin = match rv_origin { RegionVariableOrigin::Nll(origin) => origin, diff --git a/tests/crashes/124021.rs b/tests/crashes/124021.rs deleted file mode 100644 index a2b6b7f9a663..000000000000 --- a/tests/crashes/124021.rs +++ /dev/null @@ -1,6 +0,0 @@ -//@ known-bug: #124021 -type Opaque2<'a> = impl Sized + 'a; - -fn test2() -> impl for<'a, 'b> Fn((&'a str, &'b str)) -> (Opaque2<'a>, Opaque2<'a>) { - |x| x -} diff --git a/tests/ui/borrowck/overwrite-anon-late-param-regions.rs b/tests/ui/borrowck/overwrite-anon-late-param-regions.rs new file mode 100644 index 000000000000..7b0f784068f6 --- /dev/null +++ b/tests/ui/borrowck/overwrite-anon-late-param-regions.rs @@ -0,0 +1,15 @@ +// A regression test for #124021. When liberating the late bound regions here +// we encounter multiple `LateBoundRegion::Anon`. These ended up resulting in +// distinct nll vars, but mapped to the same `RegionKind::LateParam`. This +// then caused an ICE when trying to fetch lazily computed information for the +// nll var of an overwritten liberated bound region. +#![feature(type_alias_impl_trait)] +type Opaque2<'a> = impl Sized + 'a; + +fn test2() -> impl for<'a, 'b> Fn((&'a str, &'b str)) -> (Opaque2<'a>, Opaque2<'a>) { + |x| x + //~^ ERROR lifetime may not live long enough + //~| ERROR expected generic lifetime parameter, found `'a` +} + +fn main() {} diff --git a/tests/ui/borrowck/overwrite-anon-late-param-regions.stderr b/tests/ui/borrowck/overwrite-anon-late-param-regions.stderr new file mode 100644 index 000000000000..c5b7284271e4 --- /dev/null +++ b/tests/ui/borrowck/overwrite-anon-late-param-regions.stderr @@ -0,0 +1,21 @@ +error: lifetime may not live long enough + --> $DIR/overwrite-anon-late-param-regions.rs:10:9 + | +LL | |x| x + | - ^ closure was supposed to return data with lifetime `'2` but it is returning data with lifetime `'1` + | | + | has type `(&str, &'1 str)` + | has type `(&'2 str, &str)` + +error[E0792]: expected generic lifetime parameter, found `'a` + --> $DIR/overwrite-anon-late-param-regions.rs:10:5 + | +LL | type Opaque2<'a> = impl Sized + 'a; + | -- this generic parameter must be used with a generic lifetime parameter +... +LL | |x| x + | ^^^^^ + +error: aborting due to 2 previous errors + +For more information about this error, try `rustc --explain E0792`. From 38ce73145c894399471c7a4bae588ac3c913b0a3 Mon Sep 17 00:00:00 2001 From: lcnr Date: Tue, 26 Nov 2024 09:29:01 +0100 Subject: [PATCH 60/92] canonicalizer: keep 'static in the param_env --- .../src/canonicalizer.rs | 119 ++++++++++++++---- .../src/solve/eval_ctxt/canonical.rs | 23 ++-- 2 files changed, 102 insertions(+), 40 deletions(-) diff --git a/compiler/rustc_next_trait_solver/src/canonicalizer.rs b/compiler/rustc_next_trait_solver/src/canonicalizer.rs index 63608f9e8561..2f7301d8fe51 100644 --- a/compiler/rustc_next_trait_solver/src/canonicalizer.rs +++ b/compiler/rustc_next_trait_solver/src/canonicalizer.rs @@ -3,6 +3,7 @@ use std::cmp::Ordering; use rustc_type_ir::data_structures::HashMap; use rustc_type_ir::fold::{TypeFoldable, TypeFolder, TypeSuperFoldable}; use rustc_type_ir::inherent::*; +use rustc_type_ir::solve::{Goal, QueryInput}; use rustc_type_ir::visit::TypeVisitableExt; use rustc_type_ir::{ self as ty, Canonical, CanonicalTyVarKind, CanonicalVarInfo, CanonicalVarKind, InferCtxtLike, @@ -17,8 +18,11 @@ use crate::delegate::SolverDelegate; /// while canonicalizing the response happens in the context of the /// query. #[derive(Debug, Clone, Copy)] -pub enum CanonicalizeMode { - Input, +enum CanonicalizeMode { + /// When canonicalizing the `param_env`, we keep `'static` as merging + /// trait candidates relies on it when deciding whether a where-bound + /// is trivial. + Input { keep_static: bool }, /// FIXME: We currently return region constraints referring to /// placeholders and inference variables from a binder instantiated /// inside of the query. @@ -59,15 +63,15 @@ pub struct Canonicalizer<'a, D: SolverDelegate, I: Interner> { } impl<'a, D: SolverDelegate, I: Interner> Canonicalizer<'a, D, I> { - pub fn canonicalize>( + pub fn canonicalize_response>( delegate: &'a D, - canonicalize_mode: CanonicalizeMode, + max_input_universe: ty::UniverseIndex, variables: &'a mut Vec, value: T, ) -> ty::Canonical { let mut canonicalizer = Canonicalizer { delegate, - canonicalize_mode, + canonicalize_mode: CanonicalizeMode::Response { max_input_universe }, variables, variable_lookup_table: Default::default(), @@ -80,9 +84,67 @@ impl<'a, D: SolverDelegate, I: Interner> Canonicalizer<'a, D, I> { let value = value.fold_with(&mut canonicalizer); assert!(!value.has_infer(), "unexpected infer in {value:?}"); assert!(!value.has_placeholders(), "unexpected placeholders in {value:?}"); - let (max_universe, variables) = canonicalizer.finalize(); + Canonical { max_universe, variables, value } + } + /// When canonicalizing query inputs, we keep `'static` in the `param_env` + /// but erase it everywhere else. We generally don't want to depend on region + /// identity, so while it should not matter whether `'static` is kept in the + /// value or opaque type storage as well, this prevents us from accidentally + /// relying on it in the future. + /// + /// We want to keep the option of canonicalizing `'static` to an existential + /// variable in the future by changing the way we detect global where-bounds. + pub fn canonicalize_input>( + delegate: &'a D, + variables: &'a mut Vec, + input: QueryInput, + ) -> ty::Canonical> { + // First canonicalize the `param_env` while keeping `'static` + let mut env_canonicalizer = Canonicalizer { + delegate, + canonicalize_mode: CanonicalizeMode::Input { keep_static: true }, + + variables, + variable_lookup_table: Default::default(), + primitive_var_infos: Vec::new(), + binder_index: ty::INNERMOST, + + cache: Default::default(), + }; + let param_env = input.goal.param_env.fold_with(&mut env_canonicalizer); + debug_assert_eq!(env_canonicalizer.binder_index, ty::INNERMOST); + // Then canonicalize the rest of the input without keeping `'static` + // while *mostly* reusing the canonicalizer from above. + let mut rest_canonicalizer = Canonicalizer { + delegate, + canonicalize_mode: CanonicalizeMode::Input { keep_static: false }, + + variables: env_canonicalizer.variables, + // We're able to reuse the `variable_lookup_table` as whether or not + // it already contains an entry for `'static` does not matter. + variable_lookup_table: env_canonicalizer.variable_lookup_table, + primitive_var_infos: env_canonicalizer.primitive_var_infos, + binder_index: ty::INNERMOST, + + // We do not reuse the cache as it may contain entries whose canonicalized + // value contains `'static`. While we could alternatively handle this by + // checking for `'static` when using cached entries, this does not + // feel worth the effort. I do not expect that a `ParamEnv` will ever + // contain large enough types for caching to be necessary. + cache: Default::default(), + }; + + let predicate = input.goal.predicate.fold_with(&mut rest_canonicalizer); + let goal = Goal { param_env, predicate }; + let predefined_opaques_in_body = + input.predefined_opaques_in_body.fold_with(&mut rest_canonicalizer); + let value = QueryInput { goal, predefined_opaques_in_body }; + + assert!(!value.has_infer(), "unexpected infer in {value:?}"); + assert!(!value.has_placeholders(), "unexpected placeholders in {value:?}"); + let (max_universe, variables) = rest_canonicalizer.finalize(); Canonical { max_universe, variables, value } } @@ -126,7 +188,7 @@ impl<'a, D: SolverDelegate, I: Interner> Canonicalizer<'a, D, I> { // all information which should not matter for the solver. // // For this we compress universes as much as possible. - CanonicalizeMode::Input => {} + CanonicalizeMode::Input { .. } => {} // When canonicalizing a response we map a universes already entered // by the caller to the root universe and only return useful universe // information for placeholders and inference variables created inside @@ -290,17 +352,15 @@ impl<'a, D: SolverDelegate, I: Interner> Canonicalizer<'a, D, I> { } }, ty::Placeholder(placeholder) => match self.canonicalize_mode { - CanonicalizeMode::Input => CanonicalVarKind::PlaceholderTy(PlaceholderLike::new( - placeholder.universe(), - self.variables.len().into(), - )), + CanonicalizeMode::Input { .. } => CanonicalVarKind::PlaceholderTy( + PlaceholderLike::new(placeholder.universe(), self.variables.len().into()), + ), CanonicalizeMode::Response { .. } => CanonicalVarKind::PlaceholderTy(placeholder), }, ty::Param(_) => match self.canonicalize_mode { - CanonicalizeMode::Input => CanonicalVarKind::PlaceholderTy(PlaceholderLike::new( - ty::UniverseIndex::ROOT, - self.variables.len().into(), - )), + CanonicalizeMode::Input { .. } => CanonicalVarKind::PlaceholderTy( + PlaceholderLike::new(ty::UniverseIndex::ROOT, self.variables.len().into()), + ), CanonicalizeMode::Response { .. } => panic!("param ty in response: {t:?}"), }, ty::Bool @@ -357,21 +417,30 @@ impl, I: Interner> TypeFolder for Canonicaliz let kind = match r.kind() { ty::ReBound(..) => return r, - // We may encounter `ReStatic` in item signatures or the hidden type - // of an opaque. `ReErased` should only be encountered in the hidden + // We don't canonicalize `ReStatic` in the `param_env` as we use it + // when checking whether a `ParamEnv` candidate is global. + ty::ReStatic => match self.canonicalize_mode { + CanonicalizeMode::Input { keep_static: false } => { + CanonicalVarKind::Region(ty::UniverseIndex::ROOT) + } + CanonicalizeMode::Input { keep_static: true } + | CanonicalizeMode::Response { .. } => return r, + }, + + // `ReErased` should only be encountered in the hidden // type of an opaque for regions that are ignored for the purposes of // captures. // // FIXME: We should investigate the perf implications of not uniquifying // `ReErased`. We may be able to short-circuit registering region // obligations if we encounter a `ReErased` on one side, for example. - ty::ReStatic | ty::ReErased | ty::ReError(_) => match self.canonicalize_mode { - CanonicalizeMode::Input => CanonicalVarKind::Region(ty::UniverseIndex::ROOT), + ty::ReErased | ty::ReError(_) => match self.canonicalize_mode { + CanonicalizeMode::Input { .. } => CanonicalVarKind::Region(ty::UniverseIndex::ROOT), CanonicalizeMode::Response { .. } => return r, }, ty::ReEarlyParam(_) | ty::ReLateParam(_) => match self.canonicalize_mode { - CanonicalizeMode::Input => CanonicalVarKind::Region(ty::UniverseIndex::ROOT), + CanonicalizeMode::Input { .. } => CanonicalVarKind::Region(ty::UniverseIndex::ROOT), CanonicalizeMode::Response { .. } => { panic!("unexpected region in response: {r:?}") } @@ -379,7 +448,7 @@ impl, I: Interner> TypeFolder for Canonicaliz ty::RePlaceholder(placeholder) => match self.canonicalize_mode { // We canonicalize placeholder regions as existentials in query inputs. - CanonicalizeMode::Input => CanonicalVarKind::Region(ty::UniverseIndex::ROOT), + CanonicalizeMode::Input { .. } => CanonicalVarKind::Region(ty::UniverseIndex::ROOT), CanonicalizeMode::Response { max_input_universe } => { // If we have a placeholder region inside of a query, it must be from // a new universe. @@ -397,7 +466,9 @@ impl, I: Interner> TypeFolder for Canonicaliz "region vid should have been resolved fully before canonicalization" ); match self.canonicalize_mode { - CanonicalizeMode::Input => CanonicalVarKind::Region(ty::UniverseIndex::ROOT), + CanonicalizeMode::Input { keep_static: _ } => { + CanonicalVarKind::Region(ty::UniverseIndex::ROOT) + } CanonicalizeMode::Response { .. } => { CanonicalVarKind::Region(self.delegate.universe_of_lt(vid).unwrap()) } @@ -434,7 +505,7 @@ impl, I: Interner> TypeFolder for Canonicaliz ty::InferConst::Fresh(_) => todo!(), }, ty::ConstKind::Placeholder(placeholder) => match self.canonicalize_mode { - CanonicalizeMode::Input => CanonicalVarKind::PlaceholderConst( + CanonicalizeMode::Input { .. } => CanonicalVarKind::PlaceholderConst( PlaceholderLike::new(placeholder.universe(), self.variables.len().into()), ), CanonicalizeMode::Response { .. } => { @@ -442,7 +513,7 @@ impl, I: Interner> TypeFolder for Canonicaliz } }, ty::ConstKind::Param(_) => match self.canonicalize_mode { - CanonicalizeMode::Input => CanonicalVarKind::PlaceholderConst( + CanonicalizeMode::Input { .. } => CanonicalVarKind::PlaceholderConst( PlaceholderLike::new(ty::UniverseIndex::ROOT, self.variables.len().into()), ), CanonicalizeMode::Response { .. } => panic!("param ty in response: {c:?}"), diff --git a/compiler/rustc_next_trait_solver/src/solve/eval_ctxt/canonical.rs b/compiler/rustc_next_trait_solver/src/solve/eval_ctxt/canonical.rs index a143af13688b..e99cd3d27270 100644 --- a/compiler/rustc_next_trait_solver/src/solve/eval_ctxt/canonical.rs +++ b/compiler/rustc_next_trait_solver/src/solve/eval_ctxt/canonical.rs @@ -18,7 +18,7 @@ use rustc_type_ir::relate::solver_relating::RelateExt; use rustc_type_ir::{self as ty, Canonical, CanonicalVarValues, InferCtxtLike, Interner}; use tracing::{debug, instrument, trace}; -use crate::canonicalizer::{CanonicalizeMode, Canonicalizer}; +use crate::canonicalizer::Canonicalizer; use crate::delegate::SolverDelegate; use crate::resolve::EagerResolver; use crate::solve::eval_ctxt::NestedGoals; @@ -60,17 +60,13 @@ where (goal, opaque_types).fold_with(&mut EagerResolver::new(self.delegate)); let mut orig_values = Default::default(); - let canonical = Canonicalizer::canonicalize( - self.delegate, - CanonicalizeMode::Input, - &mut orig_values, - QueryInput { + let canonical = + Canonicalizer::canonicalize_input(self.delegate, &mut orig_values, QueryInput { goal, predefined_opaques_in_body: self .cx() .mk_predefined_opaques_in_body(PredefinedOpaquesData { opaque_types }), - }, - ); + }); let query_input = ty::CanonicalQueryInput { canonical, typing_mode: self.typing_mode() }; (orig_values, query_input) } @@ -148,9 +144,9 @@ where .region_constraints .retain(|outlives| outlives.0.as_region().map_or(true, |re| re != outlives.1)); - let canonical = Canonicalizer::canonicalize( + let canonical = Canonicalizer::canonicalize_response( self.delegate, - CanonicalizeMode::Response { max_input_universe: self.max_input_universe }, + self.max_input_universe, &mut Default::default(), Response { var_values, @@ -428,12 +424,7 @@ where let var_values = CanonicalVarValues { var_values: delegate.cx().mk_args(var_values) }; let state = inspect::State { var_values, data }; let state = state.fold_with(&mut EagerResolver::new(delegate)); - Canonicalizer::canonicalize( - delegate, - CanonicalizeMode::Response { max_input_universe }, - &mut vec![], - state, - ) + Canonicalizer::canonicalize_response(delegate, max_input_universe, &mut vec![], state) } // FIXME: needs to be pub to be accessed by downstream From 6734a04c0a6aff674011c9b4cb1c89cba2636c4d Mon Sep 17 00:00:00 2001 From: acceptacross Date: Wed, 18 Dec 2024 23:23:44 +0800 Subject: [PATCH 61/92] chore: fix some typos Signed-off-by: acceptacross --- compiler/rustc_codegen_cranelift/src/compiler_builtins.rs | 2 +- compiler/rustc_codegen_gcc/src/intrinsic/mod.rs | 2 +- compiler/rustc_errors/src/emitter.rs | 2 +- compiler/rustc_errors/src/markdown/parse.rs | 2 +- compiler/rustc_resolve/src/late.rs | 2 +- compiler/rustc_trait_selection/src/traits/mod.rs | 2 +- 6 files changed, 6 insertions(+), 6 deletions(-) diff --git a/compiler/rustc_codegen_cranelift/src/compiler_builtins.rs b/compiler/rustc_codegen_cranelift/src/compiler_builtins.rs index 4154a62234c1..f8e3a034421d 100644 --- a/compiler/rustc_codegen_cranelift/src/compiler_builtins.rs +++ b/compiler/rustc_codegen_cranelift/src/compiler_builtins.rs @@ -3,7 +3,7 @@ use std::ffi::c_int; #[cfg(feature = "jit")] use std::ffi::c_void; -// FIXME replace with core::ffi::c_size_t once stablized +// FIXME replace with core::ffi::c_size_t once stabilized #[allow(non_camel_case_types)] #[cfg(feature = "jit")] type size_t = usize; diff --git a/compiler/rustc_codegen_gcc/src/intrinsic/mod.rs b/compiler/rustc_codegen_gcc/src/intrinsic/mod.rs index 69326f409bb3..78ec9741f578 100644 --- a/compiler/rustc_codegen_gcc/src/intrinsic/mod.rs +++ b/compiler/rustc_codegen_gcc/src/intrinsic/mod.rs @@ -66,7 +66,7 @@ fn get_simple_intrinsic<'gcc, 'tcx>( sym::log2f64 => "log2", sym::fmaf32 => "fmaf", sym::fmaf64 => "fma", - // FIXME: calling `fma` from libc without FMA target feature uses expensive sofware emulation + // FIXME: calling `fma` from libc without FMA target feature uses expensive software emulation sym::fmuladdf32 => "fmaf", // TODO: use gcc intrinsic analogous to llvm.fmuladd.f32 sym::fmuladdf64 => "fma", // TODO: use gcc intrinsic analogous to llvm.fmuladd.f64 sym::fabsf32 => "fabsf", diff --git a/compiler/rustc_errors/src/emitter.rs b/compiler/rustc_errors/src/emitter.rs index ac2f91cdeb3f..f63188402fe7 100644 --- a/compiler/rustc_errors/src/emitter.rs +++ b/compiler/rustc_errors/src/emitter.rs @@ -2523,7 +2523,7 @@ impl HumanEmitter { buffer.puts(*row_num, max_line_num_len + 1, "+ ", Style::Addition); } [] => { - // FIXME: needed? Doesn't get excercised in any test. + // FIXME: needed? Doesn't get exercised in any test. self.draw_col_separator_no_space(buffer, *row_num, max_line_num_len + 1); } _ => { diff --git a/compiler/rustc_errors/src/markdown/parse.rs b/compiler/rustc_errors/src/markdown/parse.rs index 8dd146c1c337..7a991a2ace71 100644 --- a/compiler/rustc_errors/src/markdown/parse.rs +++ b/compiler/rustc_errors/src/markdown/parse.rs @@ -346,7 +346,7 @@ fn parse_with_end_pat<'a>( None } -/// Resturn `(match, residual)` to end of line. The EOL is returned with the +/// Return `(match, residual)` to end of line. The EOL is returned with the /// residual. fn parse_to_newline(buf: &[u8]) -> (&[u8], &[u8]) { buf.iter().position(|ch| *ch == b'\n').map_or((buf, &[]), |pos| buf.split_at(pos)) diff --git a/compiler/rustc_resolve/src/late.rs b/compiler/rustc_resolve/src/late.rs index a48a2865228a..7324d3fe7862 100644 --- a/compiler/rustc_resolve/src/late.rs +++ b/compiler/rustc_resolve/src/late.rs @@ -4325,7 +4325,7 @@ impl<'a, 'ast, 'ra: 'ast, 'tcx> LateResolutionVisitor<'a, 'ast, 'ra, 'tcx> { #[inline] /// If we're actually rustdoc then avoid giving a name resolution error for `cfg()` items or - // an invalid `use foo::*;` was found, which can cause unbounded ammounts of "item not found" + // an invalid `use foo::*;` was found, which can cause unbounded amounts of "item not found" // errors. We silence them all. fn should_report_errs(&self) -> bool { !(self.r.tcx.sess.opts.actually_rustdoc && self.in_func_body) diff --git a/compiler/rustc_trait_selection/src/traits/mod.rs b/compiler/rustc_trait_selection/src/traits/mod.rs index 069d42d4018c..1dcd0d0dfb83 100644 --- a/compiler/rustc_trait_selection/src/traits/mod.rs +++ b/compiler/rustc_trait_selection/src/traits/mod.rs @@ -599,7 +599,7 @@ pub fn try_evaluate_const<'tcx>( // even though it is not something we should ever actually encounter. // // Array repeat expr counts are allowed to syntactically use generic parameters - // but must not actually depend on them in order to evalaute succesfully. This means + // but must not actually depend on them in order to evalaute successfully. This means // that it is actually fine to evalaute them in their own environment rather than with // the actually provided generic arguments. tcx.dcx().delayed_bug( From d5a0c5cfdbebc1366c8c801b3b7f9348f0197296 Mon Sep 17 00:00:00 2001 From: lcnr Date: Tue, 26 Nov 2024 12:09:42 +0100 Subject: [PATCH 62/92] update new solver candidate assembly --- compiler/rustc_middle/src/ty/mod.rs | 2 +- .../src/solve/assembly/mod.rs | 134 ++++++++---------- .../src/solve/effect_goals.rs | 8 +- .../src/solve/eval_ctxt/mod.rs | 2 +- .../rustc_next_trait_solver/src/solve/mod.rs | 25 ++-- .../src/solve/normalizes_to/mod.rs | 11 +- .../src/solve/trait_goals.rs | 93 +++++++++++- compiler/rustc_type_ir/src/inherent.rs | 2 +- ...-method-resolution-opaque-type.next.stderr | 9 -- ...e-method-resolution-opaque-type.old.stderr | 4 +- ...rm-before-method-resolution-opaque-type.rs | 2 +- 11 files changed, 187 insertions(+), 105 deletions(-) delete mode 100644 tests/ui/higher-ranked/trait-bounds/normalize-under-binder/norm-before-method-resolution-opaque-type.next.stderr diff --git a/compiler/rustc_middle/src/ty/mod.rs b/compiler/rustc_middle/src/ty/mod.rs index 25d0d7b71da6..830ae7dd00a6 100644 --- a/compiler/rustc_middle/src/ty/mod.rs +++ b/compiler/rustc_middle/src/ty/mod.rs @@ -971,7 +971,7 @@ pub struct ParamEnv<'tcx> { } impl<'tcx> rustc_type_ir::inherent::ParamEnv> for ParamEnv<'tcx> { - fn caller_bounds(self) -> impl IntoIterator> { + fn caller_bounds(self) -> impl inherent::SliceLike> { self.caller_bounds() } } diff --git a/compiler/rustc_next_trait_solver/src/solve/assembly/mod.rs b/compiler/rustc_next_trait_solver/src/solve/assembly/mod.rs index 198ccb000f34..02f6439b77fb 100644 --- a/compiler/rustc_next_trait_solver/src/solve/assembly/mod.rs +++ b/compiler/rustc_next_trait_solver/src/solve/assembly/mod.rs @@ -11,6 +11,7 @@ use rustc_type_ir::visit::TypeVisitableExt as _; use rustc_type_ir::{self as ty, Interner, TypingMode, Upcast as _, elaborate}; use tracing::{debug, instrument}; +use super::trait_goals::TraitGoalProvenVia; use crate::delegate::SolverDelegate; use crate::solve::inspect::ProbeKind; use crate::solve::{ @@ -337,15 +338,6 @@ where self.assemble_param_env_candidates(goal, &mut candidates); - match self.typing_mode() { - TypingMode::Coherence => {} - TypingMode::Analysis { .. } - | TypingMode::PostBorrowckAnalysis { .. } - | TypingMode::PostAnalysis => { - self.discard_impls_shadowed_by_env(goal, &mut candidates); - } - } - candidates } @@ -500,7 +492,7 @@ where goal: Goal, candidates: &mut Vec>, ) { - for (i, assumption) in goal.param_env.caller_bounds().into_iter().enumerate() { + for (i, assumption) in goal.param_env.caller_bounds().iter().enumerate() { candidates.extend(G::probe_and_consider_implied_clause( self, CandidateSource::ParamEnv(i), @@ -733,72 +725,64 @@ where }) } - /// If there's a where-bound for the current goal, do not use any impl candidates - /// to prove the current goal. Most importantly, if there is a where-bound which does - /// not specify any associated types, we do not allow normalizing the associated type - /// by using an impl, even if it would apply. + /// We sadly can't simply take all possible candidates for normalization goals + /// and check whether they result in the same constraints. We want to make sure + /// that trying to normalize an alias doesn't result in constraints which aren't + /// otherwise required. /// - /// - // FIXME(@lcnr): The current structure here makes me unhappy and feels ugly. idk how - // to improve this however. However, this should make it fairly straightforward to refine - // the filtering going forward, so it seems alright-ish for now. - #[instrument(level = "debug", skip(self, goal))] - fn discard_impls_shadowed_by_env>( - &mut self, - goal: Goal, - candidates: &mut Vec>, - ) { - let cx = self.cx(); - let trait_goal: Goal> = - goal.with(cx, goal.predicate.trait_ref(cx)); - - let mut trait_candidates_from_env = vec![]; - self.probe(|_| ProbeKind::ShadowedEnvProbing).enter(|ecx| { - ecx.assemble_param_env_candidates(trait_goal, &mut trait_candidates_from_env); - ecx.assemble_alias_bound_candidates(trait_goal, &mut trait_candidates_from_env); - }); - - if !trait_candidates_from_env.is_empty() { - let trait_env_result = self.merge_candidates(trait_candidates_from_env); - match trait_env_result.unwrap().value.certainty { - // If proving the trait goal succeeds by using the env, - // we freely drop all impl candidates. - // - // FIXME(@lcnr): It feels like this could easily hide - // a forced ambiguity candidate added earlier. - // This feels dangerous. - Certainty::Yes => { - candidates.retain(|c| match c.source { - CandidateSource::Impl(_) | CandidateSource::BuiltinImpl(_) => { - debug!(?c, "discard impl candidate"); - false - } - CandidateSource::ParamEnv(_) | CandidateSource::AliasBound => true, - CandidateSource::CoherenceUnknowable => panic!("uh oh"), - }); - } - // If it is still ambiguous we instead just force the whole goal - // to be ambig and wait for inference constraints. See - // tests/ui/traits/next-solver/env-shadows-impls/ambig-env-no-shadow.rs - Certainty::Maybe(cause) => { - debug!(?cause, "force ambiguity"); - *candidates = self.forced_ambiguity(cause).into_iter().collect(); - } - } - } - } - - /// If there are multiple ways to prove a trait or projection goal, we have - /// to somehow try to merge the candidates into one. If that fails, we return - /// ambiguity. + /// Most notably, when proving a trait goal by via a where-bound, we should not + /// normalize via impls which have stricter region constraints than the where-bound: + /// + /// ```rust + /// trait Trait<'a> { + /// type Assoc; + /// } + /// + /// impl<'a, T: 'a> Trait<'a> for T { + /// type Assoc = u32; + /// } + /// + /// fn with_bound<'a, T: Trait<'a>>(_value: T::Assoc) {} + /// ``` + /// + /// The where-bound of `with_bound` doesn't specify the associated type, so we would + /// only be able to normalize `>::Assoc` by using the impl. This impl + /// adds a `T: 'a` bound however, which would result in a region error. Given that the + /// user explicitly wrote that `T: Trait<'a>` holds, this is undesirable and we instead + /// treat the alias as rigid. + /// + /// See trait-system-refactor-initiative#124 for more details. #[instrument(level = "debug", skip(self), ret)] - pub(super) fn merge_candidates(&mut self, candidates: Vec>) -> QueryResult { - // First try merging all candidates. This is complete and fully sound. - let responses = candidates.iter().map(|c| c.result).collect::>(); - if let Some(result) = self.try_merge_responses(&responses) { - return Ok(result); - } else { - self.flounder(&responses) - } + pub(super) fn merge_candidates( + &mut self, + proven_via: Option, + candidates: Vec>, + ) -> QueryResult { + let Some(proven_via) = proven_via else { + // We don't care about overflow. If proving the trait goal overflowed, then + // it's enough to report an overflow error for that, we don't also have to + // overflow during normalization. + return Ok(self.make_ambiguous_response_no_constraints(MaybeCause::Ambiguity)); + }; + + let responses: Vec<_> = match proven_via { + // Even when a trait bound has been proven using a where-bound, we + // still need to consider alias-bounds for normalization, see + // tests/ui/next-solver/alias-bound-shadowed-by-env.rs. + // + // FIXME(const_trait_impl): should this behavior also be used by + // constness checking. Doing so is *at least theoretically* breaking, + // see github.com/rust-lang/rust/issues/133044#issuecomment-2500709754 + TraitGoalProvenVia::ParamEnv | TraitGoalProvenVia::AliasBound => candidates + .iter() + .filter(|c| { + matches!(c.source, CandidateSource::AliasBound | CandidateSource::ParamEnv(_)) + }) + .map(|c| c.result) + .collect(), + TraitGoalProvenVia::Misc => candidates.iter().map(|c| c.result).collect(), + }; + + self.try_merge_responses(&responses).map_or_else(|| self.flounder(&responses), Ok) } } diff --git a/compiler/rustc_next_trait_solver/src/solve/effect_goals.rs b/compiler/rustc_next_trait_solver/src/solve/effect_goals.rs index 81b5199002b2..ce7552e30f0f 100644 --- a/compiler/rustc_next_trait_solver/src/solve/effect_goals.rs +++ b/compiler/rustc_next_trait_solver/src/solve/effect_goals.rs @@ -4,6 +4,7 @@ use rustc_type_ir::fast_reject::DeepRejectCtxt; use rustc_type_ir::inherent::*; use rustc_type_ir::lang_items::TraitSolverLangItem; +use rustc_type_ir::solve::inspect::ProbeKind; use rustc_type_ir::{self as ty, Interner, elaborate}; use tracing::instrument; @@ -391,6 +392,11 @@ where goal: Goal>, ) -> QueryResult { let candidates = self.assemble_and_evaluate_candidates(goal); - self.merge_candidates(candidates) + let (_, proven_via) = self.probe(|_| ProbeKind::ShadowedEnvProbing).enter(|ecx| { + let trait_goal: Goal> = + goal.with(ecx.cx(), goal.predicate.trait_ref); + ecx.compute_trait_goal(trait_goal) + })?; + self.merge_candidates(proven_via, candidates) } } diff --git a/compiler/rustc_next_trait_solver/src/solve/eval_ctxt/mod.rs b/compiler/rustc_next_trait_solver/src/solve/eval_ctxt/mod.rs index 70ceb22bfea5..8c74490e0e0e 100644 --- a/compiler/rustc_next_trait_solver/src/solve/eval_ctxt/mod.rs +++ b/compiler/rustc_next_trait_solver/src/solve/eval_ctxt/mod.rs @@ -440,7 +440,7 @@ where if let Some(kind) = kind.no_bound_vars() { match kind { ty::PredicateKind::Clause(ty::ClauseKind::Trait(predicate)) => { - self.compute_trait_goal(Goal { param_env, predicate }) + self.compute_trait_goal(Goal { param_env, predicate }).map(|(r, _via)| r) } ty::PredicateKind::Clause(ty::ClauseKind::HostEffect(predicate)) => { self.compute_host_effect_goal(Goal { param_env, predicate }) diff --git a/compiler/rustc_next_trait_solver/src/solve/mod.rs b/compiler/rustc_next_trait_solver/src/solve/mod.rs index ebf1013db1ec..37678bfd8805 100644 --- a/compiler/rustc_next_trait_solver/src/solve/mod.rs +++ b/compiler/rustc_next_trait_solver/src/solve/mod.rs @@ -243,22 +243,27 @@ where .copied() } + fn bail_with_ambiguity(&mut self, responses: &[CanonicalResponse]) -> CanonicalResponse { + debug_assert!(!responses.is_empty()); + if let Certainty::Maybe(maybe_cause) = + responses.iter().fold(Certainty::AMBIGUOUS, |certainty, response| { + certainty.unify_with(response.value.certainty) + }) + { + self.make_ambiguous_response_no_constraints(maybe_cause) + } else { + panic!("expected flounder response to be ambiguous") + } + } + /// If we fail to merge responses we flounder and return overflow or ambiguity. #[instrument(level = "trace", skip(self), ret)] fn flounder(&mut self, responses: &[CanonicalResponse]) -> QueryResult { if responses.is_empty() { return Err(NoSolution); + } else { + Ok(self.bail_with_ambiguity(responses)) } - - let Certainty::Maybe(maybe_cause) = - responses.iter().fold(Certainty::AMBIGUOUS, |certainty, response| { - certainty.unify_with(response.value.certainty) - }) - else { - panic!("expected flounder response to be ambiguous") - }; - - Ok(self.make_ambiguous_response_no_constraints(maybe_cause)) } /// Normalize a type for when it is structurally matched on. diff --git a/compiler/rustc_next_trait_solver/src/solve/normalizes_to/mod.rs b/compiler/rustc_next_trait_solver/src/solve/normalizes_to/mod.rs index 63dbee2640bf..b88671922251 100644 --- a/compiler/rustc_next_trait_solver/src/solve/normalizes_to/mod.rs +++ b/compiler/rustc_next_trait_solver/src/solve/normalizes_to/mod.rs @@ -88,10 +88,17 @@ where /// returns `NoSolution`. #[instrument(level = "trace", skip(self), ret)] fn normalize_at_least_one_step(&mut self, goal: Goal>) -> QueryResult { - match goal.predicate.alias.kind(self.cx()) { + let cx = self.cx(); + match goal.predicate.alias.kind(cx) { ty::AliasTermKind::ProjectionTy | ty::AliasTermKind::ProjectionConst => { let candidates = self.assemble_and_evaluate_candidates(goal); - self.merge_candidates(candidates) + let (_, proven_via) = + self.probe(|_| ProbeKind::ShadowedEnvProbing).enter(|ecx| { + let trait_goal: Goal> = + goal.with(cx, goal.predicate.alias.trait_ref(cx)); + ecx.compute_trait_goal(trait_goal) + })?; + self.merge_candidates(proven_via, candidates) } ty::AliasTermKind::InherentTy => self.normalize_inherent_associated_type(goal), ty::AliasTermKind::OpaqueTy => self.normalize_opaque_type(goal), diff --git a/compiler/rustc_next_trait_solver/src/solve/trait_goals.rs b/compiler/rustc_next_trait_solver/src/solve/trait_goals.rs index 12df35d30b8f..886cdec03455 100644 --- a/compiler/rustc_next_trait_solver/src/solve/trait_goals.rs +++ b/compiler/rustc_next_trait_solver/src/solve/trait_goals.rs @@ -5,6 +5,7 @@ use rustc_type_ir::data_structures::IndexSet; use rustc_type_ir::fast_reject::DeepRejectCtxt; use rustc_type_ir::inherent::*; use rustc_type_ir::lang_items::TraitSolverLangItem; +use rustc_type_ir::solve::CanonicalResponse; use rustc_type_ir::visit::TypeVisitableExt as _; use rustc_type_ir::{self as ty, Interner, TraitPredicate, TypingMode, Upcast as _, elaborate}; use tracing::{instrument, trace}; @@ -1147,13 +1148,101 @@ where ecx.evaluate_added_goals_and_make_canonical_response(Certainty::Yes) }) } +} + +/// How we've proven this trait goal. +/// +/// This is used by `NormalizesTo` goals to only normalize +/// by using the same 'kind of candidate' we've used to prove +/// its corresponding trait goal. Most notably, we do not +/// normalize by using an impl if the trait goal has been +/// proven via a `ParamEnv` candidate. +/// +/// This is necessary to avoid unnecessary region constraints, +/// see trait-system-refactor-initiative#125 for more details. +#[derive(Debug, Clone, Copy)] +pub(super) enum TraitGoalProvenVia { + /// We've proven the trait goal by something which is + /// is not a non-global where-bound or an alias-bound. + /// + /// This means we don't disable any candidates during + /// normalization. + Misc, + ParamEnv, + AliasBound, +} + +impl EvalCtxt<'_, D> +where + D: SolverDelegate, + I: Interner, +{ + pub(super) fn merge_trait_candidates( + &mut self, + goal: Goal>, + candidates: Vec>, + ) -> Result<(CanonicalResponse, Option), NoSolution> { + if let TypingMode::Coherence = self.typing_mode() { + let all_candidates: Vec<_> = candidates.into_iter().map(|c| c.result).collect(); + return if let Some(response) = self.try_merge_responses(&all_candidates) { + Ok((response, Some(TraitGoalProvenVia::Misc))) + } else { + self.flounder(&all_candidates).map(|r| (r, None)) + }; + } + + // FIXME: prefer trivial builtin impls + + // If there are non-global where-bounds, prefer where-bounds + // (including global ones) over everything else. + let has_non_global_where_bounds = candidates.iter().any(|c| match c.source { + CandidateSource::ParamEnv(idx) => { + let where_bound = goal.param_env.caller_bounds().get(idx); + where_bound.has_bound_vars() || !where_bound.is_global() + } + _ => false, + }); + if has_non_global_where_bounds { + let where_bounds: Vec<_> = candidates + .iter() + .filter(|c| matches!(c.source, CandidateSource::ParamEnv(_))) + .map(|c| c.result) + .collect(); + + return if let Some(response) = self.try_merge_responses(&where_bounds) { + Ok((response, Some(TraitGoalProvenVia::ParamEnv))) + } else { + Ok((self.bail_with_ambiguity(&where_bounds), None)) + }; + } + + if candidates.iter().any(|c| matches!(c.source, CandidateSource::AliasBound)) { + let alias_bounds: Vec<_> = candidates + .iter() + .filter(|c| matches!(c.source, CandidateSource::AliasBound)) + .map(|c| c.result) + .collect(); + return if let Some(response) = self.try_merge_responses(&alias_bounds) { + Ok((response, Some(TraitGoalProvenVia::AliasBound))) + } else { + Ok((self.bail_with_ambiguity(&alias_bounds), None)) + }; + } + + let all_candidates: Vec<_> = candidates.into_iter().map(|c| c.result).collect(); + if let Some(response) = self.try_merge_responses(&all_candidates) { + Ok((response, Some(TraitGoalProvenVia::Misc))) + } else { + self.flounder(&all_candidates).map(|r| (r, None)) + } + } #[instrument(level = "trace", skip(self))] pub(super) fn compute_trait_goal( &mut self, goal: Goal>, - ) -> QueryResult { + ) -> Result<(CanonicalResponse, Option), NoSolution> { let candidates = self.assemble_and_evaluate_candidates(goal); - self.merge_candidates(candidates) + self.merge_trait_candidates(goal, candidates) } } diff --git a/compiler/rustc_type_ir/src/inherent.rs b/compiler/rustc_type_ir/src/inherent.rs index f45c94127bd0..2db40accda39 100644 --- a/compiler/rustc_type_ir/src/inherent.rs +++ b/compiler/rustc_type_ir/src/inherent.rs @@ -543,7 +543,7 @@ pub trait AdtDef: Copy + Debug + Hash + Eq { } pub trait ParamEnv: Copy + Debug + Hash + Eq + TypeFoldable { - fn caller_bounds(self) -> impl IntoIterator; + fn caller_bounds(self) -> impl SliceLike; } pub trait Features: Copy { diff --git a/tests/ui/higher-ranked/trait-bounds/normalize-under-binder/norm-before-method-resolution-opaque-type.next.stderr b/tests/ui/higher-ranked/trait-bounds/normalize-under-binder/norm-before-method-resolution-opaque-type.next.stderr deleted file mode 100644 index 9e04e90a98ac..000000000000 --- a/tests/ui/higher-ranked/trait-bounds/normalize-under-binder/norm-before-method-resolution-opaque-type.next.stderr +++ /dev/null @@ -1,9 +0,0 @@ -error[E0284]: type annotations needed: cannot satisfy `Foo == _` - --> $DIR/norm-before-method-resolution-opaque-type.rs:15:19 - | -LL | fn weird_bound(x: &>::Out) -> X - | ^ cannot satisfy `Foo == _` - -error: aborting due to 1 previous error - -For more information about this error, try `rustc --explain E0284`. diff --git a/tests/ui/higher-ranked/trait-bounds/normalize-under-binder/norm-before-method-resolution-opaque-type.old.stderr b/tests/ui/higher-ranked/trait-bounds/normalize-under-binder/norm-before-method-resolution-opaque-type.old.stderr index 479f59843557..57cbe1691182 100644 --- a/tests/ui/higher-ranked/trait-bounds/normalize-under-binder/norm-before-method-resolution-opaque-type.old.stderr +++ b/tests/ui/higher-ranked/trait-bounds/normalize-under-binder/norm-before-method-resolution-opaque-type.old.stderr @@ -1,12 +1,12 @@ error: item does not constrain `Foo::{opaque#0}`, but has it in its signature - --> $DIR/norm-before-method-resolution-opaque-type.rs:15:4 + --> $DIR/norm-before-method-resolution-opaque-type.rs:16:4 | LL | fn weird_bound(x: &>::Out) -> X | ^^^^^^^^^^^ | = note: consider moving the opaque type's declaration and defining uses into a separate module note: this opaque type is in the signature - --> $DIR/norm-before-method-resolution-opaque-type.rs:13:12 + --> $DIR/norm-before-method-resolution-opaque-type.rs:14:12 | LL | type Foo = impl Sized; | ^^^^^^^^^^ diff --git a/tests/ui/higher-ranked/trait-bounds/normalize-under-binder/norm-before-method-resolution-opaque-type.rs b/tests/ui/higher-ranked/trait-bounds/normalize-under-binder/norm-before-method-resolution-opaque-type.rs index ffbfc622bb01..43207d892764 100644 --- a/tests/ui/higher-ranked/trait-bounds/normalize-under-binder/norm-before-method-resolution-opaque-type.rs +++ b/tests/ui/higher-ranked/trait-bounds/normalize-under-binder/norm-before-method-resolution-opaque-type.rs @@ -1,5 +1,6 @@ //@ revisions: old next //@[next] compile-flags: -Znext-solver +//@[next] check-pass #![feature(type_alias_impl_trait)] trait Trait<'a> { @@ -14,7 +15,6 @@ type Foo = impl Sized; fn weird_bound(x: &>::Out) -> X //[old]~^ ERROR: item does not constrain -//[next]~^^ ERROR: cannot satisfy `Foo == _` where for<'a> X: Trait<'a>, for<'a> >::Out<()>: Copy, From f0ae48d1065b6d017df75dc2d70a7c56b272b54d Mon Sep 17 00:00:00 2001 From: lcnr Date: Fri, 29 Nov 2024 18:43:55 +0100 Subject: [PATCH 63/92] add tests --- tests/crashes/133639.rs | 33 ------------------- .../specialization-fuzzing-ice-133639.rs | 19 +++++++++++ .../specialization-fuzzing-ice-133639.stderr | 11 +++++++ .../param-env-eager-norm-dedup.rs | 3 ++ .../winnowing/global-non-global-env-1.rs | 3 ++ .../winnowing/global-non-global-env-2.rs | 3 ++ .../winnowing/global-non-global-env-3.rs | 3 ++ .../winnowing/global-non-global-env-4.rs | 3 ++ 8 files changed, 45 insertions(+), 33 deletions(-) delete mode 100644 tests/crashes/133639.rs create mode 100644 tests/ui/const-generics/generic_const_exprs/specialization-fuzzing-ice-133639.rs create mode 100644 tests/ui/const-generics/generic_const_exprs/specialization-fuzzing-ice-133639.stderr diff --git a/tests/crashes/133639.rs b/tests/crashes/133639.rs deleted file mode 100644 index d522b0730cf8..000000000000 --- a/tests/crashes/133639.rs +++ /dev/null @@ -1,33 +0,0 @@ -//@ known-bug: #133639 - -#![feature(with_negative_coherence)] -#![feature(min_specialization)] -#![feature(generic_const_exprs)] - -#![crate_type = "lib"] -use std::str::FromStr; - -struct a; - -trait c {} - -impl FromStr for e -where - a<{ d <= 2 }>: c, -{ - type Err = (); - fn from_str(f: &str) -> Result { - unimplemented!() - } -} -struct e; - -impl FromStr for e -where - a<{ d <= 2 }>: c, -{ - type Err = (); - fn from_str(f: &str) -> Result { - unimplemented!() - } -} diff --git a/tests/ui/const-generics/generic_const_exprs/specialization-fuzzing-ice-133639.rs b/tests/ui/const-generics/generic_const_exprs/specialization-fuzzing-ice-133639.rs new file mode 100644 index 000000000000..d3ae863bee96 --- /dev/null +++ b/tests/ui/const-generics/generic_const_exprs/specialization-fuzzing-ice-133639.rs @@ -0,0 +1,19 @@ +//@ check-pass + +// Regression test for #133639. + +#![feature(with_negative_coherence)] +#![feature(min_specialization)] +#![feature(generic_const_exprs)] +//~^ WARNING the feature `generic_const_exprs` is incomplete + +#![crate_type = "lib"] +trait Trait {} +struct A; + +trait C {} + +impl Trait for E where A<{ D <= 2 }>: C {} +struct E; + +impl Trait for E where A<{ D <= 2 }>: C {} diff --git a/tests/ui/const-generics/generic_const_exprs/specialization-fuzzing-ice-133639.stderr b/tests/ui/const-generics/generic_const_exprs/specialization-fuzzing-ice-133639.stderr new file mode 100644 index 000000000000..f17b248d856d --- /dev/null +++ b/tests/ui/const-generics/generic_const_exprs/specialization-fuzzing-ice-133639.stderr @@ -0,0 +1,11 @@ +warning: the feature `generic_const_exprs` is incomplete and may not be safe to use and/or cause compiler crashes + --> $DIR/specialization-fuzzing-ice-133639.rs:7:12 + | +LL | #![feature(generic_const_exprs)] + | ^^^^^^^^^^^^^^^^^^^ + | + = note: see issue #76560 for more information + = note: `#[warn(incomplete_features)]` on by default + +warning: 1 warning emitted + diff --git a/tests/ui/const-generics/min_const_generics/param-env-eager-norm-dedup.rs b/tests/ui/const-generics/min_const_generics/param-env-eager-norm-dedup.rs index 9600b3875ba4..2e97e3fe0044 100644 --- a/tests/ui/const-generics/min_const_generics/param-env-eager-norm-dedup.rs +++ b/tests/ui/const-generics/min_const_generics/param-env-eager-norm-dedup.rs @@ -1,3 +1,6 @@ +//@ revisions: current next +//@ ignore-compare-mode-next-solver (explicit revisions) +//@[next] compile-flags: -Znext-solver //@ check-pass // This caused a regression in a crater run in #132325. diff --git a/tests/ui/traits/winnowing/global-non-global-env-1.rs b/tests/ui/traits/winnowing/global-non-global-env-1.rs index d232d32dddff..75c184b65bf0 100644 --- a/tests/ui/traits/winnowing/global-non-global-env-1.rs +++ b/tests/ui/traits/winnowing/global-non-global-env-1.rs @@ -1,3 +1,6 @@ +//@ revisions: current next +//@ ignore-compare-mode-next-solver (explicit revisions) +//@[next] compile-flags: -Znext-solver //@ check-pass // A regression test for an edge case of candidate selection diff --git a/tests/ui/traits/winnowing/global-non-global-env-2.rs b/tests/ui/traits/winnowing/global-non-global-env-2.rs index c73d0f06cd95..128ec2a40dab 100644 --- a/tests/ui/traits/winnowing/global-non-global-env-2.rs +++ b/tests/ui/traits/winnowing/global-non-global-env-2.rs @@ -1,3 +1,6 @@ +//@ revisions: current next +//@ ignore-compare-mode-next-solver (explicit revisions) +//@[next] compile-flags: -Znext-solver //@ check-pass // A regression test for an edge case of candidate selection diff --git a/tests/ui/traits/winnowing/global-non-global-env-3.rs b/tests/ui/traits/winnowing/global-non-global-env-3.rs index 008d07e41446..7e5dbd4ba8ec 100644 --- a/tests/ui/traits/winnowing/global-non-global-env-3.rs +++ b/tests/ui/traits/winnowing/global-non-global-env-3.rs @@ -1,3 +1,6 @@ +//@ revisions: current next +//@ ignore-compare-mode-next-solver (explicit revisions) +//@[next] compile-flags: -Znext-solver //@ check-pass // A regression test for an edge case of candidate selection diff --git a/tests/ui/traits/winnowing/global-non-global-env-4.rs b/tests/ui/traits/winnowing/global-non-global-env-4.rs index 74793620c9e7..2dc082be45c5 100644 --- a/tests/ui/traits/winnowing/global-non-global-env-4.rs +++ b/tests/ui/traits/winnowing/global-non-global-env-4.rs @@ -1,3 +1,6 @@ +//@ revisions: current next +//@ ignore-compare-mode-next-solver (explicit revisions) +//@[next] compile-flags: -Znext-solver //@ check-pass // A regression test for an edge case of candidate selection From 5fa4b093f59e4be0847ee00628ae5439fad51cfc Mon Sep 17 00:00:00 2001 From: lcnr Date: Wed, 18 Dec 2024 16:31:44 +0100 Subject: [PATCH 64/92] resolve FIXME --- .../next-solver/generalize/occurs-check-nested-alias.rs | 5 ----- 1 file changed, 5 deletions(-) diff --git a/tests/ui/traits/next-solver/generalize/occurs-check-nested-alias.rs b/tests/ui/traits/next-solver/generalize/occurs-check-nested-alias.rs index 00dc7a9d337d..fbf4cadc678d 100644 --- a/tests/ui/traits/next-solver/generalize/occurs-check-nested-alias.rs +++ b/tests/ui/traits/next-solver/generalize/occurs-check-nested-alias.rs @@ -37,9 +37,4 @@ fn foo() { // result in a cyclic type. However, we can still unify these types by first // normalizing the inner associated type. Emitting an error here would be incomplete. drop::(t); - - // FIXME(-Znext-solver): This line is necessary due to an unrelated solver bug - // and should get removed in the future. - // https://github.com/rust-lang/trait-system-refactor-initiative/issues/96 - drop::::Assoc>>(u); } From 661b8f5694ff1d188172ecb893b71cd5da2f6072 Mon Sep 17 00:00:00 2001 From: Oli Scherer Date: Thu, 12 Dec 2024 20:17:32 +0000 Subject: [PATCH 65/92] Forbid overwriting types in typeck --- .../rustc_hir_typeck/src/fn_ctxt/_impl.rs | 20 +++++++++++++------ .../rustc_hir_typeck/src/fn_ctxt/checks.rs | 7 ++++--- .../ui/pattern/slice-pattern-refutable.stderr | 12 ++++++----- .../pattern/slice-patterns-ambiguity.stderr | 14 +++++++------ 4 files changed, 33 insertions(+), 20 deletions(-) diff --git a/compiler/rustc_hir_typeck/src/fn_ctxt/_impl.rs b/compiler/rustc_hir_typeck/src/fn_ctxt/_impl.rs index 2a4914348a96..364499378b0e 100644 --- a/compiler/rustc_hir_typeck/src/fn_ctxt/_impl.rs +++ b/compiler/rustc_hir_typeck/src/fn_ctxt/_impl.rs @@ -146,13 +146,21 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { debug!("write_ty({:?}, {:?}) in fcx {}", id, self.resolve_vars_if_possible(ty), self.tag()); let mut typeck = self.typeck_results.borrow_mut(); let mut node_ty = typeck.node_types_mut(); - if let Some(ty) = node_ty.get(id) - && ty.references_error() - { - return; - } - node_ty.insert(id, ty); + if let Some(prev) = node_ty.insert(id, ty) { + if prev.references_error() { + node_ty.insert(id, prev); + } else if !ty.references_error() { + // Could change this to a bug, but there's lots of diagnostic code re-lowering + // or re-typechecking nodes that were already typecked. + // Lots of that diagnostics code relies on subtle effects of re-lowering, so we'll + // let it keep doing that and just ensure that compilation won't succeed. + self.dcx().span_delayed_bug( + self.tcx.hir().span(id), + format!("`{prev}` overridden by `{ty}` for {id:?} in {:?}", self.body_id), + ); + } + } if let Err(e) = ty.error_reported() { self.set_tainted_by_errors(e); diff --git a/compiler/rustc_hir_typeck/src/fn_ctxt/checks.rs b/compiler/rustc_hir_typeck/src/fn_ctxt/checks.rs index c1f08d237eb3..fffea8f640b8 100644 --- a/compiler/rustc_hir_typeck/src/fn_ctxt/checks.rs +++ b/compiler/rustc_hir_typeck/src/fn_ctxt/checks.rs @@ -1750,10 +1750,9 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { } } - pub(in super::super) fn check_decl(&self, decl: Declaration<'tcx>) { + pub(in super::super) fn check_decl(&self, decl: Declaration<'tcx>) -> Ty<'tcx> { // Determine and write the type which we'll check the pattern against. let decl_ty = self.local_ty(decl.span, decl.hir_id); - self.write_ty(decl.hir_id, decl_ty); // Type check the initializer. if let Some(ref init) = decl.init { @@ -1785,11 +1784,13 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { } self.diverges.set(previous_diverges); } + decl_ty } /// Type check a `let` statement. fn check_decl_local(&self, local: &'tcx hir::LetStmt<'tcx>) { - self.check_decl(local.into()); + let ty = self.check_decl(local.into()); + self.write_ty(local.hir_id, ty); if local.pat.is_never_pattern() { self.diverges.set(Diverges::Always { span: local.pat.span, diff --git a/tests/ui/pattern/slice-pattern-refutable.stderr b/tests/ui/pattern/slice-pattern-refutable.stderr index df5b58d3e9c6..3d9f769d1341 100644 --- a/tests/ui/pattern/slice-pattern-refutable.stderr +++ b/tests/ui/pattern/slice-pattern-refutable.stderr @@ -1,13 +1,15 @@ error[E0282]: type annotations needed - --> $DIR/slice-pattern-refutable.rs:14:9 + --> $DIR/slice-pattern-refutable.rs:14:28 | LL | let [a, b, c] = Zeroes.into() else { - | ^^^^^^^^^ + | --------- ^^^^ + | | + | type must be known at this point | -help: consider giving this pattern a type +help: try using a fully qualified path to specify the expected types | -LL | let [a, b, c]: /* Type */ = Zeroes.into() else { - | ++++++++++++ +LL | let [a, b, c] = >::into(Zeroes) else { + | ++++++++++++++++++++++++++ ~ error[E0282]: type annotations needed --> $DIR/slice-pattern-refutable.rs:21:31 diff --git a/tests/ui/pattern/slice-patterns-ambiguity.stderr b/tests/ui/pattern/slice-patterns-ambiguity.stderr index 3ef99d0e2d1b..690776196ce1 100644 --- a/tests/ui/pattern/slice-patterns-ambiguity.stderr +++ b/tests/ui/pattern/slice-patterns-ambiguity.stderr @@ -1,13 +1,15 @@ -error[E0282]: type annotations needed for `&_` - --> $DIR/slice-patterns-ambiguity.rs:25:9 +error[E0282]: type annotations needed + --> $DIR/slice-patterns-ambiguity.rs:25:26 | LL | let &[a, b] = Zeroes.into() else { - | ^^^^^^^ + | ------ ^^^^ + | | + | type must be known at this point | -help: consider giving this pattern a type, where the placeholders `_` are specified +help: try using a fully qualified path to specify the expected types | -LL | let &[a, b]: &_ = Zeroes.into() else { - | ++++ +LL | let &[a, b] = >::into(Zeroes) else { + | +++++++++++++++++++++++++++ ~ error[E0282]: type annotations needed --> $DIR/slice-patterns-ambiguity.rs:32:29 From b0d923c33be9927c66e06b196db4ed98d05e539b Mon Sep 17 00:00:00 2001 From: lcnr Date: Wed, 18 Dec 2024 18:27:26 +0100 Subject: [PATCH 66/92] move lint_unused_mut into subfn --- compiler/rustc_borrowck/src/lib.rs | 62 ++++++++++++++++-------------- 1 file changed, 33 insertions(+), 29 deletions(-) diff --git a/compiler/rustc_borrowck/src/lib.rs b/compiler/rustc_borrowck/src/lib.rs index 63e20b16f7a0..19b5c8689c84 100644 --- a/compiler/rustc_borrowck/src/lib.rs +++ b/compiler/rustc_borrowck/src/lib.rs @@ -334,35 +334,7 @@ fn do_mir_borrowck<'tcx>( mbcx.gather_used_muts(temporary_used_locals, unused_mut_locals); debug!("mbcx.used_mut: {:?}", mbcx.used_mut); - let used_mut = std::mem::take(&mut mbcx.used_mut); - for local in mbcx.body.mut_vars_and_args_iter().filter(|local| !used_mut.contains(local)) { - let local_decl = &mbcx.body.local_decls[local]; - let lint_root = match &mbcx.body.source_scopes[local_decl.source_info.scope].local_data { - ClearCrossCrate::Set(data) => data.lint_root, - _ => continue, - }; - - // Skip over locals that begin with an underscore or have no name - match mbcx.local_names[local] { - Some(name) => { - if name.as_str().starts_with('_') { - continue; - } - } - None => continue, - } - - let span = local_decl.source_info.span; - if span.desugaring_kind().is_some() { - // If the `mut` arises as part of a desugaring, we should ignore it. - continue; - } - - let mut_span = tcx.sess.source_map().span_until_non_whitespace(span); - - tcx.emit_node_span_lint(UNUSED_MUT, lint_root, span, VarNeedNotMut { span: mut_span }) - } - + mbcx.lint_unused_mut(); let tainted_by_errors = mbcx.emit_errors(); let result = BorrowCheckResult { @@ -2390,6 +2362,38 @@ impl<'a, 'tcx> MirBorrowckCtxt<'a, '_, 'tcx> { // `BasicBlocks` computes dominators on-demand and caches them. self.body.basic_blocks.dominators() } + + fn lint_unused_mut(&self) { + let tcx = self.infcx.tcx; + let body = self.body; + for local in body.mut_vars_and_args_iter().filter(|local| !self.used_mut.contains(local)) { + let local_decl = &body.local_decls[local]; + let lint_root = match &body.source_scopes[local_decl.source_info.scope].local_data { + ClearCrossCrate::Set(data) => data.lint_root, + _ => continue, + }; + + // Skip over locals that begin with an underscore or have no name + match self.local_names[local] { + Some(name) => { + if name.as_str().starts_with('_') { + continue; + } + } + None => continue, + } + + let span = local_decl.source_info.span; + if span.desugaring_kind().is_some() { + // If the `mut` arises as part of a desugaring, we should ignore it. + continue; + } + + let mut_span = tcx.sess.source_map().span_until_non_whitespace(span); + + tcx.emit_node_span_lint(UNUSED_MUT, lint_root, span, VarNeedNotMut { span: mut_span }) + } + } } mod diags { From 19e44f4db48e21832d17378a32739a70db29cf30 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Esteban=20K=C3=BCber?= Date: Wed, 18 Dec 2024 19:27:44 +0000 Subject: [PATCH 67/92] Point at lint name instead of whole attr for gated lints ``` warning: unknown lint: `test_unstable_lint` --> $DIR/warn-unknown-unstable-lint-inline.rs:4:10 | LL | #![allow(test_unstable_lint, another_unstable_lint)] | ^^^^^^^^^^^^^^^^^^ | = note: the `test_unstable_lint` lint is unstable = help: add `#![feature(test_unstable_lint)]` to the crate attributes to enable = note: this compiler was built on YYYY-MM-DD; consider upgrading it if it is out of date note: the lint level is defined here --> $DIR/warn-unknown-unstable-lint-inline.rs:3:9 | LL | #![warn(unknown_lints)] | ^^^^^^^^^^^^^ warning: unknown lint: `test_unstable_lint` --> $DIR/warn-unknown-unstable-lint-inline.rs:4:29 | LL | #![allow(test_unstable_lint, another_unstable_lint)] | ^^^^^^^^^^^^^^^^^^^^^ | = note: the `test_unstable_lint` lint is unstable = help: add `#![feature(test_unstable_lint)]` to the crate attributes to enable = note: this compiler was built on YYYY-MM-DD; consider upgrading it if it is out of date note: the lint level is defined here --> $DIR/warn-unknown-unstable-lint-inline.rs:3:9 | LL | #![warn(unknown_lints)] | ^^^^^^^^^^^^^ ``` This is particularly relevant when there are multiple lints in the same `warn` attribute. Pointing at the smaller span makes it clearer which one the warning is complaining about. --- compiler/rustc_lint/src/levels.rs | 2 +- ...e-rustdoc_missing_doc_code_examples.stderr | 4 ++-- ...gate-multiple_supertrait_upcastable.stderr | 8 +++---- ...on_exhaustive_omitted_patterns_lint.stderr | 24 +++++++++---------- ...eature-gate-strict_provenance_lints.stderr | 8 +++---- .../feature-gate-test_unstable_lint.stderr | 4 ++-- ...ture-gate-unqualified-local-imports.stderr | 4 ++-- tests/ui/lint/must_not_suspend/gated.stderr | 4 ++-- .../deny-unstable-lint-inline.stderr | 4 ++-- .../warn-unknown-unstable-lint-inline.stderr | 4 ++-- 10 files changed, 33 insertions(+), 33 deletions(-) diff --git a/compiler/rustc_lint/src/levels.rs b/compiler/rustc_lint/src/levels.rs index 7ea6c63dbe68..7f4aa60fa0b3 100644 --- a/compiler/rustc_lint/src/levels.rs +++ b/compiler/rustc_lint/src/levels.rs @@ -915,7 +915,7 @@ impl<'s, P: LintLevelsProvider> LintLevelsBuilder<'s, P> { let src = LintLevelSource::Node { name, span: sp, reason }; for &id in ids { - if self.check_gated_lint(id, attr.span(), false) { + if self.check_gated_lint(id, sp, false) { self.insert_spec(id, (level, src)); } } diff --git a/tests/rustdoc-ui/lints/feature-gate-rustdoc_missing_doc_code_examples.stderr b/tests/rustdoc-ui/lints/feature-gate-rustdoc_missing_doc_code_examples.stderr index 67540949f4d7..e017b1f34a17 100644 --- a/tests/rustdoc-ui/lints/feature-gate-rustdoc_missing_doc_code_examples.stderr +++ b/tests/rustdoc-ui/lints/feature-gate-rustdoc_missing_doc_code_examples.stderr @@ -1,8 +1,8 @@ error: unknown lint: `rustdoc::missing_doc_code_examples` - --> $DIR/feature-gate-rustdoc_missing_doc_code_examples.rs:4:1 + --> $DIR/feature-gate-rustdoc_missing_doc_code_examples.rs:4:10 | LL | #![allow(rustdoc::missing_doc_code_examples)] - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ | = note: the `rustdoc::missing_doc_code_examples` lint is unstable = note: see issue #101730 for more information diff --git a/tests/ui/feature-gates/feature-gate-multiple_supertrait_upcastable.stderr b/tests/ui/feature-gates/feature-gate-multiple_supertrait_upcastable.stderr index 8a43d6159633..0c7e68a599cd 100644 --- a/tests/ui/feature-gates/feature-gate-multiple_supertrait_upcastable.stderr +++ b/tests/ui/feature-gates/feature-gate-multiple_supertrait_upcastable.stderr @@ -1,8 +1,8 @@ warning: unknown lint: `multiple_supertrait_upcastable` - --> $DIR/feature-gate-multiple_supertrait_upcastable.rs:3:1 + --> $DIR/feature-gate-multiple_supertrait_upcastable.rs:3:9 | LL | #![deny(multiple_supertrait_upcastable)] - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ | = note: the `multiple_supertrait_upcastable` lint is unstable = help: add `#![feature(multiple_supertrait_upcastable)]` to the crate attributes to enable @@ -10,10 +10,10 @@ LL | #![deny(multiple_supertrait_upcastable)] = note: `#[warn(unknown_lints)]` on by default warning: unknown lint: `multiple_supertrait_upcastable` - --> $DIR/feature-gate-multiple_supertrait_upcastable.rs:5:1 + --> $DIR/feature-gate-multiple_supertrait_upcastable.rs:5:9 | LL | #![warn(multiple_supertrait_upcastable)] - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ | = note: the `multiple_supertrait_upcastable` lint is unstable = help: add `#![feature(multiple_supertrait_upcastable)]` to the crate attributes to enable diff --git a/tests/ui/feature-gates/feature-gate-non_exhaustive_omitted_patterns_lint.stderr b/tests/ui/feature-gates/feature-gate-non_exhaustive_omitted_patterns_lint.stderr index 41764c8e018d..7a453521590d 100644 --- a/tests/ui/feature-gates/feature-gate-non_exhaustive_omitted_patterns_lint.stderr +++ b/tests/ui/feature-gates/feature-gate-non_exhaustive_omitted_patterns_lint.stderr @@ -1,8 +1,8 @@ warning: unknown lint: `non_exhaustive_omitted_patterns` - --> $DIR/feature-gate-non_exhaustive_omitted_patterns_lint.rs:3:1 + --> $DIR/feature-gate-non_exhaustive_omitted_patterns_lint.rs:3:9 | LL | #![deny(non_exhaustive_omitted_patterns)] - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ | = note: the `non_exhaustive_omitted_patterns` lint is unstable = note: see issue #89554 for more information @@ -11,10 +11,10 @@ LL | #![deny(non_exhaustive_omitted_patterns)] = note: `#[warn(unknown_lints)]` on by default warning: unknown lint: `non_exhaustive_omitted_patterns` - --> $DIR/feature-gate-non_exhaustive_omitted_patterns_lint.rs:5:1 + --> $DIR/feature-gate-non_exhaustive_omitted_patterns_lint.rs:5:10 | LL | #![allow(non_exhaustive_omitted_patterns)] - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ | = note: the `non_exhaustive_omitted_patterns` lint is unstable = note: see issue #89554 for more information @@ -22,10 +22,10 @@ LL | #![allow(non_exhaustive_omitted_patterns)] = note: this compiler was built on YYYY-MM-DD; consider upgrading it if it is out of date warning: unknown lint: `non_exhaustive_omitted_patterns` - --> $DIR/feature-gate-non_exhaustive_omitted_patterns_lint.rs:15:5 + --> $DIR/feature-gate-non_exhaustive_omitted_patterns_lint.rs:15:13 | LL | #[allow(non_exhaustive_omitted_patterns)] - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ | = note: the `non_exhaustive_omitted_patterns` lint is unstable = note: see issue #89554 for more information @@ -33,10 +33,10 @@ LL | #[allow(non_exhaustive_omitted_patterns)] = note: this compiler was built on YYYY-MM-DD; consider upgrading it if it is out of date warning: unknown lint: `non_exhaustive_omitted_patterns` - --> $DIR/feature-gate-non_exhaustive_omitted_patterns_lint.rs:15:5 + --> $DIR/feature-gate-non_exhaustive_omitted_patterns_lint.rs:15:13 | LL | #[allow(non_exhaustive_omitted_patterns)] - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ | = note: the `non_exhaustive_omitted_patterns` lint is unstable = note: see issue #89554 for more information @@ -45,10 +45,10 @@ LL | #[allow(non_exhaustive_omitted_patterns)] = note: duplicate diagnostic emitted due to `-Z deduplicate-diagnostics=no` warning: unknown lint: `non_exhaustive_omitted_patterns` - --> $DIR/feature-gate-non_exhaustive_omitted_patterns_lint.rs:24:5 + --> $DIR/feature-gate-non_exhaustive_omitted_patterns_lint.rs:24:12 | LL | #[warn(non_exhaustive_omitted_patterns)] - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ | = note: the `non_exhaustive_omitted_patterns` lint is unstable = note: see issue #89554 for more information @@ -56,10 +56,10 @@ LL | #[warn(non_exhaustive_omitted_patterns)] = note: this compiler was built on YYYY-MM-DD; consider upgrading it if it is out of date warning: unknown lint: `non_exhaustive_omitted_patterns` - --> $DIR/feature-gate-non_exhaustive_omitted_patterns_lint.rs:24:5 + --> $DIR/feature-gate-non_exhaustive_omitted_patterns_lint.rs:24:12 | LL | #[warn(non_exhaustive_omitted_patterns)] - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ | = note: the `non_exhaustive_omitted_patterns` lint is unstable = note: see issue #89554 for more information diff --git a/tests/ui/feature-gates/feature-gate-strict_provenance_lints.stderr b/tests/ui/feature-gates/feature-gate-strict_provenance_lints.stderr index 15428cbd4be4..3f3b49bc6067 100644 --- a/tests/ui/feature-gates/feature-gate-strict_provenance_lints.stderr +++ b/tests/ui/feature-gates/feature-gate-strict_provenance_lints.stderr @@ -1,8 +1,8 @@ warning: unknown lint: `fuzzy_provenance_casts` - --> $DIR/feature-gate-strict_provenance_lints.rs:3:1 + --> $DIR/feature-gate-strict_provenance_lints.rs:3:9 | LL | #![deny(fuzzy_provenance_casts)] - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | ^^^^^^^^^^^^^^^^^^^^^^ | = note: the `fuzzy_provenance_casts` lint is unstable = note: see issue #130351 for more information @@ -11,10 +11,10 @@ LL | #![deny(fuzzy_provenance_casts)] = note: `#[warn(unknown_lints)]` on by default warning: unknown lint: `lossy_provenance_casts` - --> $DIR/feature-gate-strict_provenance_lints.rs:5:1 + --> $DIR/feature-gate-strict_provenance_lints.rs:5:9 | LL | #![deny(lossy_provenance_casts)] - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | ^^^^^^^^^^^^^^^^^^^^^^ | = note: the `lossy_provenance_casts` lint is unstable = note: see issue #130351 for more information diff --git a/tests/ui/feature-gates/feature-gate-test_unstable_lint.stderr b/tests/ui/feature-gates/feature-gate-test_unstable_lint.stderr index 5dc303da7420..e460688e5fc4 100644 --- a/tests/ui/feature-gates/feature-gate-test_unstable_lint.stderr +++ b/tests/ui/feature-gates/feature-gate-test_unstable_lint.stderr @@ -1,8 +1,8 @@ warning: unknown lint: `test_unstable_lint` - --> $DIR/feature-gate-test_unstable_lint.rs:4:1 + --> $DIR/feature-gate-test_unstable_lint.rs:4:10 | LL | #![allow(test_unstable_lint)] - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | ^^^^^^^^^^^^^^^^^^ | = note: the `test_unstable_lint` lint is unstable = help: add `#![feature(test_unstable_lint)]` to the crate attributes to enable diff --git a/tests/ui/feature-gates/feature-gate-unqualified-local-imports.stderr b/tests/ui/feature-gates/feature-gate-unqualified-local-imports.stderr index 22cd3bf4c6fa..bc8edd847cc0 100644 --- a/tests/ui/feature-gates/feature-gate-unqualified-local-imports.stderr +++ b/tests/ui/feature-gates/feature-gate-unqualified-local-imports.stderr @@ -1,8 +1,8 @@ warning: unknown lint: `unqualified_local_imports` - --> $DIR/feature-gate-unqualified-local-imports.rs:3:1 + --> $DIR/feature-gate-unqualified-local-imports.rs:3:10 | LL | #![allow(unqualified_local_imports)] - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | ^^^^^^^^^^^^^^^^^^^^^^^^^ | = note: the `unqualified_local_imports` lint is unstable = help: add `#![feature(unqualified_local_imports)]` to the crate attributes to enable diff --git a/tests/ui/lint/must_not_suspend/gated.stderr b/tests/ui/lint/must_not_suspend/gated.stderr index aff1b6a2ac45..8ec3202c5af9 100644 --- a/tests/ui/lint/must_not_suspend/gated.stderr +++ b/tests/ui/lint/must_not_suspend/gated.stderr @@ -1,8 +1,8 @@ warning: unknown lint: `must_not_suspend` - --> $DIR/gated.rs:4:1 + --> $DIR/gated.rs:4:9 | LL | #![deny(must_not_suspend)] - | ^^^^^^^^^^^^^^^^^^^^^^^^^^ + | ^^^^^^^^^^^^^^^^ | = note: the `must_not_suspend` lint is unstable = note: see issue #83310 for more information diff --git a/tests/ui/unknown-unstable-lints/deny-unstable-lint-inline.stderr b/tests/ui/unknown-unstable-lints/deny-unstable-lint-inline.stderr index e486f04f2735..4ff909453979 100644 --- a/tests/ui/unknown-unstable-lints/deny-unstable-lint-inline.stderr +++ b/tests/ui/unknown-unstable-lints/deny-unstable-lint-inline.stderr @@ -1,8 +1,8 @@ error: unknown lint: `test_unstable_lint` - --> $DIR/deny-unstable-lint-inline.rs:4:1 + --> $DIR/deny-unstable-lint-inline.rs:4:10 | LL | #![allow(test_unstable_lint)] - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | ^^^^^^^^^^^^^^^^^^ | = note: the `test_unstable_lint` lint is unstable = help: add `#![feature(test_unstable_lint)]` to the crate attributes to enable diff --git a/tests/ui/unknown-unstable-lints/warn-unknown-unstable-lint-inline.stderr b/tests/ui/unknown-unstable-lints/warn-unknown-unstable-lint-inline.stderr index 981d3b1a874c..7d56b3608372 100644 --- a/tests/ui/unknown-unstable-lints/warn-unknown-unstable-lint-inline.stderr +++ b/tests/ui/unknown-unstable-lints/warn-unknown-unstable-lint-inline.stderr @@ -1,8 +1,8 @@ warning: unknown lint: `test_unstable_lint` - --> $DIR/warn-unknown-unstable-lint-inline.rs:4:1 + --> $DIR/warn-unknown-unstable-lint-inline.rs:4:10 | LL | #![allow(test_unstable_lint)] - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | ^^^^^^^^^^^^^^^^^^ | = note: the `test_unstable_lint` lint is unstable = help: add `#![feature(test_unstable_lint)]` to the crate attributes to enable From 007586966cfae4e076d6335bc2aaf7eedd56aa20 Mon Sep 17 00:00:00 2001 From: Nicholas Nethercote Date: Thu, 19 Dec 2024 07:41:00 +1100 Subject: [PATCH 68/92] Add nnethercote to the `triagebot.toml` vacation list. --- triagebot.toml | 1 + 1 file changed, 1 insertion(+) diff --git a/triagebot.toml b/triagebot.toml index 214fc2a21c48..eefb87aa298f 100644 --- a/triagebot.toml +++ b/triagebot.toml @@ -996,6 +996,7 @@ contributing_url = "https://rustc-dev-guide.rust-lang.org/getting-started.html" users_on_vacation = [ "jyn514", "celinval", + "nnethercote", ] [[assign.warn_non_default_branch.exceptions]] From 2e57394d8004b155c6f74ca4e2a1106dedfcccc4 Mon Sep 17 00:00:00 2001 From: Michael Goulet Date: Wed, 18 Dec 2024 21:54:50 +0000 Subject: [PATCH 69/92] Add a failing test --- ...hod_1.ElaborateDrops.after.panic-abort.mir | 183 ++++++++++++++++++ ...od_1.ElaborateDrops.after.panic-unwind.mir | 183 ++++++++++++++++++ tests/mir-opt/tail_expr_drop_order_unwind.rs | 36 ++++ 3 files changed, 402 insertions(+) create mode 100644 tests/mir-opt/tail_expr_drop_order_unwind.method_1.ElaborateDrops.after.panic-abort.mir create mode 100644 tests/mir-opt/tail_expr_drop_order_unwind.method_1.ElaborateDrops.after.panic-unwind.mir create mode 100644 tests/mir-opt/tail_expr_drop_order_unwind.rs diff --git a/tests/mir-opt/tail_expr_drop_order_unwind.method_1.ElaborateDrops.after.panic-abort.mir b/tests/mir-opt/tail_expr_drop_order_unwind.method_1.ElaborateDrops.after.panic-abort.mir new file mode 100644 index 000000000000..54bedfdc0af1 --- /dev/null +++ b/tests/mir-opt/tail_expr_drop_order_unwind.method_1.ElaborateDrops.after.panic-abort.mir @@ -0,0 +1,183 @@ +// MIR for `method_1` after ElaborateDrops + +fn method_1(_1: Guard) -> () { + debug g => _1; + let mut _0: (); + let mut _2: std::result::Result; + let mut _3: &Guard; + let _4: &Guard; + let _5: Guard; + let mut _6: &Guard; + let mut _7: isize; + let _8: OtherDrop; + let _9: (); + let mut _10: bool; + let mut _11: bool; + let mut _12: isize; + let mut _13: isize; + let mut _14: isize; + scope 1 { + debug other_drop => _8; + } + scope 2 { + debug err => _9; + } + + bb0: { + _11 = const false; + _10 = const false; + StorageLive(_2); + StorageLive(_3); + StorageLive(_4); + StorageLive(_5); + StorageLive(_6); + _6 = &_1; + _5 = ::clone(move _6) -> [return: bb1, unwind: bb16]; + } + + bb1: { + _11 = const true; + StorageDead(_6); + _4 = &_5; + _3 = &(*_4); + _2 = method_2(move _3) -> [return: bb2, unwind: bb14]; + } + + bb2: { + _10 = const true; + StorageDead(_3); + PlaceMention(_2); + _7 = discriminant(_2); + switchInt(move _7) -> [0: bb5, 1: bb4, otherwise: bb3]; + } + + bb3: { + unreachable; + } + + bb4: { + StorageLive(_9); + _9 = copy ((_2 as Err).0: ()); + _0 = const (); + StorageDead(_9); + goto -> bb7; + } + + bb5: { + StorageLive(_8); + _8 = move ((_2 as Ok).0: OtherDrop); + _0 = const (); + drop(_8) -> [return: bb6, unwind: bb11]; + } + + bb6: { + StorageDead(_8); + goto -> bb7; + } + + bb7: { + backward incompatible drop(_2); + backward incompatible drop(_5); + goto -> bb24; + } + + bb8: { + drop(_5) -> [return: bb9, unwind: bb16]; + } + + bb9: { + _11 = const false; + StorageDead(_5); + StorageDead(_4); + _10 = const false; + StorageDead(_2); + drop(_1) -> [return: bb10, unwind: bb17]; + } + + bb10: { + return; + } + + bb11 (cleanup): { + goto -> bb28; + } + + bb12 (cleanup): { + drop(_5) -> [return: bb13, unwind terminate(cleanup)]; + } + + bb13 (cleanup): { + goto -> bb15; + } + + bb14 (cleanup): { + drop(_5) -> [return: bb15, unwind terminate(cleanup)]; + } + + bb15 (cleanup): { + goto -> bb30; + } + + bb16 (cleanup): { + drop(_1) -> [return: bb17, unwind terminate(cleanup)]; + } + + bb17 (cleanup): { + resume; + } + + bb18: { + goto -> bb8; + } + + bb19 (cleanup): { + goto -> bb15; + } + + bb20 (cleanup): { + goto -> bb15; + } + + bb21: { + goto -> bb18; + } + + bb22: { + goto -> bb18; + } + + bb23 (cleanup): { + goto -> bb15; + } + + bb24: { + _12 = discriminant(_2); + switchInt(move _12) -> [0: bb21, otherwise: bb22]; + } + + bb25 (cleanup): { + _13 = discriminant(_2); + switchInt(move _13) -> [0: bb19, otherwise: bb23]; + } + + bb26 (cleanup): { + goto -> bb12; + } + + bb27 (cleanup): { + goto -> bb12; + } + + bb28 (cleanup): { + _14 = discriminant(_2); + switchInt(move _14) -> [0: bb26, otherwise: bb27]; + } + + bb29 (cleanup): { + drop(_5) -> [return: bb16, unwind terminate(cleanup)]; + } + + bb30 (cleanup): { + switchInt(copy _11) -> [0: bb16, otherwise: bb29]; + } +} diff --git a/tests/mir-opt/tail_expr_drop_order_unwind.method_1.ElaborateDrops.after.panic-unwind.mir b/tests/mir-opt/tail_expr_drop_order_unwind.method_1.ElaborateDrops.after.panic-unwind.mir new file mode 100644 index 000000000000..54bedfdc0af1 --- /dev/null +++ b/tests/mir-opt/tail_expr_drop_order_unwind.method_1.ElaborateDrops.after.panic-unwind.mir @@ -0,0 +1,183 @@ +// MIR for `method_1` after ElaborateDrops + +fn method_1(_1: Guard) -> () { + debug g => _1; + let mut _0: (); + let mut _2: std::result::Result; + let mut _3: &Guard; + let _4: &Guard; + let _5: Guard; + let mut _6: &Guard; + let mut _7: isize; + let _8: OtherDrop; + let _9: (); + let mut _10: bool; + let mut _11: bool; + let mut _12: isize; + let mut _13: isize; + let mut _14: isize; + scope 1 { + debug other_drop => _8; + } + scope 2 { + debug err => _9; + } + + bb0: { + _11 = const false; + _10 = const false; + StorageLive(_2); + StorageLive(_3); + StorageLive(_4); + StorageLive(_5); + StorageLive(_6); + _6 = &_1; + _5 = ::clone(move _6) -> [return: bb1, unwind: bb16]; + } + + bb1: { + _11 = const true; + StorageDead(_6); + _4 = &_5; + _3 = &(*_4); + _2 = method_2(move _3) -> [return: bb2, unwind: bb14]; + } + + bb2: { + _10 = const true; + StorageDead(_3); + PlaceMention(_2); + _7 = discriminant(_2); + switchInt(move _7) -> [0: bb5, 1: bb4, otherwise: bb3]; + } + + bb3: { + unreachable; + } + + bb4: { + StorageLive(_9); + _9 = copy ((_2 as Err).0: ()); + _0 = const (); + StorageDead(_9); + goto -> bb7; + } + + bb5: { + StorageLive(_8); + _8 = move ((_2 as Ok).0: OtherDrop); + _0 = const (); + drop(_8) -> [return: bb6, unwind: bb11]; + } + + bb6: { + StorageDead(_8); + goto -> bb7; + } + + bb7: { + backward incompatible drop(_2); + backward incompatible drop(_5); + goto -> bb24; + } + + bb8: { + drop(_5) -> [return: bb9, unwind: bb16]; + } + + bb9: { + _11 = const false; + StorageDead(_5); + StorageDead(_4); + _10 = const false; + StorageDead(_2); + drop(_1) -> [return: bb10, unwind: bb17]; + } + + bb10: { + return; + } + + bb11 (cleanup): { + goto -> bb28; + } + + bb12 (cleanup): { + drop(_5) -> [return: bb13, unwind terminate(cleanup)]; + } + + bb13 (cleanup): { + goto -> bb15; + } + + bb14 (cleanup): { + drop(_5) -> [return: bb15, unwind terminate(cleanup)]; + } + + bb15 (cleanup): { + goto -> bb30; + } + + bb16 (cleanup): { + drop(_1) -> [return: bb17, unwind terminate(cleanup)]; + } + + bb17 (cleanup): { + resume; + } + + bb18: { + goto -> bb8; + } + + bb19 (cleanup): { + goto -> bb15; + } + + bb20 (cleanup): { + goto -> bb15; + } + + bb21: { + goto -> bb18; + } + + bb22: { + goto -> bb18; + } + + bb23 (cleanup): { + goto -> bb15; + } + + bb24: { + _12 = discriminant(_2); + switchInt(move _12) -> [0: bb21, otherwise: bb22]; + } + + bb25 (cleanup): { + _13 = discriminant(_2); + switchInt(move _13) -> [0: bb19, otherwise: bb23]; + } + + bb26 (cleanup): { + goto -> bb12; + } + + bb27 (cleanup): { + goto -> bb12; + } + + bb28 (cleanup): { + _14 = discriminant(_2); + switchInt(move _14) -> [0: bb26, otherwise: bb27]; + } + + bb29 (cleanup): { + drop(_5) -> [return: bb16, unwind terminate(cleanup)]; + } + + bb30 (cleanup): { + switchInt(copy _11) -> [0: bb16, otherwise: bb29]; + } +} diff --git a/tests/mir-opt/tail_expr_drop_order_unwind.rs b/tests/mir-opt/tail_expr_drop_order_unwind.rs new file mode 100644 index 000000000000..b67b35808750 --- /dev/null +++ b/tests/mir-opt/tail_expr_drop_order_unwind.rs @@ -0,0 +1,36 @@ +// skip-filecheck +// EMIT_MIR_FOR_EACH_PANIC_STRATEGY +// EMIT_MIR tail_expr_drop_order_unwind.method_1.ElaborateDrops.after.mir + +#![deny(tail_expr_drop_order)] + +use std::backtrace::Backtrace; + +#[derive(Clone)] +struct Guard; +impl Drop for Guard { + fn drop(&mut self) { + println!("Drop!"); + } +} + +#[derive(Clone)] +struct OtherDrop; +impl Drop for OtherDrop { + fn drop(&mut self) { + println!("Drop!"); + } +} + +fn method_1(g: Guard) { + match method_2(&g.clone()) { + Ok(other_drop) => { + // repro needs something else being dropped too. + }, + Err(err) => {}, + } +} + +fn method_2(_: &Guard) -> Result { + panic!("Method 2 panics!"); +} From 5e079011eafbb1d5fc779c14c7a29d4a620574f9 Mon Sep 17 00:00:00 2001 From: Michael Goulet Date: Wed, 18 Dec 2024 21:57:20 +0000 Subject: [PATCH 70/92] Separate DropKind::ForLint --- compiler/rustc_mir_build/src/builder/scope.rs | 108 +++++++++++------- ...hod_1.ElaborateDrops.after.panic-abort.mir | 88 ++++++-------- ...od_1.ElaborateDrops.after.panic-unwind.mir | 88 ++++++-------- tests/mir-opt/tail_expr_drop_order_unwind.rs | 4 +- 4 files changed, 135 insertions(+), 153 deletions(-) diff --git a/compiler/rustc_mir_build/src/builder/scope.rs b/compiler/rustc_mir_build/src/builder/scope.rs index 882e29de46d3..19ab7a44e0dc 100644 --- a/compiler/rustc_mir_build/src/builder/scope.rs +++ b/compiler/rustc_mir_build/src/builder/scope.rs @@ -151,15 +151,13 @@ struct DropData { /// Whether this is a value Drop or a StorageDead. kind: DropKind, - - /// Whether this is a backwards-incompatible drop lint - backwards_incompatible_lint: bool, } #[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)] pub(crate) enum DropKind { Value, Storage, + ForLint, } #[derive(Debug)] @@ -248,7 +246,7 @@ impl Scope { /// use of optimizations in the MIR coroutine transform. fn needs_cleanup(&self) -> bool { self.drops.iter().any(|drop| match drop.kind { - DropKind::Value => true, + DropKind::Value | DropKind::ForLint => true, DropKind::Storage => false, }) } @@ -277,12 +275,8 @@ impl DropTree { // represents the block in the tree that should be jumped to once all // of the required drops have been performed. let fake_source_info = SourceInfo::outermost(DUMMY_SP); - let fake_data = DropData { - source_info: fake_source_info, - local: Local::MAX, - kind: DropKind::Storage, - backwards_incompatible_lint: false, - }; + let fake_data = + DropData { source_info: fake_source_info, local: Local::MAX, kind: DropKind::Storage }; let drops = IndexVec::from_raw(vec![DropNode { data: fake_data, next: DropIdx::MAX }]); Self { drops, entry_points: Vec::new(), existing_drops_map: FxHashMap::default() } } @@ -411,6 +405,27 @@ impl DropTree { }; cfg.terminate(block, drop_node.data.source_info, terminator); } + DropKind::ForLint => { + let stmt = Statement { + source_info: drop_node.data.source_info, + kind: StatementKind::BackwardIncompatibleDropHint { + place: Box::new(drop_node.data.local.into()), + reason: BackwardIncompatibleDropReason::Edition2024, + }, + }; + cfg.push(block, stmt); + let target = blocks[drop_node.next].unwrap(); + if target != block { + // Diagnostics don't use this `Span` but debuginfo + // might. Since we don't want breakpoints to be placed + // here, especially when this is on an unwind path, we + // use `DUMMY_SP`. + let source_info = + SourceInfo { span: DUMMY_SP, ..drop_node.data.source_info }; + let terminator = TerminatorKind::Goto { target }; + cfg.terminate(block, source_info, terminator); + } + } // Root nodes don't correspond to a drop. DropKind::Storage if drop_idx == ROOT_NODE => {} DropKind::Storage => { @@ -770,12 +785,7 @@ impl<'a, 'tcx> Builder<'a, 'tcx> { let local = place.as_local().unwrap_or_else(|| bug!("projection in tail call args")); - Some(DropData { - source_info, - local, - kind: DropKind::Value, - backwards_incompatible_lint: false, - }) + Some(DropData { source_info, local, kind: DropKind::Value }) } Operand::Constant(_) => None, }) @@ -822,6 +832,15 @@ impl<'a, 'tcx> Builder<'a, 'tcx> { }); block = next; } + DropKind::ForLint => { + self.cfg.push(block, Statement { + source_info, + kind: StatementKind::BackwardIncompatibleDropHint { + place: Box::new(local.into()), + reason: BackwardIncompatibleDropReason::Edition2024, + }, + }); + } DropKind::Storage => { // Only temps and vars need their storage dead. assert!(local.index() > self.arg_count); @@ -1021,7 +1040,7 @@ impl<'a, 'tcx> Builder<'a, 'tcx> { drop_kind: DropKind, ) { let needs_drop = match drop_kind { - DropKind::Value => { + DropKind::Value | DropKind::ForLint => { if !self.local_decls[local].ty.needs_drop(self.tcx, self.typing_env()) { return; } @@ -1101,7 +1120,6 @@ impl<'a, 'tcx> Builder<'a, 'tcx> { source_info: SourceInfo { span: scope_end, scope: scope.source_scope }, local, kind: drop_kind, - backwards_incompatible_lint: false, }); return; @@ -1135,8 +1153,7 @@ impl<'a, 'tcx> Builder<'a, 'tcx> { scope.drops.push(DropData { source_info: SourceInfo { span: scope_end, scope: scope.source_scope }, local, - kind: DropKind::Value, - backwards_incompatible_lint: true, + kind: DropKind::ForLint, }); return; @@ -1430,25 +1447,38 @@ fn build_scope_drops<'tcx>( continue; } - if drop_data.backwards_incompatible_lint { - cfg.push(block, Statement { - source_info, - kind: StatementKind::BackwardIncompatibleDropHint { - place: Box::new(local.into()), - reason: BackwardIncompatibleDropReason::Edition2024, - }, - }); - } else { - unwind_drops.add_entry_point(block, unwind_to); - let next = cfg.start_new_block(); - cfg.terminate(block, source_info, TerminatorKind::Drop { - place: local.into(), - target: next, - unwind: UnwindAction::Continue, - replace: false, - }); - block = next; + unwind_drops.add_entry_point(block, unwind_to); + let next = cfg.start_new_block(); + cfg.terminate(block, source_info, TerminatorKind::Drop { + place: local.into(), + target: next, + unwind: UnwindAction::Continue, + replace: false, + }); + block = next; + } + DropKind::ForLint => { + // If the operand has been moved, and we are not on an unwind + // path, then don't generate the drop. (We only take this into + // account for non-unwind paths so as not to disturb the + // caching mechanism.) + if scope.moved_locals.iter().any(|&o| o == local) { + continue; } + + if storage_dead_on_unwind { + debug_assert_eq!(unwind_drops.drops[unwind_to].data.local, drop_data.local); + debug_assert_eq!(unwind_drops.drops[unwind_to].data.kind, drop_data.kind); + unwind_to = unwind_drops.drops[unwind_to].next; + } + + cfg.push(block, Statement { + source_info, + kind: StatementKind::BackwardIncompatibleDropHint { + place: Box::new(local.into()), + reason: BackwardIncompatibleDropReason::Edition2024, + }, + }); } DropKind::Storage => { if storage_dead_on_unwind { @@ -1500,7 +1530,7 @@ impl<'a, 'tcx: 'a> Builder<'a, 'tcx> { unwind_indices.push(unwind_indices[drop_node.next]); } } - DropKind::Value => { + DropKind::Value | DropKind::ForLint => { let unwind_drop = self .scopes .unwind_drops diff --git a/tests/mir-opt/tail_expr_drop_order_unwind.method_1.ElaborateDrops.after.panic-abort.mir b/tests/mir-opt/tail_expr_drop_order_unwind.method_1.ElaborateDrops.after.panic-abort.mir index 54bedfdc0af1..e9bbe30bd774 100644 --- a/tests/mir-opt/tail_expr_drop_order_unwind.method_1.ElaborateDrops.after.panic-abort.mir +++ b/tests/mir-opt/tail_expr_drop_order_unwind.method_1.ElaborateDrops.after.panic-abort.mir @@ -12,10 +12,9 @@ fn method_1(_1: Guard) -> () { let _8: OtherDrop; let _9: (); let mut _10: bool; - let mut _11: bool; + let mut _11: isize; let mut _12: isize; let mut _13: isize; - let mut _14: isize; scope 1 { debug other_drop => _8; } @@ -24,7 +23,6 @@ fn method_1(_1: Guard) -> () { } bb0: { - _11 = const false; _10 = const false; StorageLive(_2); StorageLive(_3); @@ -32,15 +30,14 @@ fn method_1(_1: Guard) -> () { StorageLive(_5); StorageLive(_6); _6 = &_1; - _5 = ::clone(move _6) -> [return: bb1, unwind: bb16]; + _5 = ::clone(move _6) -> [return: bb1, unwind: bb13]; } bb1: { - _11 = const true; StorageDead(_6); _4 = &_5; _3 = &(*_4); - _2 = method_2(move _3) -> [return: bb2, unwind: bb14]; + _2 = method_2(move _3) -> [return: bb2, unwind: bb12]; } bb2: { @@ -78,20 +75,19 @@ fn method_1(_1: Guard) -> () { bb7: { backward incompatible drop(_2); backward incompatible drop(_5); - goto -> bb24; + goto -> bb21; } bb8: { - drop(_5) -> [return: bb9, unwind: bb16]; + drop(_5) -> [return: bb9, unwind: bb13]; } bb9: { - _11 = const false; StorageDead(_5); StorageDead(_4); _10 = const false; StorageDead(_2); - drop(_1) -> [return: bb10, unwind: bb17]; + drop(_1) -> [return: bb10, unwind: bb14]; } bb10: { @@ -99,7 +95,7 @@ fn method_1(_1: Guard) -> () { } bb11 (cleanup): { - goto -> bb28; + goto -> bb25; } bb12 (cleanup): { @@ -107,77 +103,57 @@ fn method_1(_1: Guard) -> () { } bb13 (cleanup): { - goto -> bb15; + drop(_1) -> [return: bb14, unwind terminate(cleanup)]; } bb14 (cleanup): { - drop(_5) -> [return: bb15, unwind terminate(cleanup)]; - } - - bb15 (cleanup): { - goto -> bb30; - } - - bb16 (cleanup): { - drop(_1) -> [return: bb17, unwind terminate(cleanup)]; - } - - bb17 (cleanup): { resume; } - bb18: { + bb15: { goto -> bb8; } - bb19 (cleanup): { + bb16 (cleanup): { + goto -> bb12; + } + + bb17 (cleanup): { + goto -> bb12; + } + + bb18: { + goto -> bb15; + } + + bb19: { goto -> bb15; } bb20 (cleanup): { - goto -> bb15; + goto -> bb12; } bb21: { - goto -> bb18; + _11 = discriminant(_2); + switchInt(move _11) -> [0: bb18, otherwise: bb19]; } - bb22: { - goto -> bb18; + bb22 (cleanup): { + _12 = discriminant(_2); + switchInt(move _12) -> [0: bb16, otherwise: bb20]; } bb23 (cleanup): { - goto -> bb15; + goto -> bb12; } - bb24: { - _12 = discriminant(_2); - switchInt(move _12) -> [0: bb21, otherwise: bb22]; + bb24 (cleanup): { + goto -> bb12; } bb25 (cleanup): { _13 = discriminant(_2); - switchInt(move _13) -> [0: bb19, otherwise: bb23]; - } - - bb26 (cleanup): { - goto -> bb12; - } - - bb27 (cleanup): { - goto -> bb12; - } - - bb28 (cleanup): { - _14 = discriminant(_2); - switchInt(move _14) -> [0: bb26, otherwise: bb27]; - } - - bb29 (cleanup): { - drop(_5) -> [return: bb16, unwind terminate(cleanup)]; - } - - bb30 (cleanup): { - switchInt(copy _11) -> [0: bb16, otherwise: bb29]; + switchInt(move _13) -> [0: bb23, otherwise: bb24]; } } diff --git a/tests/mir-opt/tail_expr_drop_order_unwind.method_1.ElaborateDrops.after.panic-unwind.mir b/tests/mir-opt/tail_expr_drop_order_unwind.method_1.ElaborateDrops.after.panic-unwind.mir index 54bedfdc0af1..e9bbe30bd774 100644 --- a/tests/mir-opt/tail_expr_drop_order_unwind.method_1.ElaborateDrops.after.panic-unwind.mir +++ b/tests/mir-opt/tail_expr_drop_order_unwind.method_1.ElaborateDrops.after.panic-unwind.mir @@ -12,10 +12,9 @@ fn method_1(_1: Guard) -> () { let _8: OtherDrop; let _9: (); let mut _10: bool; - let mut _11: bool; + let mut _11: isize; let mut _12: isize; let mut _13: isize; - let mut _14: isize; scope 1 { debug other_drop => _8; } @@ -24,7 +23,6 @@ fn method_1(_1: Guard) -> () { } bb0: { - _11 = const false; _10 = const false; StorageLive(_2); StorageLive(_3); @@ -32,15 +30,14 @@ fn method_1(_1: Guard) -> () { StorageLive(_5); StorageLive(_6); _6 = &_1; - _5 = ::clone(move _6) -> [return: bb1, unwind: bb16]; + _5 = ::clone(move _6) -> [return: bb1, unwind: bb13]; } bb1: { - _11 = const true; StorageDead(_6); _4 = &_5; _3 = &(*_4); - _2 = method_2(move _3) -> [return: bb2, unwind: bb14]; + _2 = method_2(move _3) -> [return: bb2, unwind: bb12]; } bb2: { @@ -78,20 +75,19 @@ fn method_1(_1: Guard) -> () { bb7: { backward incompatible drop(_2); backward incompatible drop(_5); - goto -> bb24; + goto -> bb21; } bb8: { - drop(_5) -> [return: bb9, unwind: bb16]; + drop(_5) -> [return: bb9, unwind: bb13]; } bb9: { - _11 = const false; StorageDead(_5); StorageDead(_4); _10 = const false; StorageDead(_2); - drop(_1) -> [return: bb10, unwind: bb17]; + drop(_1) -> [return: bb10, unwind: bb14]; } bb10: { @@ -99,7 +95,7 @@ fn method_1(_1: Guard) -> () { } bb11 (cleanup): { - goto -> bb28; + goto -> bb25; } bb12 (cleanup): { @@ -107,77 +103,57 @@ fn method_1(_1: Guard) -> () { } bb13 (cleanup): { - goto -> bb15; + drop(_1) -> [return: bb14, unwind terminate(cleanup)]; } bb14 (cleanup): { - drop(_5) -> [return: bb15, unwind terminate(cleanup)]; - } - - bb15 (cleanup): { - goto -> bb30; - } - - bb16 (cleanup): { - drop(_1) -> [return: bb17, unwind terminate(cleanup)]; - } - - bb17 (cleanup): { resume; } - bb18: { + bb15: { goto -> bb8; } - bb19 (cleanup): { + bb16 (cleanup): { + goto -> bb12; + } + + bb17 (cleanup): { + goto -> bb12; + } + + bb18: { + goto -> bb15; + } + + bb19: { goto -> bb15; } bb20 (cleanup): { - goto -> bb15; + goto -> bb12; } bb21: { - goto -> bb18; + _11 = discriminant(_2); + switchInt(move _11) -> [0: bb18, otherwise: bb19]; } - bb22: { - goto -> bb18; + bb22 (cleanup): { + _12 = discriminant(_2); + switchInt(move _12) -> [0: bb16, otherwise: bb20]; } bb23 (cleanup): { - goto -> bb15; + goto -> bb12; } - bb24: { - _12 = discriminant(_2); - switchInt(move _12) -> [0: bb21, otherwise: bb22]; + bb24 (cleanup): { + goto -> bb12; } bb25 (cleanup): { _13 = discriminant(_2); - switchInt(move _13) -> [0: bb19, otherwise: bb23]; - } - - bb26 (cleanup): { - goto -> bb12; - } - - bb27 (cleanup): { - goto -> bb12; - } - - bb28 (cleanup): { - _14 = discriminant(_2); - switchInt(move _14) -> [0: bb26, otherwise: bb27]; - } - - bb29 (cleanup): { - drop(_5) -> [return: bb16, unwind terminate(cleanup)]; - } - - bb30 (cleanup): { - switchInt(copy _11) -> [0: bb16, otherwise: bb29]; + switchInt(move _13) -> [0: bb23, otherwise: bb24]; } } diff --git a/tests/mir-opt/tail_expr_drop_order_unwind.rs b/tests/mir-opt/tail_expr_drop_order_unwind.rs index b67b35808750..065e08c34096 100644 --- a/tests/mir-opt/tail_expr_drop_order_unwind.rs +++ b/tests/mir-opt/tail_expr_drop_order_unwind.rs @@ -26,8 +26,8 @@ fn method_1(g: Guard) { match method_2(&g.clone()) { Ok(other_drop) => { // repro needs something else being dropped too. - }, - Err(err) => {}, + } + Err(err) => {} } } From dbf5ae3a864f555cfe6770896a23f7dea77fb6fb Mon Sep 17 00:00:00 2001 From: Eric Huss Date: Wed, 18 Dec 2024 15:03:44 -0800 Subject: [PATCH 71/92] Add reference annotations for the `coverage` attribute --- tests/coverage/attr/impl.cov-map | 12 +++---- tests/coverage/attr/impl.coverage | 1 + tests/coverage/attr/impl.rs | 1 + tests/coverage/attr/module.cov-map | 12 +++---- tests/coverage/attr/module.coverage | 1 + tests/coverage/attr/module.rs | 1 + tests/coverage/attr/nested.cov-map | 8 ++--- tests/coverage/attr/nested.coverage | 1 + tests/coverage/attr/nested.rs | 1 + tests/coverage/attr/off-on-sandwich.cov-map | 12 +++---- tests/coverage/attr/off-on-sandwich.coverage | 1 + tests/coverage/attr/off-on-sandwich.rs | 1 + tests/coverage/no_cov_crate.cov-map | 28 +++++++-------- tests/coverage/no_cov_crate.coverage | 2 ++ tests/coverage/no_cov_crate.rs | 2 ++ tests/ui/coverage-attr/bad-attr-ice.rs | 1 + tests/ui/coverage-attr/bad-attr-ice.stderr | 2 +- tests/ui/coverage-attr/bad-syntax.rs | 2 ++ tests/ui/coverage-attr/bad-syntax.stderr | 26 +++++++------- tests/ui/coverage-attr/name-value.rs | 1 + tests/ui/coverage-attr/name-value.stderr | 38 ++++++++++---------- tests/ui/coverage-attr/no-coverage.rs | 2 ++ tests/ui/coverage-attr/no-coverage.stderr | 22 ++++++------ tests/ui/coverage-attr/subword.rs | 1 + tests/ui/coverage-attr/subword.stderr | 8 ++--- tests/ui/coverage-attr/word-only.rs | 1 + tests/ui/coverage-attr/word-only.stderr | 38 ++++++++++---------- 27 files changed, 123 insertions(+), 103 deletions(-) diff --git a/tests/coverage/attr/impl.cov-map b/tests/coverage/attr/impl.cov-map index afb91af6829c..4d068c290f42 100644 --- a/tests/coverage/attr/impl.cov-map +++ b/tests/coverage/attr/impl.cov-map @@ -1,27 +1,27 @@ Function name: ::off_on (unused) -Raw bytes (9): 0x[01, 01, 00, 01, 00, 0d, 05, 00, 13] +Raw bytes (9): 0x[01, 01, 00, 01, 00, 0e, 05, 00, 13] Number of files: 1 - file 0 => global file 1 Number of expressions: 0 Number of file 0 mappings: 1 -- Code(Zero) at (prev + 13, 5) to (start + 0, 19) +- Code(Zero) at (prev + 14, 5) to (start + 0, 19) Highest counter ID seen: (none) Function name: ::on_inherit (unused) -Raw bytes (9): 0x[01, 01, 00, 01, 00, 15, 05, 00, 17] +Raw bytes (9): 0x[01, 01, 00, 01, 00, 16, 05, 00, 17] Number of files: 1 - file 0 => global file 1 Number of expressions: 0 Number of file 0 mappings: 1 -- Code(Zero) at (prev + 21, 5) to (start + 0, 23) +- Code(Zero) at (prev + 22, 5) to (start + 0, 23) Highest counter ID seen: (none) Function name: ::on_on (unused) -Raw bytes (9): 0x[01, 01, 00, 01, 00, 18, 05, 00, 12] +Raw bytes (9): 0x[01, 01, 00, 01, 00, 19, 05, 00, 12] Number of files: 1 - file 0 => global file 1 Number of expressions: 0 Number of file 0 mappings: 1 -- Code(Zero) at (prev + 24, 5) to (start + 0, 18) +- Code(Zero) at (prev + 25, 5) to (start + 0, 18) Highest counter ID seen: (none) diff --git a/tests/coverage/attr/impl.coverage b/tests/coverage/attr/impl.coverage index 205b9e830a56..af00df5d7437 100644 --- a/tests/coverage/attr/impl.coverage +++ b/tests/coverage/attr/impl.coverage @@ -1,4 +1,5 @@ LL| |//@ edition: 2021 + LL| |//@ reference: attributes.coverage.nesting LL| | LL| |// Checks that `#[coverage(..)]` can be applied to impl and impl-trait blocks, LL| |// and is inherited by any enclosed functions. diff --git a/tests/coverage/attr/impl.rs b/tests/coverage/attr/impl.rs index 8c1f991926dc..db08fdc41798 100644 --- a/tests/coverage/attr/impl.rs +++ b/tests/coverage/attr/impl.rs @@ -1,4 +1,5 @@ //@ edition: 2021 +//@ reference: attributes.coverage.nesting // Checks that `#[coverage(..)]` can be applied to impl and impl-trait blocks, // and is inherited by any enclosed functions. diff --git a/tests/coverage/attr/module.cov-map b/tests/coverage/attr/module.cov-map index 3efc745dba37..b318ac85a6c8 100644 --- a/tests/coverage/attr/module.cov-map +++ b/tests/coverage/attr/module.cov-map @@ -1,27 +1,27 @@ Function name: module::off::on (unused) -Raw bytes (9): 0x[01, 01, 00, 01, 00, 0b, 05, 00, 0f] +Raw bytes (9): 0x[01, 01, 00, 01, 00, 0c, 05, 00, 0f] Number of files: 1 - file 0 => global file 1 Number of expressions: 0 Number of file 0 mappings: 1 -- Code(Zero) at (prev + 11, 5) to (start + 0, 15) +- Code(Zero) at (prev + 12, 5) to (start + 0, 15) Highest counter ID seen: (none) Function name: module::on::inherit (unused) -Raw bytes (9): 0x[01, 01, 00, 01, 00, 13, 05, 00, 14] +Raw bytes (9): 0x[01, 01, 00, 01, 00, 14, 05, 00, 14] Number of files: 1 - file 0 => global file 1 Number of expressions: 0 Number of file 0 mappings: 1 -- Code(Zero) at (prev + 19, 5) to (start + 0, 20) +- Code(Zero) at (prev + 20, 5) to (start + 0, 20) Highest counter ID seen: (none) Function name: module::on::on (unused) -Raw bytes (9): 0x[01, 01, 00, 01, 00, 16, 05, 00, 0f] +Raw bytes (9): 0x[01, 01, 00, 01, 00, 17, 05, 00, 0f] Number of files: 1 - file 0 => global file 1 Number of expressions: 0 Number of file 0 mappings: 1 -- Code(Zero) at (prev + 22, 5) to (start + 0, 15) +- Code(Zero) at (prev + 23, 5) to (start + 0, 15) Highest counter ID seen: (none) diff --git a/tests/coverage/attr/module.coverage b/tests/coverage/attr/module.coverage index acad03120690..732850fb04a2 100644 --- a/tests/coverage/attr/module.coverage +++ b/tests/coverage/attr/module.coverage @@ -1,4 +1,5 @@ LL| |//@ edition: 2021 + LL| |//@ reference: attributes.coverage.nesting LL| | LL| |// Checks that `#[coverage(..)]` can be applied to modules, and is inherited LL| |// by any enclosed functions. diff --git a/tests/coverage/attr/module.rs b/tests/coverage/attr/module.rs index ed530d53e47a..c0ec5bc1d625 100644 --- a/tests/coverage/attr/module.rs +++ b/tests/coverage/attr/module.rs @@ -1,4 +1,5 @@ //@ edition: 2021 +//@ reference: attributes.coverage.nesting // Checks that `#[coverage(..)]` can be applied to modules, and is inherited // by any enclosed functions. diff --git a/tests/coverage/attr/nested.cov-map b/tests/coverage/attr/nested.cov-map index 2bd953253732..138b3159ea5c 100644 --- a/tests/coverage/attr/nested.cov-map +++ b/tests/coverage/attr/nested.cov-map @@ -1,20 +1,20 @@ Function name: nested::closure_expr -Raw bytes (14): 0x[01, 01, 00, 02, 01, 3f, 01, 01, 0f, 01, 0b, 05, 01, 02] +Raw bytes (14): 0x[01, 01, 00, 02, 01, 40, 01, 01, 0f, 01, 0b, 05, 01, 02] Number of files: 1 - file 0 => global file 1 Number of expressions: 0 Number of file 0 mappings: 2 -- Code(Counter(0)) at (prev + 63, 1) to (start + 1, 15) +- Code(Counter(0)) at (prev + 64, 1) to (start + 1, 15) - Code(Counter(0)) at (prev + 11, 5) to (start + 1, 2) Highest counter ID seen: c0 Function name: nested::closure_tail -Raw bytes (14): 0x[01, 01, 00, 02, 01, 4e, 01, 01, 0f, 01, 11, 05, 01, 02] +Raw bytes (14): 0x[01, 01, 00, 02, 01, 4f, 01, 01, 0f, 01, 11, 05, 01, 02] Number of files: 1 - file 0 => global file 1 Number of expressions: 0 Number of file 0 mappings: 2 -- Code(Counter(0)) at (prev + 78, 1) to (start + 1, 15) +- Code(Counter(0)) at (prev + 79, 1) to (start + 1, 15) - Code(Counter(0)) at (prev + 17, 5) to (start + 1, 2) Highest counter ID seen: c0 diff --git a/tests/coverage/attr/nested.coverage b/tests/coverage/attr/nested.coverage index 1e2525eb8601..13e9aa0a8e81 100644 --- a/tests/coverage/attr/nested.coverage +++ b/tests/coverage/attr/nested.coverage @@ -1,5 +1,6 @@ LL| |#![feature(stmt_expr_attributes)] LL| |//@ edition: 2021 + LL| |//@ reference: attributes.coverage.nesting LL| | LL| |// Demonstrates the interaction between #[coverage(off)] and various kinds of LL| |// nested function. diff --git a/tests/coverage/attr/nested.rs b/tests/coverage/attr/nested.rs index 019f07428c11..184fa54c0669 100644 --- a/tests/coverage/attr/nested.rs +++ b/tests/coverage/attr/nested.rs @@ -1,5 +1,6 @@ #![feature(stmt_expr_attributes)] //@ edition: 2021 +//@ reference: attributes.coverage.nesting // Demonstrates the interaction between #[coverage(off)] and various kinds of // nested function. diff --git a/tests/coverage/attr/off-on-sandwich.cov-map b/tests/coverage/attr/off-on-sandwich.cov-map index d7972d0cc9e0..ae5c9bd19a29 100644 --- a/tests/coverage/attr/off-on-sandwich.cov-map +++ b/tests/coverage/attr/off-on-sandwich.cov-map @@ -1,30 +1,30 @@ Function name: off_on_sandwich::dense_a::dense_b -Raw bytes (14): 0x[01, 01, 00, 02, 01, 0e, 05, 02, 12, 01, 07, 05, 00, 06] +Raw bytes (14): 0x[01, 01, 00, 02, 01, 0f, 05, 02, 12, 01, 07, 05, 00, 06] Number of files: 1 - file 0 => global file 1 Number of expressions: 0 Number of file 0 mappings: 2 -- Code(Counter(0)) at (prev + 14, 5) to (start + 2, 18) +- Code(Counter(0)) at (prev + 15, 5) to (start + 2, 18) - Code(Counter(0)) at (prev + 7, 5) to (start + 0, 6) Highest counter ID seen: c0 Function name: off_on_sandwich::sparse_a::sparse_b::sparse_c -Raw bytes (14): 0x[01, 01, 00, 02, 01, 20, 09, 02, 17, 01, 0b, 09, 00, 0a] +Raw bytes (14): 0x[01, 01, 00, 02, 01, 21, 09, 02, 17, 01, 0b, 09, 00, 0a] Number of files: 1 - file 0 => global file 1 Number of expressions: 0 Number of file 0 mappings: 2 -- Code(Counter(0)) at (prev + 32, 9) to (start + 2, 23) +- Code(Counter(0)) at (prev + 33, 9) to (start + 2, 23) - Code(Counter(0)) at (prev + 11, 9) to (start + 0, 10) Highest counter ID seen: c0 Function name: off_on_sandwich::sparse_a::sparse_b::sparse_c::sparse_d -Raw bytes (14): 0x[01, 01, 00, 02, 01, 23, 0d, 02, 1b, 01, 07, 0d, 00, 0e] +Raw bytes (14): 0x[01, 01, 00, 02, 01, 24, 0d, 02, 1b, 01, 07, 0d, 00, 0e] Number of files: 1 - file 0 => global file 1 Number of expressions: 0 Number of file 0 mappings: 2 -- Code(Counter(0)) at (prev + 35, 13) to (start + 2, 27) +- Code(Counter(0)) at (prev + 36, 13) to (start + 2, 27) - Code(Counter(0)) at (prev + 7, 13) to (start + 0, 14) Highest counter ID seen: c0 diff --git a/tests/coverage/attr/off-on-sandwich.coverage b/tests/coverage/attr/off-on-sandwich.coverage index f23c248c0eba..7a8c01b31ebc 100644 --- a/tests/coverage/attr/off-on-sandwich.coverage +++ b/tests/coverage/attr/off-on-sandwich.coverage @@ -1,4 +1,5 @@ LL| |//@ edition: 2021 + LL| |//@ reference: attributes.coverage.nesting LL| | LL| |// Demonstrates the interaction of `#[coverage(off)]` and `#[coverage(on)]` LL| |// in nested functions. diff --git a/tests/coverage/attr/off-on-sandwich.rs b/tests/coverage/attr/off-on-sandwich.rs index 4272365d87dc..6603e071deef 100644 --- a/tests/coverage/attr/off-on-sandwich.rs +++ b/tests/coverage/attr/off-on-sandwich.rs @@ -1,4 +1,5 @@ //@ edition: 2021 +//@ reference: attributes.coverage.nesting // Demonstrates the interaction of `#[coverage(off)]` and `#[coverage(on)]` // in nested functions. diff --git a/tests/coverage/no_cov_crate.cov-map b/tests/coverage/no_cov_crate.cov-map index dd01774b9c4b..0eb86ef93662 100644 --- a/tests/coverage/no_cov_crate.cov-map +++ b/tests/coverage/no_cov_crate.cov-map @@ -1,67 +1,67 @@ Function name: no_cov_crate::add_coverage_1 -Raw bytes (9): 0x[01, 01, 00, 01, 01, 13, 01, 02, 02] +Raw bytes (9): 0x[01, 01, 00, 01, 01, 15, 01, 02, 02] Number of files: 1 - file 0 => global file 1 Number of expressions: 0 Number of file 0 mappings: 1 -- Code(Counter(0)) at (prev + 19, 1) to (start + 2, 2) +- Code(Counter(0)) at (prev + 21, 1) to (start + 2, 2) Highest counter ID seen: c0 Function name: no_cov_crate::add_coverage_2 -Raw bytes (9): 0x[01, 01, 00, 01, 01, 17, 01, 02, 02] +Raw bytes (9): 0x[01, 01, 00, 01, 01, 19, 01, 02, 02] Number of files: 1 - file 0 => global file 1 Number of expressions: 0 Number of file 0 mappings: 1 -- Code(Counter(0)) at (prev + 23, 1) to (start + 2, 2) +- Code(Counter(0)) at (prev + 25, 1) to (start + 2, 2) Highest counter ID seen: c0 Function name: no_cov_crate::add_coverage_not_called (unused) -Raw bytes (9): 0x[01, 01, 00, 01, 00, 1c, 01, 02, 02] +Raw bytes (9): 0x[01, 01, 00, 01, 00, 1e, 01, 02, 02] Number of files: 1 - file 0 => global file 1 Number of expressions: 0 Number of file 0 mappings: 1 -- Code(Zero) at (prev + 28, 1) to (start + 2, 2) +- Code(Zero) at (prev + 30, 1) to (start + 2, 2) Highest counter ID seen: (none) Function name: no_cov_crate::main -Raw bytes (9): 0x[01, 01, 00, 01, 01, 4c, 01, 0b, 02] +Raw bytes (9): 0x[01, 01, 00, 01, 01, 4e, 01, 0b, 02] Number of files: 1 - file 0 => global file 1 Number of expressions: 0 Number of file 0 mappings: 1 -- Code(Counter(0)) at (prev + 76, 1) to (start + 11, 2) +- Code(Counter(0)) at (prev + 78, 1) to (start + 11, 2) Highest counter ID seen: c0 Function name: no_cov_crate::nested_fns::outer -Raw bytes (14): 0x[01, 01, 00, 02, 01, 30, 05, 02, 23, 01, 0c, 05, 00, 06] +Raw bytes (14): 0x[01, 01, 00, 02, 01, 32, 05, 02, 23, 01, 0c, 05, 00, 06] Number of files: 1 - file 0 => global file 1 Number of expressions: 0 Number of file 0 mappings: 2 -- Code(Counter(0)) at (prev + 48, 5) to (start + 2, 35) +- Code(Counter(0)) at (prev + 50, 5) to (start + 2, 35) - Code(Counter(0)) at (prev + 12, 5) to (start + 0, 6) Highest counter ID seen: c0 Function name: no_cov_crate::nested_fns::outer_both_covered -Raw bytes (14): 0x[01, 01, 00, 02, 01, 3e, 05, 02, 17, 01, 0b, 05, 00, 06] +Raw bytes (14): 0x[01, 01, 00, 02, 01, 40, 05, 02, 17, 01, 0b, 05, 00, 06] Number of files: 1 - file 0 => global file 1 Number of expressions: 0 Number of file 0 mappings: 2 -- Code(Counter(0)) at (prev + 62, 5) to (start + 2, 23) +- Code(Counter(0)) at (prev + 64, 5) to (start + 2, 23) - Code(Counter(0)) at (prev + 11, 5) to (start + 0, 6) Highest counter ID seen: c0 Function name: no_cov_crate::nested_fns::outer_both_covered::inner -Raw bytes (26): 0x[01, 01, 01, 01, 05, 04, 01, 42, 09, 01, 17, 05, 01, 18, 02, 0e, 02, 02, 14, 02, 0e, 01, 03, 09, 00, 0a] +Raw bytes (26): 0x[01, 01, 01, 01, 05, 04, 01, 44, 09, 01, 17, 05, 01, 18, 02, 0e, 02, 02, 14, 02, 0e, 01, 03, 09, 00, 0a] Number of files: 1 - file 0 => global file 1 Number of expressions: 1 - expression 0 operands: lhs = Counter(0), rhs = Counter(1) Number of file 0 mappings: 4 -- Code(Counter(0)) at (prev + 66, 9) to (start + 1, 23) +- Code(Counter(0)) at (prev + 68, 9) to (start + 1, 23) - Code(Counter(1)) at (prev + 1, 24) to (start + 2, 14) - Code(Expression(0, Sub)) at (prev + 2, 20) to (start + 2, 14) = (c0 - c1) diff --git a/tests/coverage/no_cov_crate.coverage b/tests/coverage/no_cov_crate.coverage index b08e56044545..a75057287bcd 100644 --- a/tests/coverage/no_cov_crate.coverage +++ b/tests/coverage/no_cov_crate.coverage @@ -1,4 +1,6 @@ LL| |// Enables `coverage(off)` on the entire crate + LL| |//@ reference: attributes.coverage.intro + LL| |//@ reference: attributes.coverage.nesting LL| | LL| |#[coverage(off)] LL| |fn do_not_add_coverage_1() { diff --git a/tests/coverage/no_cov_crate.rs b/tests/coverage/no_cov_crate.rs index 1b4b384b1671..df8594e9790b 100644 --- a/tests/coverage/no_cov_crate.rs +++ b/tests/coverage/no_cov_crate.rs @@ -1,4 +1,6 @@ // Enables `coverage(off)` on the entire crate +//@ reference: attributes.coverage.intro +//@ reference: attributes.coverage.nesting #[coverage(off)] fn do_not_add_coverage_1() { diff --git a/tests/ui/coverage-attr/bad-attr-ice.rs b/tests/ui/coverage-attr/bad-attr-ice.rs index eaf9ec255dcf..4b58989e3a2a 100644 --- a/tests/ui/coverage-attr/bad-attr-ice.rs +++ b/tests/ui/coverage-attr/bad-attr-ice.rs @@ -1,5 +1,6 @@ //@ compile-flags: -Cinstrument-coverage //@ needs-profiler-runtime +//@ reference: attributes.coverage.syntax // Malformed `#[coverage(..)]` attributes should not cause an ICE when built // with `-Cinstrument-coverage`. diff --git a/tests/ui/coverage-attr/bad-attr-ice.stderr b/tests/ui/coverage-attr/bad-attr-ice.stderr index e48436ccdfe0..dc88bb8d1a40 100644 --- a/tests/ui/coverage-attr/bad-attr-ice.stderr +++ b/tests/ui/coverage-attr/bad-attr-ice.stderr @@ -1,5 +1,5 @@ error: malformed `coverage` attribute input - --> $DIR/bad-attr-ice.rs:8:1 + --> $DIR/bad-attr-ice.rs:9:1 | LL | #[coverage] | ^^^^^^^^^^^ diff --git a/tests/ui/coverage-attr/bad-syntax.rs b/tests/ui/coverage-attr/bad-syntax.rs index fa2b25ceccd7..ad6c5dc03f12 100644 --- a/tests/ui/coverage-attr/bad-syntax.rs +++ b/tests/ui/coverage-attr/bad-syntax.rs @@ -1,4 +1,6 @@ //@ edition: 2021 +//@ reference: attributes.coverage.syntax +//@ reference: attributes.coverage.duplicates // Tests the error messages produced (or not produced) by various unusual // uses of the `#[coverage(..)]` attribute. diff --git a/tests/ui/coverage-attr/bad-syntax.stderr b/tests/ui/coverage-attr/bad-syntax.stderr index e1833b57a723..072a8c4ca943 100644 --- a/tests/ui/coverage-attr/bad-syntax.stderr +++ b/tests/ui/coverage-attr/bad-syntax.stderr @@ -1,5 +1,5 @@ error: malformed `coverage` attribute input - --> $DIR/bad-syntax.rs:14:1 + --> $DIR/bad-syntax.rs:16:1 | LL | #[coverage] | ^^^^^^^^^^^ @@ -12,7 +12,7 @@ LL | #[coverage(on)] | ~~~~~~~~~~~~~~~ error: malformed `coverage` attribute input - --> $DIR/bad-syntax.rs:17:1 + --> $DIR/bad-syntax.rs:19:1 | LL | #[coverage = true] | ^^^^^^^^^^^^^^^^^^ @@ -25,7 +25,7 @@ LL | #[coverage(on)] | ~~~~~~~~~~~~~~~ error: malformed `coverage` attribute input - --> $DIR/bad-syntax.rs:20:1 + --> $DIR/bad-syntax.rs:22:1 | LL | #[coverage()] | ^^^^^^^^^^^^^ @@ -38,7 +38,7 @@ LL | #[coverage(on)] | ~~~~~~~~~~~~~~~ error: malformed `coverage` attribute input - --> $DIR/bad-syntax.rs:23:1 + --> $DIR/bad-syntax.rs:25:1 | LL | #[coverage(off, off)] | ^^^^^^^^^^^^^^^^^^^^^ @@ -51,7 +51,7 @@ LL | #[coverage(on)] | ~~~~~~~~~~~~~~~ error: malformed `coverage` attribute input - --> $DIR/bad-syntax.rs:26:1 + --> $DIR/bad-syntax.rs:28:1 | LL | #[coverage(off, on)] | ^^^^^^^^^^^^^^^^^^^^ @@ -64,7 +64,7 @@ LL | #[coverage(on)] | ~~~~~~~~~~~~~~~ error: malformed `coverage` attribute input - --> $DIR/bad-syntax.rs:29:1 + --> $DIR/bad-syntax.rs:31:1 | LL | #[coverage(bogus)] | ^^^^^^^^^^^^^^^^^^ @@ -77,7 +77,7 @@ LL | #[coverage(on)] | ~~~~~~~~~~~~~~~ error: malformed `coverage` attribute input - --> $DIR/bad-syntax.rs:32:1 + --> $DIR/bad-syntax.rs:34:1 | LL | #[coverage(bogus, off)] | ^^^^^^^^^^^^^^^^^^^^^^^ @@ -90,7 +90,7 @@ LL | #[coverage(on)] | ~~~~~~~~~~~~~~~ error: malformed `coverage` attribute input - --> $DIR/bad-syntax.rs:35:1 + --> $DIR/bad-syntax.rs:37:1 | LL | #[coverage(off, bogus)] | ^^^^^^^^^^^^^^^^^^^^^^^ @@ -103,7 +103,7 @@ LL | #[coverage(on)] | ~~~~~~~~~~~~~~~ error: expected identifier, found `,` - --> $DIR/bad-syntax.rs:41:12 + --> $DIR/bad-syntax.rs:43:12 | LL | #[coverage(,off)] | ^ expected identifier @@ -115,25 +115,25 @@ LL + #[coverage(off)] | error: multiple `coverage` attributes - --> $DIR/bad-syntax.rs:6:1 + --> $DIR/bad-syntax.rs:8:1 | LL | #[coverage(off)] | ^^^^^^^^^^^^^^^^ help: remove this attribute | note: attribute also specified here - --> $DIR/bad-syntax.rs:7:1 + --> $DIR/bad-syntax.rs:9:1 | LL | #[coverage(off)] | ^^^^^^^^^^^^^^^^ error: multiple `coverage` attributes - --> $DIR/bad-syntax.rs:10:1 + --> $DIR/bad-syntax.rs:12:1 | LL | #[coverage(off)] | ^^^^^^^^^^^^^^^^ help: remove this attribute | note: attribute also specified here - --> $DIR/bad-syntax.rs:11:1 + --> $DIR/bad-syntax.rs:13:1 | LL | #[coverage(on)] | ^^^^^^^^^^^^^^^ diff --git a/tests/ui/coverage-attr/name-value.rs b/tests/ui/coverage-attr/name-value.rs index 4d09b3796a79..cdb2f6490f24 100644 --- a/tests/ui/coverage-attr/name-value.rs +++ b/tests/ui/coverage-attr/name-value.rs @@ -1,4 +1,5 @@ //@ edition: 2021 +//@ reference: attributes.coverage.syntax // Demonstrates the diagnostics produced when using the syntax // `#[coverage = "off"]`, which should not be allowed. diff --git a/tests/ui/coverage-attr/name-value.stderr b/tests/ui/coverage-attr/name-value.stderr index 48581df52f79..38101764d6f9 100644 --- a/tests/ui/coverage-attr/name-value.stderr +++ b/tests/ui/coverage-attr/name-value.stderr @@ -1,5 +1,5 @@ error: malformed `coverage` attribute input - --> $DIR/name-value.rs:10:1 + --> $DIR/name-value.rs:11:1 | LL | #[coverage = "off"] | ^^^^^^^^^^^^^^^^^^^ @@ -12,7 +12,7 @@ LL | #[coverage(on)] | error: malformed `coverage` attribute input - --> $DIR/name-value.rs:15:5 + --> $DIR/name-value.rs:16:5 | LL | #![coverage = "off"] | ^^^^^^^^^^^^^^^^^^^^ @@ -25,7 +25,7 @@ LL | #![coverage(on)] | error: malformed `coverage` attribute input - --> $DIR/name-value.rs:19:1 + --> $DIR/name-value.rs:20:1 | LL | #[coverage = "off"] | ^^^^^^^^^^^^^^^^^^^ @@ -38,7 +38,7 @@ LL | #[coverage(on)] | error: malformed `coverage` attribute input - --> $DIR/name-value.rs:27:5 + --> $DIR/name-value.rs:28:5 | LL | #[coverage = "off"] | ^^^^^^^^^^^^^^^^^^^ @@ -51,7 +51,7 @@ LL | #[coverage(on)] | error: malformed `coverage` attribute input - --> $DIR/name-value.rs:24:1 + --> $DIR/name-value.rs:25:1 | LL | #[coverage = "off"] | ^^^^^^^^^^^^^^^^^^^ @@ -64,7 +64,7 @@ LL | #[coverage(on)] | error: malformed `coverage` attribute input - --> $DIR/name-value.rs:37:5 + --> $DIR/name-value.rs:38:5 | LL | #[coverage = "off"] | ^^^^^^^^^^^^^^^^^^^ @@ -77,7 +77,7 @@ LL | #[coverage(on)] | error: malformed `coverage` attribute input - --> $DIR/name-value.rs:42:5 + --> $DIR/name-value.rs:43:5 | LL | #[coverage = "off"] | ^^^^^^^^^^^^^^^^^^^ @@ -90,7 +90,7 @@ LL | #[coverage(on)] | error: malformed `coverage` attribute input - --> $DIR/name-value.rs:33:1 + --> $DIR/name-value.rs:34:1 | LL | #[coverage = "off"] | ^^^^^^^^^^^^^^^^^^^ @@ -103,7 +103,7 @@ LL | #[coverage(on)] | error: malformed `coverage` attribute input - --> $DIR/name-value.rs:51:5 + --> $DIR/name-value.rs:52:5 | LL | #[coverage = "off"] | ^^^^^^^^^^^^^^^^^^^ @@ -116,7 +116,7 @@ LL | #[coverage(on)] | error: malformed `coverage` attribute input - --> $DIR/name-value.rs:56:5 + --> $DIR/name-value.rs:57:5 | LL | #[coverage = "off"] | ^^^^^^^^^^^^^^^^^^^ @@ -129,7 +129,7 @@ LL | #[coverage(on)] | error: malformed `coverage` attribute input - --> $DIR/name-value.rs:48:1 + --> $DIR/name-value.rs:49:1 | LL | #[coverage = "off"] | ^^^^^^^^^^^^^^^^^^^ @@ -142,7 +142,7 @@ LL | #[coverage(on)] | error: malformed `coverage` attribute input - --> $DIR/name-value.rs:62:1 + --> $DIR/name-value.rs:63:1 | LL | #[coverage = "off"] | ^^^^^^^^^^^^^^^^^^^ @@ -155,7 +155,7 @@ LL | #[coverage(on)] | error[E0788]: attribute should be applied to a function definition or closure - --> $DIR/name-value.rs:19:1 + --> $DIR/name-value.rs:20:1 | LL | #[coverage = "off"] | ^^^^^^^^^^^^^^^^^^^ @@ -164,7 +164,7 @@ LL | struct MyStruct; | ---------------- not a function or closure error[E0788]: attribute should be applied to a function definition or closure - --> $DIR/name-value.rs:33:1 + --> $DIR/name-value.rs:34:1 | LL | #[coverage = "off"] | ^^^^^^^^^^^^^^^^^^^ @@ -177,7 +177,7 @@ LL | | } | |_- not a function or closure error[E0788]: attribute should be applied to a function definition or closure - --> $DIR/name-value.rs:37:5 + --> $DIR/name-value.rs:38:5 | LL | #[coverage = "off"] | ^^^^^^^^^^^^^^^^^^^ @@ -186,7 +186,7 @@ LL | const X: u32; | ------------- not a function or closure error[E0788]: attribute should be applied to a function definition or closure - --> $DIR/name-value.rs:42:5 + --> $DIR/name-value.rs:43:5 | LL | #[coverage = "off"] | ^^^^^^^^^^^^^^^^^^^ @@ -195,7 +195,7 @@ LL | type T; | ------- not a function or closure error[E0788]: attribute should be applied to a function definition or closure - --> $DIR/name-value.rs:27:5 + --> $DIR/name-value.rs:28:5 | LL | #[coverage = "off"] | ^^^^^^^^^^^^^^^^^^^ @@ -204,7 +204,7 @@ LL | const X: u32 = 7; | ----------------- not a function or closure error[E0788]: attribute should be applied to a function definition or closure - --> $DIR/name-value.rs:51:5 + --> $DIR/name-value.rs:52:5 | LL | #[coverage = "off"] | ^^^^^^^^^^^^^^^^^^^ @@ -213,7 +213,7 @@ LL | const X: u32 = 8; | ----------------- not a function or closure error[E0788]: attribute should be applied to a function definition or closure - --> $DIR/name-value.rs:56:5 + --> $DIR/name-value.rs:57:5 | LL | #[coverage = "off"] | ^^^^^^^^^^^^^^^^^^^ diff --git a/tests/ui/coverage-attr/no-coverage.rs b/tests/ui/coverage-attr/no-coverage.rs index 634eceee0f67..691456aee40e 100644 --- a/tests/ui/coverage-attr/no-coverage.rs +++ b/tests/ui/coverage-attr/no-coverage.rs @@ -1,3 +1,5 @@ +//@ reference: attributes.coverage.allowed-positions + #![feature(extern_types)] #![feature(impl_trait_in_assoc_type)] #![warn(unused_attributes)] diff --git a/tests/ui/coverage-attr/no-coverage.stderr b/tests/ui/coverage-attr/no-coverage.stderr index 6f117c68f88d..2421d2771f58 100644 --- a/tests/ui/coverage-attr/no-coverage.stderr +++ b/tests/ui/coverage-attr/no-coverage.stderr @@ -1,5 +1,5 @@ error[E0788]: attribute should be applied to a function definition or closure - --> $DIR/no-coverage.rs:6:1 + --> $DIR/no-coverage.rs:8:1 | LL | #[coverage(off)] | ^^^^^^^^^^^^^^^^ @@ -12,7 +12,7 @@ LL | | } | |_- not a function or closure error[E0788]: attribute should be applied to a function definition or closure - --> $DIR/no-coverage.rs:38:5 + --> $DIR/no-coverage.rs:40:5 | LL | #[coverage(off)] | ^^^^^^^^^^^^^^^^ @@ -20,7 +20,7 @@ LL | let _ = (); | ----------- not a function or closure error[E0788]: attribute should be applied to a function definition or closure - --> $DIR/no-coverage.rs:42:9 + --> $DIR/no-coverage.rs:44:9 | LL | #[coverage(off)] | ^^^^^^^^^^^^^^^^ @@ -28,7 +28,7 @@ LL | () => (), | -------- not a function or closure error[E0788]: attribute should be applied to a function definition or closure - --> $DIR/no-coverage.rs:46:5 + --> $DIR/no-coverage.rs:48:5 | LL | #[coverage(off)] | ^^^^^^^^^^^^^^^^ @@ -36,7 +36,7 @@ LL | return (); | --------- not a function or closure error[E0788]: attribute should be applied to a function definition or closure - --> $DIR/no-coverage.rs:8:5 + --> $DIR/no-coverage.rs:10:5 | LL | #[coverage(off)] | ^^^^^^^^^^^^^^^^ @@ -44,7 +44,7 @@ LL | const X: u32; | ------------- not a function or closure error[E0788]: attribute should be applied to a function definition or closure - --> $DIR/no-coverage.rs:11:5 + --> $DIR/no-coverage.rs:13:5 | LL | #[coverage(off)] | ^^^^^^^^^^^^^^^^ @@ -52,7 +52,7 @@ LL | type T; | ------- not a function or closure error[E0788]: attribute should be applied to a function definition or closure - --> $DIR/no-coverage.rs:21:5 + --> $DIR/no-coverage.rs:23:5 | LL | #[coverage(off)] | ^^^^^^^^^^^^^^^^ @@ -60,7 +60,7 @@ LL | type T = Self; | -------------- not a function or closure error[E0788]: attribute should be applied to a function definition or closure - --> $DIR/no-coverage.rs:24:5 + --> $DIR/no-coverage.rs:26:5 | LL | #[coverage(off)] | ^^^^^^^^^^^^^^^^ @@ -68,7 +68,7 @@ LL | type U = impl Trait; | -------------------- not a function or closure error[E0788]: attribute should be applied to a function definition or closure - --> $DIR/no-coverage.rs:29:5 + --> $DIR/no-coverage.rs:31:5 | LL | #[coverage(off)] | ^^^^^^^^^^^^^^^^ @@ -76,7 +76,7 @@ LL | static X: u32; | -------------- not a function or closure error[E0788]: attribute should be applied to a function definition or closure - --> $DIR/no-coverage.rs:32:5 + --> $DIR/no-coverage.rs:34:5 | LL | #[coverage(off)] | ^^^^^^^^^^^^^^^^ @@ -84,7 +84,7 @@ LL | type T; | ------- not a function or closure error: unconstrained opaque type - --> $DIR/no-coverage.rs:25:14 + --> $DIR/no-coverage.rs:27:14 | LL | type U = impl Trait; | ^^^^^^^^^^ diff --git a/tests/ui/coverage-attr/subword.rs b/tests/ui/coverage-attr/subword.rs index 00c8dea3d374..ff5b750e70e6 100644 --- a/tests/ui/coverage-attr/subword.rs +++ b/tests/ui/coverage-attr/subword.rs @@ -1,4 +1,5 @@ //@ edition: 2021 +//@ reference: attributes.coverage.syntax // Check that yes/no in `#[coverage(yes)]` and `#[coverage(no)]` must be bare // words, not part of a more complicated substructure. diff --git a/tests/ui/coverage-attr/subword.stderr b/tests/ui/coverage-attr/subword.stderr index 60e58c015d88..3a106898f8b9 100644 --- a/tests/ui/coverage-attr/subword.stderr +++ b/tests/ui/coverage-attr/subword.stderr @@ -1,5 +1,5 @@ error: malformed `coverage` attribute input - --> $DIR/subword.rs:6:1 + --> $DIR/subword.rs:7:1 | LL | #[coverage(yes(milord))] | ^^^^^^^^^^^^^^^^^^^^^^^^ @@ -12,7 +12,7 @@ LL | #[coverage(on)] | ~~~~~~~~~~~~~~~ error: malformed `coverage` attribute input - --> $DIR/subword.rs:9:1 + --> $DIR/subword.rs:10:1 | LL | #[coverage(no(milord))] | ^^^^^^^^^^^^^^^^^^^^^^^ @@ -25,7 +25,7 @@ LL | #[coverage(on)] | ~~~~~~~~~~~~~~~ error: malformed `coverage` attribute input - --> $DIR/subword.rs:12:1 + --> $DIR/subword.rs:13:1 | LL | #[coverage(yes = "milord")] | ^^^^^^^^^^^^^^^^^^^^^^^^^^^ @@ -38,7 +38,7 @@ LL | #[coverage(on)] | ~~~~~~~~~~~~~~~ error: malformed `coverage` attribute input - --> $DIR/subword.rs:15:1 + --> $DIR/subword.rs:16:1 | LL | #[coverage(no = "milord")] | ^^^^^^^^^^^^^^^^^^^^^^^^^^ diff --git a/tests/ui/coverage-attr/word-only.rs b/tests/ui/coverage-attr/word-only.rs index 6d9503593f01..496268fd8c89 100644 --- a/tests/ui/coverage-attr/word-only.rs +++ b/tests/ui/coverage-attr/word-only.rs @@ -1,4 +1,5 @@ //@ edition: 2021 +//@ reference: attributes.coverage.syntax // Demonstrates the diagnostics produced when using the syntax `#[coverage]`, // which should not be allowed. diff --git a/tests/ui/coverage-attr/word-only.stderr b/tests/ui/coverage-attr/word-only.stderr index de025cad96f7..154ea61f3a3d 100644 --- a/tests/ui/coverage-attr/word-only.stderr +++ b/tests/ui/coverage-attr/word-only.stderr @@ -1,5 +1,5 @@ error: malformed `coverage` attribute input - --> $DIR/word-only.rs:10:1 + --> $DIR/word-only.rs:11:1 | LL | #[coverage] | ^^^^^^^^^^^ @@ -12,7 +12,7 @@ LL | #[coverage(on)] | error: malformed `coverage` attribute input - --> $DIR/word-only.rs:15:5 + --> $DIR/word-only.rs:16:5 | LL | #![coverage] | ^^^^^^^^^^^^ @@ -25,7 +25,7 @@ LL | #![coverage(on)] | error: malformed `coverage` attribute input - --> $DIR/word-only.rs:19:1 + --> $DIR/word-only.rs:20:1 | LL | #[coverage] | ^^^^^^^^^^^ @@ -38,7 +38,7 @@ LL | #[coverage(on)] | error: malformed `coverage` attribute input - --> $DIR/word-only.rs:27:5 + --> $DIR/word-only.rs:28:5 | LL | #[coverage] | ^^^^^^^^^^^ @@ -51,7 +51,7 @@ LL | #[coverage(on)] | error: malformed `coverage` attribute input - --> $DIR/word-only.rs:24:1 + --> $DIR/word-only.rs:25:1 | LL | #[coverage] | ^^^^^^^^^^^ @@ -64,7 +64,7 @@ LL | #[coverage(on)] | error: malformed `coverage` attribute input - --> $DIR/word-only.rs:37:5 + --> $DIR/word-only.rs:38:5 | LL | #[coverage] | ^^^^^^^^^^^ @@ -77,7 +77,7 @@ LL | #[coverage(on)] | error: malformed `coverage` attribute input - --> $DIR/word-only.rs:42:5 + --> $DIR/word-only.rs:43:5 | LL | #[coverage] | ^^^^^^^^^^^ @@ -90,7 +90,7 @@ LL | #[coverage(on)] | error: malformed `coverage` attribute input - --> $DIR/word-only.rs:33:1 + --> $DIR/word-only.rs:34:1 | LL | #[coverage] | ^^^^^^^^^^^ @@ -103,7 +103,7 @@ LL | #[coverage(on)] | error: malformed `coverage` attribute input - --> $DIR/word-only.rs:51:5 + --> $DIR/word-only.rs:52:5 | LL | #[coverage] | ^^^^^^^^^^^ @@ -116,7 +116,7 @@ LL | #[coverage(on)] | error: malformed `coverage` attribute input - --> $DIR/word-only.rs:56:5 + --> $DIR/word-only.rs:57:5 | LL | #[coverage] | ^^^^^^^^^^^ @@ -129,7 +129,7 @@ LL | #[coverage(on)] | error: malformed `coverage` attribute input - --> $DIR/word-only.rs:48:1 + --> $DIR/word-only.rs:49:1 | LL | #[coverage] | ^^^^^^^^^^^ @@ -142,7 +142,7 @@ LL | #[coverage(on)] | error: malformed `coverage` attribute input - --> $DIR/word-only.rs:62:1 + --> $DIR/word-only.rs:63:1 | LL | #[coverage] | ^^^^^^^^^^^ @@ -155,7 +155,7 @@ LL | #[coverage(on)] | error[E0788]: attribute should be applied to a function definition or closure - --> $DIR/word-only.rs:19:1 + --> $DIR/word-only.rs:20:1 | LL | #[coverage] | ^^^^^^^^^^^ @@ -164,7 +164,7 @@ LL | struct MyStruct; | ---------------- not a function or closure error[E0788]: attribute should be applied to a function definition or closure - --> $DIR/word-only.rs:33:1 + --> $DIR/word-only.rs:34:1 | LL | #[coverage] | ^^^^^^^^^^^ @@ -177,7 +177,7 @@ LL | | } | |_- not a function or closure error[E0788]: attribute should be applied to a function definition or closure - --> $DIR/word-only.rs:37:5 + --> $DIR/word-only.rs:38:5 | LL | #[coverage] | ^^^^^^^^^^^ @@ -186,7 +186,7 @@ LL | const X: u32; | ------------- not a function or closure error[E0788]: attribute should be applied to a function definition or closure - --> $DIR/word-only.rs:42:5 + --> $DIR/word-only.rs:43:5 | LL | #[coverage] | ^^^^^^^^^^^ @@ -195,7 +195,7 @@ LL | type T; | ------- not a function or closure error[E0788]: attribute should be applied to a function definition or closure - --> $DIR/word-only.rs:27:5 + --> $DIR/word-only.rs:28:5 | LL | #[coverage] | ^^^^^^^^^^^ @@ -204,7 +204,7 @@ LL | const X: u32 = 7; | ----------------- not a function or closure error[E0788]: attribute should be applied to a function definition or closure - --> $DIR/word-only.rs:51:5 + --> $DIR/word-only.rs:52:5 | LL | #[coverage] | ^^^^^^^^^^^ @@ -213,7 +213,7 @@ LL | const X: u32 = 8; | ----------------- not a function or closure error[E0788]: attribute should be applied to a function definition or closure - --> $DIR/word-only.rs:56:5 + --> $DIR/word-only.rs:57:5 | LL | #[coverage] | ^^^^^^^^^^^ From 983930635228c36045dd8013dc3251578989ea14 Mon Sep 17 00:00:00 2001 From: rustbot <47979223+rustbot@users.noreply.github.com> Date: Mon, 16 Dec 2024 12:00:54 -0500 Subject: [PATCH 72/92] Update books --- src/doc/book | 2 +- src/doc/edition-guide | 2 +- src/doc/nomicon | 2 +- src/doc/reference | 2 +- src/doc/rust-by-example | 2 +- src/doc/rustc-dev-guide | 2 +- 6 files changed, 6 insertions(+), 6 deletions(-) diff --git a/src/doc/book b/src/doc/book index 9900d976bbfe..ad2011d3bcad 160000 --- a/src/doc/book +++ b/src/doc/book @@ -1 +1 @@ -Subproject commit 9900d976bbfecf4e8124da54351a9ad85ee3c7f3 +Subproject commit ad2011d3bcad9f152d034faf7635c22506839d58 diff --git a/src/doc/edition-guide b/src/doc/edition-guide index 128669297c8a..bc4ce51e1d4d 160000 --- a/src/doc/edition-guide +++ b/src/doc/edition-guide @@ -1 +1 @@ -Subproject commit 128669297c8a7fdf771042eaec18b8adfaeaf0cd +Subproject commit bc4ce51e1d4dacb9350a92e95f6159a42de2f8c6 diff --git a/src/doc/nomicon b/src/doc/nomicon index 0674321898cd..97e84a38c94b 160000 --- a/src/doc/nomicon +++ b/src/doc/nomicon @@ -1 +1 @@ -Subproject commit 0674321898cd454764ab69702819d39a919afd68 +Subproject commit 97e84a38c94bf9362b11284c20b2cb4adaa1e868 diff --git a/src/doc/reference b/src/doc/reference index ede56d1bbe13..9f41bc11342d 160000 --- a/src/doc/reference +++ b/src/doc/reference @@ -1 +1 @@ -Subproject commit ede56d1bbe132bac476b5029cd6d7508ca9572e9 +Subproject commit 9f41bc11342d46544ae0732caf14ec0bcaf27376 diff --git a/src/doc/rust-by-example b/src/doc/rust-by-example index e1d1f2cdcee4..76406337f413 160000 --- a/src/doc/rust-by-example +++ b/src/doc/rust-by-example @@ -1 +1 @@ -Subproject commit e1d1f2cdcee4d52b9a01ff7c448be4372a377b70 +Subproject commit 76406337f4131253443aea0ed7e7f451b464117c diff --git a/src/doc/rustc-dev-guide b/src/doc/rustc-dev-guide index b21d99b770f9..7f7ba48f04ab 160000 --- a/src/doc/rustc-dev-guide +++ b/src/doc/rustc-dev-guide @@ -1 +1 @@ -Subproject commit b21d99b770f9aceb0810c843847c52f86f45d2ed +Subproject commit 7f7ba48f04abc2ad25e52f30b5e2bffa286b019f From f8cd8c1c37892378974766b4ce2eebd138ee70d9 Mon Sep 17 00:00:00 2001 From: leejaehong Date: Thu, 19 Dec 2024 10:37:19 +0900 Subject: [PATCH 73/92] fix typo in ptr/mod.rs Signed-off-by: leejaehong --- library/core/src/ptr/mod.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/library/core/src/ptr/mod.rs b/library/core/src/ptr/mod.rs index 51ab2054b3be..1423e7ea8d10 100644 --- a/library/core/src/ptr/mod.rs +++ b/library/core/src/ptr/mod.rs @@ -84,7 +84,7 @@ // ^ we use this term instead of saying that the produced reference must // be valid, as the validity of a reference is easily confused for the // validity of the thing it refers to, and while the two concepts are -// closly related, they are not identical. +// closely related, they are not identical. //! //! These rules apply even if the result is unused! //! (The part about being initialized is not yet fully decided, but until From 1f352acd34cc3d1a50d0c9b5da3b695167aadf04 Mon Sep 17 00:00:00 2001 From: Michael Goulet Date: Thu, 19 Dec 2024 02:31:52 +0000 Subject: [PATCH 74/92] Use TypingEnv from MIR builder --- compiler/rustc_mir_build/src/builder/scope.rs | 5 +---- 1 file changed, 1 insertion(+), 4 deletions(-) diff --git a/compiler/rustc_mir_build/src/builder/scope.rs b/compiler/rustc_mir_build/src/builder/scope.rs index 882e29de46d3..67a0c9c79350 100644 --- a/compiler/rustc_mir_build/src/builder/scope.rs +++ b/compiler/rustc_mir_build/src/builder/scope.rs @@ -1119,10 +1119,7 @@ impl<'a, 'tcx> Builder<'a, 'tcx> { region_scope: region::Scope, local: Local, ) { - if !self.local_decls[local].ty.has_significant_drop(self.tcx, ty::TypingEnv { - typing_mode: ty::TypingMode::non_body_analysis(), - param_env: self.param_env, - }) { + if !self.local_decls[local].ty.has_significant_drop(self.tcx, self.typing_env()) { return; } for scope in self.scopes.scopes.iter_mut().rev() { From e5e0387cdbc21be09ed39eeaff1a72d3cb2ba389 Mon Sep 17 00:00:00 2001 From: Michael Goulet Date: Thu, 19 Dec 2024 02:28:14 +0000 Subject: [PATCH 75/92] Rename Scope.id to Scope.local_id, remove trivial accessor --- .../rustc_hir_analysis/src/check/region.rs | 22 ++++++------- compiler/rustc_middle/src/middle/region.rs | 32 +++++++------------ compiler/rustc_middle/src/ty/rvalue_scopes.rs | 6 ++-- .../src/builder/expr/as_temp.rs | 4 +-- compiler/rustc_mir_build/src/builder/mod.rs | 4 +-- compiler/rustc_mir_build/src/builder/scope.rs | 2 +- compiler/rustc_mir_build/src/thir/cx/block.rs | 8 ++--- compiler/rustc_mir_build/src/thir/cx/expr.rs | 16 +++++++--- 8 files changed, 45 insertions(+), 49 deletions(-) diff --git a/compiler/rustc_hir_analysis/src/check/region.rs b/compiler/rustc_hir_analysis/src/check/region.rs index b9cb48cafdcd..ca6729a5bbdf 100644 --- a/compiler/rustc_hir_analysis/src/check/region.rs +++ b/compiler/rustc_hir_analysis/src/check/region.rs @@ -129,7 +129,7 @@ fn resolve_block<'tcx>(visitor: &mut RegionResolutionVisitor<'tcx>, blk: &'tcx h let mut prev_cx = visitor.cx; visitor.enter_scope(Scope { - id: blk.hir_id.local_id, + local_id: blk.hir_id.local_id, data: ScopeData::Remainder(FirstStatementIndex::new(i)), }); visitor.cx.var_parent = visitor.cx.parent; @@ -154,7 +154,7 @@ fn resolve_block<'tcx>(visitor: &mut RegionResolutionVisitor<'tcx>, blk: &'tcx h // the first such subscope, which has the block itself as a // parent. visitor.enter_scope(Scope { - id: blk.hir_id.local_id, + local_id: blk.hir_id.local_id, data: ScopeData::Remainder(FirstStatementIndex::new(i)), }); visitor.cx.var_parent = visitor.cx.parent; @@ -184,7 +184,7 @@ fn resolve_block<'tcx>(visitor: &mut RegionResolutionVisitor<'tcx>, blk: &'tcx h visitor .scope_tree .backwards_incompatible_scope - .insert(local_id, Scope { id: local_id, data: ScopeData::Node }); + .insert(local_id, Scope { local_id, data: ScopeData::Node }); } visitor.visit_expr(tail_expr); } @@ -221,7 +221,7 @@ fn resolve_arm<'tcx>(visitor: &mut RegionResolutionVisitor<'tcx>, arm: &'tcx hir } fn resolve_pat<'tcx>(visitor: &mut RegionResolutionVisitor<'tcx>, pat: &'tcx hir::Pat<'tcx>) { - visitor.record_child_scope(Scope { id: pat.hir_id.local_id, data: ScopeData::Node }); + visitor.record_child_scope(Scope { local_id: pat.hir_id.local_id, data: ScopeData::Node }); // If this is a binding then record the lifetime of that binding. if let PatKind::Binding(..) = pat.kind { @@ -485,7 +485,7 @@ fn resolve_expr<'tcx>(visitor: &mut RegionResolutionVisitor<'tcx>, expr: &'tcx h } else { ScopeData::IfThen }; - visitor.enter_scope(Scope { id: then.hir_id.local_id, data }); + visitor.enter_scope(Scope { local_id: then.hir_id.local_id, data }); visitor.cx.var_parent = visitor.cx.parent; visitor.visit_expr(cond); visitor.visit_expr(then); @@ -500,7 +500,7 @@ fn resolve_expr<'tcx>(visitor: &mut RegionResolutionVisitor<'tcx>, expr: &'tcx h } else { ScopeData::IfThen }; - visitor.enter_scope(Scope { id: then.hir_id.local_id, data }); + visitor.enter_scope(Scope { local_id: then.hir_id.local_id, data }); visitor.cx.var_parent = visitor.cx.parent; visitor.visit_expr(cond); visitor.visit_expr(then); @@ -516,7 +516,7 @@ fn resolve_expr<'tcx>(visitor: &mut RegionResolutionVisitor<'tcx>, expr: &'tcx h if let hir::ExprKind::Yield(_, source) = &expr.kind { // Mark this expr's scope and all parent scopes as containing `yield`. - let mut scope = Scope { id: expr.hir_id.local_id, data: ScopeData::Node }; + let mut scope = Scope { local_id: expr.hir_id.local_id, data: ScopeData::Node }; loop { let span = match expr.kind { hir::ExprKind::Yield(expr, hir::YieldSource::Await { .. }) => { @@ -803,9 +803,9 @@ impl<'tcx> RegionResolutionVisitor<'tcx> { // account for the destruction scope representing the scope of // the destructors that run immediately after it completes. if self.terminating_scopes.contains(&id) { - self.enter_scope(Scope { id, data: ScopeData::Destruction }); + self.enter_scope(Scope { local_id: id, data: ScopeData::Destruction }); } - self.enter_scope(Scope { id, data: ScopeData::Node }); + self.enter_scope(Scope { local_id: id, data: ScopeData::Node }); } fn enter_body(&mut self, hir_id: hir::HirId, f: impl FnOnce(&mut Self)) { @@ -822,8 +822,8 @@ impl<'tcx> RegionResolutionVisitor<'tcx> { let outer_pessimistic_yield = mem::replace(&mut self.pessimistic_yield, false); self.terminating_scopes.insert(hir_id.local_id); - self.enter_scope(Scope { id: hir_id.local_id, data: ScopeData::CallSite }); - self.enter_scope(Scope { id: hir_id.local_id, data: ScopeData::Arguments }); + self.enter_scope(Scope { local_id: hir_id.local_id, data: ScopeData::CallSite }); + self.enter_scope(Scope { local_id: hir_id.local_id, data: ScopeData::Arguments }); f(self); diff --git a/compiler/rustc_middle/src/middle/region.rs b/compiler/rustc_middle/src/middle/region.rs index 114211b27c17..66861519e17c 100644 --- a/compiler/rustc_middle/src/middle/region.rs +++ b/compiler/rustc_middle/src/middle/region.rs @@ -84,23 +84,23 @@ use crate::ty::TyCtxt; #[derive(Clone, PartialEq, PartialOrd, Eq, Ord, Hash, Copy, TyEncodable, TyDecodable)] #[derive(HashStable)] pub struct Scope { - pub id: hir::ItemLocalId, + pub local_id: hir::ItemLocalId, pub data: ScopeData, } impl fmt::Debug for Scope { fn fmt(&self, fmt: &mut fmt::Formatter<'_>) -> fmt::Result { match self.data { - ScopeData::Node => write!(fmt, "Node({:?})", self.id), - ScopeData::CallSite => write!(fmt, "CallSite({:?})", self.id), - ScopeData::Arguments => write!(fmt, "Arguments({:?})", self.id), - ScopeData::Destruction => write!(fmt, "Destruction({:?})", self.id), - ScopeData::IfThen => write!(fmt, "IfThen({:?})", self.id), - ScopeData::IfThenRescope => write!(fmt, "IfThen[edition2024]({:?})", self.id), + ScopeData::Node => write!(fmt, "Node({:?})", self.local_id), + ScopeData::CallSite => write!(fmt, "CallSite({:?})", self.local_id), + ScopeData::Arguments => write!(fmt, "Arguments({:?})", self.local_id), + ScopeData::Destruction => write!(fmt, "Destruction({:?})", self.local_id), + ScopeData::IfThen => write!(fmt, "IfThen({:?})", self.local_id), + ScopeData::IfThenRescope => write!(fmt, "IfThen[edition2024]({:?})", self.local_id), ScopeData::Remainder(fsi) => write!( fmt, "Remainder {{ block: {:?}, first_statement_index: {}}}", - self.id, + self.local_id, fsi.as_u32(), ), } @@ -164,18 +164,8 @@ rustc_index::newtype_index! { rustc_data_structures::static_assert_size!(ScopeData, 4); impl Scope { - /// Returns an item-local ID associated with this scope. - /// - /// N.B., likely to be replaced as API is refined; e.g., pnkfelix - /// anticipates `fn entry_node_id` and `fn each_exit_node_id`. - pub fn item_local_id(&self) -> hir::ItemLocalId { - self.id - } - pub fn hir_id(&self, scope_tree: &ScopeTree) -> Option { - scope_tree - .root_body - .map(|hir_id| HirId { owner: hir_id.owner, local_id: self.item_local_id() }) + scope_tree.root_body.map(|hir_id| HirId { owner: hir_id.owner, local_id: self.local_id }) } /// Returns the span of this `Scope`. Note that in general the @@ -350,7 +340,7 @@ impl ScopeTree { pub fn record_var_scope(&mut self, var: hir::ItemLocalId, lifetime: Scope) { debug!("record_var_scope(sub={:?}, sup={:?})", var, lifetime); - assert!(var != lifetime.item_local_id()); + assert!(var != lifetime.local_id); self.var_map.insert(var, lifetime); } @@ -359,7 +349,7 @@ impl ScopeTree { match &candidate_type { RvalueCandidateType::Borrow { lifetime: Some(lifetime), .. } | RvalueCandidateType::Pattern { lifetime: Some(lifetime), .. } => { - assert!(var.local_id != lifetime.item_local_id()) + assert!(var.local_id != lifetime.local_id) } _ => {} } diff --git a/compiler/rustc_middle/src/ty/rvalue_scopes.rs b/compiler/rustc_middle/src/ty/rvalue_scopes.rs index 57c2d7623d2d..b00c8169a36a 100644 --- a/compiler/rustc_middle/src/ty/rvalue_scopes.rs +++ b/compiler/rustc_middle/src/ty/rvalue_scopes.rs @@ -35,7 +35,7 @@ impl RvalueScopes { // if there's one. Static items, for instance, won't // have an enclosing scope, hence no scope will be // returned. - let mut id = Scope { id: expr_id, data: ScopeData::Node }; + let mut id = Scope { local_id: expr_id, data: ScopeData::Node }; let mut backwards_incompatible = None; while let Some(&(p, _)) = region_scope_tree.parent_map.get(&id) { @@ -60,7 +60,7 @@ impl RvalueScopes { if backwards_incompatible.is_none() { backwards_incompatible = region_scope_tree .backwards_incompatible_scope - .get(&p.item_local_id()) + .get(&p.local_id) .copied(); } id = p @@ -76,7 +76,7 @@ impl RvalueScopes { pub fn record_rvalue_scope(&mut self, var: hir::ItemLocalId, lifetime: Option) { debug!("record_rvalue_scope(var={var:?}, lifetime={lifetime:?})"); if let Some(lifetime) = lifetime { - assert!(var != lifetime.item_local_id()); + assert!(var != lifetime.local_id); } self.map.insert(var, lifetime); } diff --git a/compiler/rustc_mir_build/src/builder/expr/as_temp.rs b/compiler/rustc_mir_build/src/builder/expr/as_temp.rs index 5e3a24e18fb1..2927f5b0c45d 100644 --- a/compiler/rustc_mir_build/src/builder/expr/as_temp.rs +++ b/compiler/rustc_mir_build/src/builder/expr/as_temp.rs @@ -75,11 +75,11 @@ impl<'a, 'tcx> Builder<'a, 'tcx> { LocalInfo::BlockTailTemp(tail_info) } - _ if let Some(Scope { data: ScopeData::IfThenRescope, id }) = + _ if let Some(Scope { data: ScopeData::IfThenRescope, local_id }) = temp_lifetime.temp_lifetime => { LocalInfo::IfThenRescopeTemp { - if_then: HirId { owner: this.hir_id.owner, local_id: id }, + if_then: HirId { owner: this.hir_id.owner, local_id }, } } diff --git a/compiler/rustc_mir_build/src/builder/mod.rs b/compiler/rustc_mir_build/src/builder/mod.rs index fdd951c88990..0a60899248ac 100644 --- a/compiler/rustc_mir_build/src/builder/mod.rs +++ b/compiler/rustc_mir_build/src/builder/mod.rs @@ -531,9 +531,9 @@ fn construct_fn<'tcx>( ); let call_site_scope = - region::Scope { id: body.id().hir_id.local_id, data: region::ScopeData::CallSite }; + region::Scope { local_id: body.id().hir_id.local_id, data: region::ScopeData::CallSite }; let arg_scope = - region::Scope { id: body.id().hir_id.local_id, data: region::ScopeData::Arguments }; + region::Scope { local_id: body.id().hir_id.local_id, data: region::ScopeData::Arguments }; let source_info = builder.source_info(span); let call_site_s = (call_site_scope, source_info); let _: BlockAnd<()> = builder.in_scope(call_site_s, LintLevel::Inherited, |builder| { diff --git a/compiler/rustc_mir_build/src/builder/scope.rs b/compiler/rustc_mir_build/src/builder/scope.rs index 67a0c9c79350..d0febcca4517 100644 --- a/compiler/rustc_mir_build/src/builder/scope.rs +++ b/compiler/rustc_mir_build/src/builder/scope.rs @@ -89,7 +89,7 @@ use rustc_index::{IndexSlice, IndexVec}; use rustc_middle::middle::region; use rustc_middle::mir::*; use rustc_middle::thir::{ExprId, LintLevel}; -use rustc_middle::{bug, span_bug, ty}; +use rustc_middle::{bug, span_bug}; use rustc_session::lint::Level; use rustc_span::source_map::Spanned; use rustc_span::{DUMMY_SP, Span}; diff --git a/compiler/rustc_mir_build/src/thir/cx/block.rs b/compiler/rustc_mir_build/src/thir/cx/block.rs index 069c2e7881ea..c9df027687ab 100644 --- a/compiler/rustc_mir_build/src/thir/cx/block.rs +++ b/compiler/rustc_mir_build/src/thir/cx/block.rs @@ -16,7 +16,7 @@ impl<'tcx> Cx<'tcx> { let block = Block { targeted_by_break: block.targeted_by_break, region_scope: region::Scope { - id: block.hir_id.local_id, + local_id: block.hir_id.local_id, data: region::ScopeData::Node, }, span: block.span, @@ -51,7 +51,7 @@ impl<'tcx> Cx<'tcx> { let stmt = Stmt { kind: StmtKind::Expr { scope: region::Scope { - id: hir_id.local_id, + local_id: hir_id.local_id, data: region::ScopeData::Node, }, expr: self.mirror_expr(expr), @@ -65,7 +65,7 @@ impl<'tcx> Cx<'tcx> { } hir::StmtKind::Let(local) => { let remainder_scope = region::Scope { - id: block_id, + local_id: block_id, data: region::ScopeData::Remainder(region::FirstStatementIndex::new( index, )), @@ -108,7 +108,7 @@ impl<'tcx> Cx<'tcx> { kind: StmtKind::Let { remainder_scope, init_scope: region::Scope { - id: hir_id.local_id, + local_id: hir_id.local_id, data: region::ScopeData::Node, }, pattern, diff --git a/compiler/rustc_mir_build/src/thir/cx/expr.rs b/compiler/rustc_mir_build/src/thir/cx/expr.rs index ae49b2661537..0338ac674e5e 100644 --- a/compiler/rustc_mir_build/src/thir/cx/expr.rs +++ b/compiler/rustc_mir_build/src/thir/cx/expr.rs @@ -45,7 +45,7 @@ impl<'tcx> Cx<'tcx> { #[instrument(level = "trace", skip(self, hir_expr))] pub(super) fn mirror_expr_inner(&mut self, hir_expr: &'tcx hir::Expr<'tcx>) -> ExprId { let expr_scope = - region::Scope { id: hir_expr.hir_id.local_id, data: region::ScopeData::Node }; + region::Scope { local_id: hir_expr.hir_id.local_id, data: region::ScopeData::Node }; trace!(?hir_expr.hir_id, ?hir_expr.span); @@ -814,14 +814,20 @@ impl<'tcx> Cx<'tcx> { hir::ExprKind::Become(call) => ExprKind::Become { value: self.mirror_expr(call) }, hir::ExprKind::Break(dest, ref value) => match dest.target_id { Ok(target_id) => ExprKind::Break { - label: region::Scope { id: target_id.local_id, data: region::ScopeData::Node }, + label: region::Scope { + local_id: target_id.local_id, + data: region::ScopeData::Node, + }, value: value.map(|value| self.mirror_expr(value)), }, Err(err) => bug!("invalid loop id for break: {}", err), }, hir::ExprKind::Continue(dest) => match dest.target_id { Ok(loop_id) => ExprKind::Continue { - label: region::Scope { id: loop_id.local_id, data: region::ScopeData::Node }, + label: region::Scope { + local_id: loop_id.local_id, + data: region::ScopeData::Node, + }, }, Err(err) => bug!("invalid loop id for continue: {}", err), }, @@ -831,7 +837,7 @@ impl<'tcx> Cx<'tcx> { }, hir::ExprKind::If(cond, then, else_opt) => ExprKind::If { if_then_scope: region::Scope { - id: then.hir_id.local_id, + local_id: then.hir_id.local_id, data: { if expr.span.at_least_rust_2024() { region::ScopeData::IfThenRescope @@ -1021,7 +1027,7 @@ impl<'tcx> Cx<'tcx> { guard: arm.guard.as_ref().map(|g| self.mirror_expr(g)), body: self.mirror_expr(arm.body), lint_level: LintLevel::Explicit(arm.hir_id), - scope: region::Scope { id: arm.hir_id.local_id, data: region::ScopeData::Node }, + scope: region::Scope { local_id: arm.hir_id.local_id, data: region::ScopeData::Node }, span: arm.span, }; self.thir.arms.push(arm) From 48f7714819525ec5b361ea480eaecea61620a56b Mon Sep 17 00:00:00 2001 From: Nicholas Nethercote Date: Tue, 3 Dec 2024 20:09:29 +1100 Subject: [PATCH 76/92] Rename `Parser::expected_tokens` as `Parser::expected_token_types`. Because the `Token` type is similar to but different to the `TokenType` type, and the difference is important, so we want to avoid confusion. --- compiler/rustc_builtin_macros/src/format.rs | 2 +- .../rustc_parse/src/parser/diagnostics.rs | 19 ++++++++-------- compiler/rustc_parse/src/parser/expr.rs | 2 +- compiler/rustc_parse/src/parser/item.rs | 2 +- compiler/rustc_parse/src/parser/mod.rs | 22 +++++++++---------- compiler/rustc_parse/src/parser/path.rs | 2 +- compiler/rustc_parse/src/parser/ty.rs | 2 +- 7 files changed, 26 insertions(+), 25 deletions(-) diff --git a/compiler/rustc_builtin_macros/src/format.rs b/compiler/rustc_builtin_macros/src/format.rs index 73d762d21e51..df3750049b71 100644 --- a/compiler/rustc_builtin_macros/src/format.rs +++ b/compiler/rustc_builtin_macros/src/format.rs @@ -95,7 +95,7 @@ fn parse_args<'a>(ecx: &ExtCtxt<'a>, sp: Span, tts: TokenStream) -> PResult<'a, while p.token != token::Eof { if !p.eat(&token::Comma) { if first { - p.clear_expected_tokens(); + p.clear_expected_token_types(); } match p.expect(&token::Comma) { diff --git a/compiler/rustc_parse/src/parser/diagnostics.rs b/compiler/rustc_parse/src/parser/diagnostics.rs index 8417701ac0cd..938c1e2abb80 100644 --- a/compiler/rustc_parse/src/parser/diagnostics.rs +++ b/compiler/rustc_parse/src/parser/diagnostics.rs @@ -483,9 +483,10 @@ impl<'a> Parser<'a> { }) } - self.expected_tokens.extend(edible.iter().chain(inedible).cloned().map(TokenType::Token)); + self.expected_token_types + .extend(edible.iter().chain(inedible).cloned().map(TokenType::Token)); let mut expected = self - .expected_tokens + .expected_token_types .iter() .filter(|token| { // Filter out suggestions that suggest the same token which was found and deemed incorrect. @@ -785,17 +786,17 @@ impl<'a> Parser<'a> { let Some((curr_ident, _)) = self.token.ident() else { return; }; - let expected_tokens: &[TokenType] = + let expected_token_types: &[TokenType] = expected.len().checked_sub(10).map_or(&expected, |index| &expected[index..]); - let expected_keywords: Vec = expected_tokens + let expected_keywords: Vec = expected_token_types .iter() .filter_map(|token| if let TokenType::Keyword(kw) = token { Some(*kw) } else { None }) .collect(); - // When there are a few keywords in the last ten elements of `self.expected_tokens` and the current - // token is an identifier, it's probably a misspelled keyword. - // This handles code like `async Move {}`, misspelled `if` in match guard, misspelled `else` in `if`-`else` - // and mispelled `where` in a where clause. + // When there are a few keywords in the last ten elements of `self.expected_token_types` + // and the current token is an identifier, it's probably a misspelled keyword. This handles + // code like `async Move {}`, misspelled `if` in match guard, misspelled `else` in + // `if`-`else` and mispelled `where` in a where clause. if !expected_keywords.is_empty() && !curr_ident.is_used_keyword() && let Some(misspelled_kw) = find_similar_kw(curr_ident, &expected_keywords) @@ -3016,7 +3017,7 @@ impl<'a> Parser<'a> { /// Check for exclusive ranges written as `..<` pub(crate) fn maybe_err_dotdotlt_syntax(&self, maybe_lt: Token, mut err: Diag<'a>) -> Diag<'a> { if maybe_lt == token::Lt - && (self.expected_tokens.contains(&TokenType::Token(token::Gt)) + && (self.expected_token_types.contains(&TokenType::Token(token::Gt)) || matches!(self.token.kind, token::Literal(..))) { err.span_suggestion( diff --git a/compiler/rustc_parse/src/parser/expr.rs b/compiler/rustc_parse/src/parser/expr.rs index 2f34dcb93083..1e84b2a0cf8e 100644 --- a/compiler/rustc_parse/src/parser/expr.rs +++ b/compiler/rustc_parse/src/parser/expr.rs @@ -153,7 +153,7 @@ impl<'a> Parser<'a> { return Ok((lhs, parsed_something)); } - self.expected_tokens.push(TokenType::Operator); + self.expected_token_types.push(TokenType::Operator); while let Some(op) = self.check_assoc_op() { let lhs_span = self.interpolated_or_expr_span(&lhs); let cur_op_span = self.token.span; diff --git a/compiler/rustc_parse/src/parser/item.rs b/compiler/rustc_parse/src/parser/item.rs index e6a8eda42e8d..58fc90f3939d 100644 --- a/compiler/rustc_parse/src/parser/item.rs +++ b/compiler/rustc_parse/src/parser/item.rs @@ -2630,7 +2630,7 @@ impl<'a> Parser<'a> { if !self.eat_keyword_case(kw::Fn, case) { // It is possible for `expect_one_of` to recover given the contents of - // `self.expected_tokens`, therefore, do not use `self.unexpected()` which doesn't + // `self.expected_token_types`, therefore, do not use `self.unexpected()` which doesn't // account for this. match self.expect_one_of(&[], &[]) { Ok(Recovered::Yes(_)) => {} diff --git a/compiler/rustc_parse/src/parser/mod.rs b/compiler/rustc_parse/src/parser/mod.rs index 4bc8f5913b2b..d41c6c2cd1c9 100644 --- a/compiler/rustc_parse/src/parser/mod.rs +++ b/compiler/rustc_parse/src/parser/mod.rs @@ -141,7 +141,7 @@ pub struct Parser<'a> { pub prev_token: Token, pub capture_cfg: bool, restrictions: Restrictions, - expected_tokens: Vec, + expected_token_types: Vec, token_cursor: TokenCursor, // The number of calls to `bump`, i.e. the position in the token stream. num_bump_calls: u32, @@ -490,7 +490,7 @@ impl<'a> Parser<'a> { prev_token: Token::dummy(), capture_cfg: false, restrictions: Restrictions::empty(), - expected_tokens: Vec::new(), + expected_token_types: Vec::new(), token_cursor: TokenCursor { curr: TokenTreeCursor::new(stream), stack: Vec::new() }, num_bump_calls: 0, break_last_token: 0, @@ -554,7 +554,7 @@ impl<'a> Parser<'a> { /// Expects and consumes the token `t`. Signals an error if the next token is not `t`. pub fn expect(&mut self, t: &TokenKind) -> PResult<'a, Recovered> { - if self.expected_tokens.is_empty() { + if self.expected_token_types.is_empty() { if self.token == *t { self.bump(); Ok(Recovered::No) @@ -619,13 +619,13 @@ impl<'a> Parser<'a> { /// Checks if the next token is `tok`, and returns `true` if so. /// - /// This method will automatically add `tok` to `expected_tokens` if `tok` is not + /// This method will automatically add `tok` to `expected_token_types` if `tok` is not /// encountered. #[inline] fn check(&mut self, tok: &TokenKind) -> bool { let is_present = self.token == *tok; if !is_present { - self.expected_tokens.push(TokenType::Token(tok.clone())); + self.expected_token_types.push(TokenType::Token(tok.clone())); } is_present } @@ -666,7 +666,7 @@ impl<'a> Parser<'a> { #[inline] #[must_use] fn check_keyword(&mut self, kw: Symbol) -> bool { - self.expected_tokens.push(TokenType::Keyword(kw)); + self.expected_token_types.push(TokenType::Keyword(kw)); self.token.is_keyword(kw) } @@ -755,7 +755,7 @@ impl<'a> Parser<'a> { if ok { true } else { - self.expected_tokens.push(typ); + self.expected_token_types.push(typ); false } } @@ -832,7 +832,7 @@ impl<'a> Parser<'a> { true } _ => { - self.expected_tokens.push(TokenType::Token(expected)); + self.expected_token_types.push(TokenType::Token(expected)); false } } @@ -1180,7 +1180,7 @@ impl<'a> Parser<'a> { self.token_spacing = next_spacing; // Diagnostics. - self.expected_tokens.clear(); + self.expected_token_types.clear(); } /// Advance the parser by one token. @@ -1670,8 +1670,8 @@ impl<'a> Parser<'a> { DebugParser { parser: self, lookahead } } - pub fn clear_expected_tokens(&mut self) { - self.expected_tokens.clear(); + pub fn clear_expected_token_types(&mut self) { + self.expected_token_types.clear(); } pub fn approx_token_stream_pos(&self) -> u32 { diff --git a/compiler/rustc_parse/src/parser/path.rs b/compiler/rustc_parse/src/parser/path.rs index f2f0c6dfad56..3505ec88d044 100644 --- a/compiler/rustc_parse/src/parser/path.rs +++ b/compiler/rustc_parse/src/parser/path.rs @@ -300,7 +300,7 @@ impl<'a> Parser<'a> { ) }; let check_args_start = |this: &mut Self| { - this.expected_tokens.extend_from_slice(&[ + this.expected_token_types.extend_from_slice(&[ TokenType::Token(token::Lt), TokenType::Token(token::OpenDelim(Delimiter::Parenthesis)), ]); diff --git a/compiler/rustc_parse/src/parser/ty.rs b/compiler/rustc_parse/src/parser/ty.rs index 6e720db4edf7..e4f67d97aa50 100644 --- a/compiler/rustc_parse/src/parser/ty.rs +++ b/compiler/rustc_parse/src/parser/ty.rs @@ -1280,7 +1280,7 @@ impl<'a> Parser<'a> { } pub(super) fn check_lifetime(&mut self) -> bool { - self.expected_tokens.push(TokenType::Lifetime); + self.expected_token_types.push(TokenType::Lifetime); self.token.is_lifetime() } From fb5ba8a6d49d1ed46cfdaa12ac6ee7002eb7d8fd Mon Sep 17 00:00:00 2001 From: Nicholas Nethercote Date: Wed, 4 Dec 2024 15:36:49 +1100 Subject: [PATCH 77/92] Tweak some parser `check`/`eat` methods. The most significant is `check_keyword`: it now only pushes to `expected_token_types` if the keyword check fails, which matches how all the other `check` methods work. The remainder are just tweaks to make these methods more consistent with each other. --- compiler/rustc_parse/src/parser/mod.rs | 45 ++++++++++++-------------- 1 file changed, 20 insertions(+), 25 deletions(-) diff --git a/compiler/rustc_parse/src/parser/mod.rs b/compiler/rustc_parse/src/parser/mod.rs index d41c6c2cd1c9..0ee3e2bfb0d3 100644 --- a/compiler/rustc_parse/src/parser/mod.rs +++ b/compiler/rustc_parse/src/parser/mod.rs @@ -666,19 +666,20 @@ impl<'a> Parser<'a> { #[inline] #[must_use] fn check_keyword(&mut self, kw: Symbol) -> bool { - self.expected_token_types.push(TokenType::Keyword(kw)); - self.token.is_keyword(kw) + let is_keyword = self.token.is_keyword(kw); + if !is_keyword { + self.expected_token_types.push(TokenType::Keyword(kw)); + } + is_keyword } #[inline] #[must_use] fn check_keyword_case(&mut self, kw: Symbol, case: Case) -> bool { if self.check_keyword(kw) { - return true; - } - + true // Do an ASCII case-insensitive match, because all keywords are ASCII. - if case == Case::Insensitive + } else if case == Case::Insensitive && let Some((ident, IdentIsRaw::No)) = self.token.ident() && ident.as_str().eq_ignore_ascii_case(kw.as_str()) { @@ -694,12 +695,11 @@ impl<'a> Parser<'a> { #[inline] #[must_use] pub fn eat_keyword(&mut self, kw: Symbol) -> bool { - if self.check_keyword(kw) { + let is_keyword = self.check_keyword(kw); + if is_keyword { self.bump(); - true - } else { - false } + is_keyword } /// Eats a keyword, optionally ignoring the case. @@ -709,19 +709,17 @@ impl<'a> Parser<'a> { #[must_use] fn eat_keyword_case(&mut self, kw: Symbol, case: Case) -> bool { if self.eat_keyword(kw) { - return true; - } - - if case == Case::Insensitive + true + } else if case == Case::Insensitive && let Some((ident, IdentIsRaw::No)) = self.token.ident() && ident.as_str().to_lowercase() == kw.as_str().to_lowercase() { self.dcx().emit_err(errors::KwBadCase { span: ident.span, kw: kw.as_str() }); self.bump(); - return true; + true + } else { + false } - - false } /// If the next token is the given keyword, eats it and returns `true`. @@ -730,12 +728,11 @@ impl<'a> Parser<'a> { #[inline] #[must_use] pub fn eat_keyword_noexpect(&mut self, kw: Symbol) -> bool { - if self.token.is_keyword(kw) { + let is_keyword = self.token.is_keyword(kw); + if is_keyword { self.bump(); - true - } else { - false } + is_keyword } /// If the given word is not a keyword, signals an error. @@ -752,12 +749,10 @@ impl<'a> Parser<'a> { #[inline] fn check_or_expected(&mut self, ok: bool, typ: TokenType) -> bool { - if ok { - true - } else { + if !ok { self.expected_token_types.push(typ); - false } + ok } fn check_ident(&mut self) -> bool { From d5370d981f58ebadf575f075a6f0d8c35bc704e8 Mon Sep 17 00:00:00 2001 From: Nicholas Nethercote Date: Wed, 4 Dec 2024 15:50:46 +1100 Subject: [PATCH 78/92] Remove `bra`/`ket` naming. This is a naming convention used in a handful of spots in the parser for delimiters. It confused me when I first saw it a long time ago, and I've never liked it. A web search says "Bra-ket notation" exists in linear algebra but the terminology has zero prior use in a programming context, as far as I can tell. This commit changes it to `open`/`close`, which is consistent with the rest of the compiler. --- .../rustc_parse/src/parser/diagnostics.rs | 8 ++-- compiler/rustc_parse/src/parser/mod.rs | 40 +++++++++---------- 2 files changed, 24 insertions(+), 24 deletions(-) diff --git a/compiler/rustc_parse/src/parser/diagnostics.rs b/compiler/rustc_parse/src/parser/diagnostics.rs index 938c1e2abb80..1a8f8f6069aa 100644 --- a/compiler/rustc_parse/src/parser/diagnostics.rs +++ b/compiler/rustc_parse/src/parser/diagnostics.rs @@ -1125,11 +1125,11 @@ impl<'a> Parser<'a> { Ok(self.mk_expr_err(lo.to(self.token.span), guar)) } - /// Eats and discards tokens until one of `kets` is encountered. Respects token trees, + /// Eats and discards tokens until one of `closes` is encountered. Respects token trees, /// passes through any errors encountered. Used for error recovery. - pub(super) fn eat_to_tokens(&mut self, kets: &[&TokenKind]) { - if let Err(err) = - self.parse_seq_to_before_tokens(kets, &[], SeqSep::none(), |p| Ok(p.parse_token_tree())) + pub(super) fn eat_to_tokens(&mut self, closes: &[&TokenKind]) { + if let Err(err) = self + .parse_seq_to_before_tokens(closes, &[], SeqSep::none(), |p| Ok(p.parse_token_tree())) { err.cancel(); } diff --git a/compiler/rustc_parse/src/parser/mod.rs b/compiler/rustc_parse/src/parser/mod.rs index 0ee3e2bfb0d3..3e82a9cf1bb3 100644 --- a/compiler/rustc_parse/src/parser/mod.rs +++ b/compiler/rustc_parse/src/parser/mod.rs @@ -882,14 +882,14 @@ impl<'a> Parser<'a> { } } - /// Checks if the next token is contained within `kets`, and returns `true` if so. + /// Checks if the next token is contained within `closes`, and returns `true` if so. fn expect_any_with_type( &mut self, - kets_expected: &[&TokenKind], - kets_not_expected: &[&TokenKind], + closes_expected: &[&TokenKind], + closes_not_expected: &[&TokenKind], ) -> bool { - kets_expected.iter().any(|k| self.check(k)) - || kets_not_expected.iter().any(|k| self.check_noexpect(k)) + closes_expected.iter().any(|k| self.check(k)) + || closes_not_expected.iter().any(|k| self.check_noexpect(k)) } /// Parses a sequence until the specified delimiters. The function @@ -897,8 +897,8 @@ impl<'a> Parser<'a> { /// closing bracket. fn parse_seq_to_before_tokens( &mut self, - kets_expected: &[&TokenKind], - kets_not_expected: &[&TokenKind], + closes_expected: &[&TokenKind], + closes_not_expected: &[&TokenKind], sep: SeqSep, mut f: impl FnMut(&mut Parser<'a>) -> PResult<'a, T>, ) -> PResult<'a, (ThinVec, Trailing, Recovered)> { @@ -907,7 +907,7 @@ impl<'a> Parser<'a> { let mut trailing = Trailing::No; let mut v = ThinVec::new(); - while !self.expect_any_with_type(kets_expected, kets_not_expected) { + while !self.expect_any_with_type(closes_expected, closes_not_expected) { if let token::CloseDelim(..) | token::Eof = self.token.kind { break; } @@ -1006,7 +1006,7 @@ impl<'a> Parser<'a> { // we will try to recover in `maybe_recover_struct_lit_bad_delims` return Err(expect_err); } else if let [token::CloseDelim(Delimiter::Parenthesis)] = - kets_expected + closes_expected { return Err(expect_err); } else { @@ -1020,7 +1020,7 @@ impl<'a> Parser<'a> { } } if sep.trailing_sep_allowed - && self.expect_any_with_type(kets_expected, kets_not_expected) + && self.expect_any_with_type(closes_expected, closes_not_expected) { trailing = Trailing::Yes; break; @@ -1096,11 +1096,11 @@ impl<'a> Parser<'a> { /// closing bracket. fn parse_seq_to_before_end( &mut self, - ket: &TokenKind, + close: &TokenKind, sep: SeqSep, f: impl FnMut(&mut Parser<'a>) -> PResult<'a, T>, ) -> PResult<'a, (ThinVec, Trailing, Recovered)> { - self.parse_seq_to_before_tokens(&[ket], &[], sep, f) + self.parse_seq_to_before_tokens(&[close], &[], sep, f) } /// Parses a sequence, including only the closing delimiter. The function @@ -1108,15 +1108,15 @@ impl<'a> Parser<'a> { /// closing bracket. fn parse_seq_to_end( &mut self, - ket: &TokenKind, + close: &TokenKind, sep: SeqSep, f: impl FnMut(&mut Parser<'a>) -> PResult<'a, T>, ) -> PResult<'a, (ThinVec, Trailing)> { - let (val, trailing, recovered) = self.parse_seq_to_before_end(ket, sep, f)?; - if matches!(recovered, Recovered::No) && !self.eat(ket) { + let (val, trailing, recovered) = self.parse_seq_to_before_end(close, sep, f)?; + if matches!(recovered, Recovered::No) && !self.eat(close) { self.dcx().span_delayed_bug( self.token.span, - "recovered but `parse_seq_to_before_end` did not give us the ket token", + "recovered but `parse_seq_to_before_end` did not give us the close token", ); } Ok((val, trailing)) @@ -1127,13 +1127,13 @@ impl<'a> Parser<'a> { /// closing bracket. fn parse_unspanned_seq( &mut self, - bra: &TokenKind, - ket: &TokenKind, + open: &TokenKind, + close: &TokenKind, sep: SeqSep, f: impl FnMut(&mut Parser<'a>) -> PResult<'a, T>, ) -> PResult<'a, (ThinVec, Trailing)> { - self.expect(bra)?; - self.parse_seq_to_end(ket, sep, f) + self.expect(open)?; + self.parse_seq_to_end(close, sep, f) } /// Parses a comma-separated sequence, including both delimiters. From b9bf0b4b10148aa914243a527d9010aba9b7b827 Mon Sep 17 00:00:00 2001 From: Nicholas Nethercote Date: Wed, 4 Dec 2024 15:55:06 +1100 Subject: [PATCH 79/92] Speed up `Parser::expected_token_types`. The parser pushes a `TokenType` to `Parser::expected_token_types` on every call to the various `check`/`eat` methods, and clears it on every call to `bump`. Some of those `TokenType` values are full tokens that require cloning and dropping. This is a *lot* of work for something that is only used in error messages and it accounts for a significant fraction of parsing execution time. This commit overhauls `TokenType` so that `Parser::expected_token_types` can be implemented as a bitset. This requires changing `TokenType` to a C-style parameterless enum, and adding `TokenTypeSet` which uses a `u128` for the bits. (The new `TokenType` has 105 variants.) The new types `ExpTokenPair` and `ExpKeywordPair` are now arguments to the `check`/`eat` methods. This is for maximum speed. The elements in the pairs are always statically known; e.g. a `token::BinOp(token::Star)` is always paired with a `TokenType::Star`. So we now compute `TokenType`s in advance and pass them in to `check`/`eat` rather than the current approach of constructing them on insertion into `expected_token_types`. Values of these pair types can be produced by the new `exp!` macro, which is used at every `check`/`eat` call site. The macro is for convenience, allowing any pair to be generated from a single identifier. The ident/keyword filtering in `expected_one_of_not_found` is no longer necessary. It was there to account for some sloppiness in `TokenKind`/`TokenType` comparisons. The existing `TokenType` is moved to a new file `token_type.rs`, and all its new infrastructure is added to that file. There is more boilerplate code than I would like, but I can't see how to make it shorter. --- compiler/rustc_builtin_macros/src/asm.rs | 110 ++-- compiler/rustc_builtin_macros/src/assert.rs | 3 +- compiler/rustc_builtin_macros/src/cfg.rs | 5 +- compiler/rustc_builtin_macros/src/format.rs | 7 +- .../rustc_builtin_macros/src/pattern_type.rs | 5 +- compiler/rustc_builtin_macros/src/util.rs | 6 +- compiler/rustc_expand/src/module.rs | 6 +- .../rustc_expand/src/proc_macro_server.rs | 4 +- compiler/rustc_parse/src/parser/attr.rs | 41 +- .../rustc_parse/src/parser/diagnostics.rs | 139 ++-- compiler/rustc_parse/src/parser/expr.rs | 308 +++++---- compiler/rustc_parse/src/parser/generics.rs | 33 +- compiler/rustc_parse/src/parser/item.rs | 374 ++++++----- compiler/rustc_parse/src/parser/mod.rs | 226 +++---- compiler/rustc_parse/src/parser/pat.rs | 77 +-- compiler/rustc_parse/src/parser/path.rs | 34 +- compiler/rustc_parse/src/parser/stmt.rs | 27 +- compiler/rustc_parse/src/parser/token_type.rs | 620 ++++++++++++++++++ compiler/rustc_parse/src/parser/ty.rs | 92 +-- src/tools/rustfmt/src/parse/macros/cfg_if.rs | 11 +- .../rustfmt/src/parse/macros/lazy_static.rs | 17 +- src/tools/rustfmt/src/parse/parser.rs | 5 +- 22 files changed, 1357 insertions(+), 793 deletions(-) create mode 100644 compiler/rustc_parse/src/parser/token_type.rs diff --git a/compiler/rustc_builtin_macros/src/asm.rs b/compiler/rustc_builtin_macros/src/asm.rs index cce70fb2ea4b..6ae697d4030d 100644 --- a/compiler/rustc_builtin_macros/src/asm.rs +++ b/compiler/rustc_builtin_macros/src/asm.rs @@ -1,16 +1,16 @@ use ast::token::IdentIsRaw; use lint::BuiltinLintDiag; -use rustc_ast::AsmMacro; use rustc_ast::ptr::P; -use rustc_ast::token::{self, Delimiter}; use rustc_ast::tokenstream::TokenStream; +use rustc_ast::{AsmMacro, token}; use rustc_data_structures::fx::{FxHashMap, FxIndexMap}; use rustc_errors::PResult; use rustc_expand::base::*; use rustc_index::bit_set::GrowableBitSet; -use rustc_parse::parser::Parser; +use rustc_parse::exp; +use rustc_parse::parser::{ExpKeywordPair, Parser}; use rustc_session::lint; -use rustc_span::{ErrorGuaranteed, Ident, InnerSpan, Span, Symbol, kw, sym}; +use rustc_span::{ErrorGuaranteed, Ident, InnerSpan, Span, Symbol, kw}; use rustc_target::asm::InlineAsmArch; use smallvec::smallvec; use {rustc_ast as ast, rustc_parse_format as parse}; @@ -38,16 +38,16 @@ pub struct AsmArgs { /// - `Err(_)` if the current token matches the keyword, but was not expected fn eat_operand_keyword<'a>( p: &mut Parser<'a>, - symbol: Symbol, + exp: ExpKeywordPair, asm_macro: AsmMacro, ) -> PResult<'a, bool> { if matches!(asm_macro, AsmMacro::Asm) { - Ok(p.eat_keyword(symbol)) + Ok(p.eat_keyword(exp)) } else { let span = p.token.span; - if p.eat_keyword_noexpect(symbol) { + if p.eat_keyword_noexpect(exp.kw) { // in gets printed as `r#in` otherwise - let symbol = if symbol == kw::In { "in" } else { symbol.as_str() }; + let symbol = if exp.kw == kw::In { "in" } else { exp.kw.as_str() }; Err(p.dcx().create_err(errors::AsmUnsupportedOperand { span, symbol, @@ -95,13 +95,13 @@ pub fn parse_asm_args<'a>( let mut allow_templates = true; while p.token != token::Eof { - if !p.eat(&token::Comma) { + if !p.eat(exp!(Comma)) { if allow_templates { // After a template string, we always expect *only* a comma... return Err(dcx.create_err(errors::AsmExpectedComma { span: p.token.span })); } else { // ...after that delegate to `expect` to also include the other expected tokens. - return Err(p.expect(&token::Comma).err().unwrap()); + return Err(p.expect(exp!(Comma)).err().unwrap()); } } if p.token == token::Eof { @@ -109,14 +109,14 @@ pub fn parse_asm_args<'a>( } // accept trailing commas // Parse clobber_abi - if p.eat_keyword(sym::clobber_abi) { + if p.eat_keyword(exp!(ClobberAbi)) { parse_clobber_abi(p, &mut args)?; allow_templates = false; continue; } // Parse options - if p.eat_keyword(sym::options) { + if p.eat_keyword(exp!(Options)) { parse_options(p, &mut args, asm_macro)?; allow_templates = false; continue; @@ -128,7 +128,7 @@ pub fn parse_asm_args<'a>( let name = if p.token.is_ident() && p.look_ahead(1, |t| *t == token::Eq) { let (ident, _) = p.token.ident().unwrap(); p.bump(); - p.expect(&token::Eq)?; + p.expect(exp!(Eq))?; allow_templates = false; Some(ident.name) } else { @@ -136,57 +136,57 @@ pub fn parse_asm_args<'a>( }; let mut explicit_reg = false; - let op = if eat_operand_keyword(p, kw::In, asm_macro)? { + let op = if eat_operand_keyword(p, exp!(In), asm_macro)? { let reg = parse_reg(p, &mut explicit_reg)?; - if p.eat_keyword(kw::Underscore) { + if p.eat_keyword(exp!(Underscore)) { let err = dcx.create_err(errors::AsmUnderscoreInput { span: p.token.span }); return Err(err); } let expr = p.parse_expr()?; ast::InlineAsmOperand::In { reg, expr } - } else if eat_operand_keyword(p, sym::out, asm_macro)? { + } else if eat_operand_keyword(p, exp!(Out), asm_macro)? { let reg = parse_reg(p, &mut explicit_reg)?; - let expr = if p.eat_keyword(kw::Underscore) { None } else { Some(p.parse_expr()?) }; + let expr = if p.eat_keyword(exp!(Underscore)) { None } else { Some(p.parse_expr()?) }; ast::InlineAsmOperand::Out { reg, expr, late: false } - } else if eat_operand_keyword(p, sym::lateout, asm_macro)? { + } else if eat_operand_keyword(p, exp!(Lateout), asm_macro)? { let reg = parse_reg(p, &mut explicit_reg)?; - let expr = if p.eat_keyword(kw::Underscore) { None } else { Some(p.parse_expr()?) }; + let expr = if p.eat_keyword(exp!(Underscore)) { None } else { Some(p.parse_expr()?) }; ast::InlineAsmOperand::Out { reg, expr, late: true } - } else if eat_operand_keyword(p, sym::inout, asm_macro)? { + } else if eat_operand_keyword(p, exp!(Inout), asm_macro)? { let reg = parse_reg(p, &mut explicit_reg)?; - if p.eat_keyword(kw::Underscore) { + if p.eat_keyword(exp!(Underscore)) { let err = dcx.create_err(errors::AsmUnderscoreInput { span: p.token.span }); return Err(err); } let expr = p.parse_expr()?; - if p.eat(&token::FatArrow) { + if p.eat(exp!(FatArrow)) { let out_expr = - if p.eat_keyword(kw::Underscore) { None } else { Some(p.parse_expr()?) }; + if p.eat_keyword(exp!(Underscore)) { None } else { Some(p.parse_expr()?) }; ast::InlineAsmOperand::SplitInOut { reg, in_expr: expr, out_expr, late: false } } else { ast::InlineAsmOperand::InOut { reg, expr, late: false } } - } else if eat_operand_keyword(p, sym::inlateout, asm_macro)? { + } else if eat_operand_keyword(p, exp!(Inlateout), asm_macro)? { let reg = parse_reg(p, &mut explicit_reg)?; - if p.eat_keyword(kw::Underscore) { + if p.eat_keyword(exp!(Underscore)) { let err = dcx.create_err(errors::AsmUnderscoreInput { span: p.token.span }); return Err(err); } let expr = p.parse_expr()?; - if p.eat(&token::FatArrow) { + if p.eat(exp!(FatArrow)) { let out_expr = - if p.eat_keyword(kw::Underscore) { None } else { Some(p.parse_expr()?) }; + if p.eat_keyword(exp!(Underscore)) { None } else { Some(p.parse_expr()?) }; ast::InlineAsmOperand::SplitInOut { reg, in_expr: expr, out_expr, late: true } } else { ast::InlineAsmOperand::InOut { reg, expr, late: true } } - } else if eat_operand_keyword(p, sym::label, asm_macro)? { + } else if eat_operand_keyword(p, exp!(Label), asm_macro)? { let block = p.parse_block()?; ast::InlineAsmOperand::Label { block } - } else if p.eat_keyword(kw::Const) { + } else if p.eat_keyword(exp!(Const)) { let anon_const = p.parse_expr_anon_const()?; ast::InlineAsmOperand::Const { anon_const } - } else if p.eat_keyword(sym::sym) { + } else if p.eat_keyword(exp!(Sym)) { let expr = p.parse_expr()?; let ast::ExprKind::Path(qself, path) = &expr.kind else { let err = dcx.create_err(errors::AsmSymNoPath { span: expr.span }); @@ -389,31 +389,31 @@ fn parse_options<'a>( ) -> PResult<'a, ()> { let span_start = p.prev_token.span; - p.expect(&token::OpenDelim(Delimiter::Parenthesis))?; + p.expect(exp!(OpenParen))?; - while !p.eat(&token::CloseDelim(Delimiter::Parenthesis)) { - const OPTIONS: [(Symbol, ast::InlineAsmOptions); ast::InlineAsmOptions::COUNT] = [ - (sym::pure, ast::InlineAsmOptions::PURE), - (sym::nomem, ast::InlineAsmOptions::NOMEM), - (sym::readonly, ast::InlineAsmOptions::READONLY), - (sym::preserves_flags, ast::InlineAsmOptions::PRESERVES_FLAGS), - (sym::noreturn, ast::InlineAsmOptions::NORETURN), - (sym::nostack, ast::InlineAsmOptions::NOSTACK), - (sym::may_unwind, ast::InlineAsmOptions::MAY_UNWIND), - (sym::att_syntax, ast::InlineAsmOptions::ATT_SYNTAX), - (kw::Raw, ast::InlineAsmOptions::RAW), + while !p.eat(exp!(CloseParen)) { + const OPTIONS: [(ExpKeywordPair, ast::InlineAsmOptions); ast::InlineAsmOptions::COUNT] = [ + (exp!(Pure), ast::InlineAsmOptions::PURE), + (exp!(Nomem), ast::InlineAsmOptions::NOMEM), + (exp!(Readonly), ast::InlineAsmOptions::READONLY), + (exp!(PreservesFlags), ast::InlineAsmOptions::PRESERVES_FLAGS), + (exp!(Noreturn), ast::InlineAsmOptions::NORETURN), + (exp!(Nostack), ast::InlineAsmOptions::NOSTACK), + (exp!(MayUnwind), ast::InlineAsmOptions::MAY_UNWIND), + (exp!(AttSyntax), ast::InlineAsmOptions::ATT_SYNTAX), + (exp!(Raw), ast::InlineAsmOptions::RAW), ]; 'blk: { - for (symbol, option) in OPTIONS { + for (exp, option) in OPTIONS { let kw_matched = if asm_macro.is_supported_option(option) { - p.eat_keyword(symbol) + p.eat_keyword(exp) } else { - p.eat_keyword_noexpect(symbol) + p.eat_keyword_noexpect(exp.kw) }; if kw_matched { - try_set_option(p, args, asm_macro, symbol, option); + try_set_option(p, args, asm_macro, exp.kw, option); break 'blk; } } @@ -422,10 +422,10 @@ fn parse_options<'a>( } // Allow trailing commas - if p.eat(&token::CloseDelim(Delimiter::Parenthesis)) { + if p.eat(exp!(CloseParen)) { break; } - p.expect(&token::Comma)?; + p.expect(exp!(Comma))?; } let new_span = span_start.to(p.prev_token.span); @@ -437,14 +437,14 @@ fn parse_options<'a>( fn parse_clobber_abi<'a>(p: &mut Parser<'a>, args: &mut AsmArgs) -> PResult<'a, ()> { let span_start = p.prev_token.span; - p.expect(&token::OpenDelim(Delimiter::Parenthesis))?; + p.expect(exp!(OpenParen))?; - if p.eat(&token::CloseDelim(Delimiter::Parenthesis)) { + if p.eat(exp!(CloseParen)) { return Err(p.dcx().create_err(errors::NonABI { span: p.token.span })); } let mut new_abis = Vec::new(); - while !p.eat(&token::CloseDelim(Delimiter::Parenthesis)) { + while !p.eat(exp!(CloseParen)) { match p.parse_str_lit() { Ok(str_lit) => { new_abis.push((str_lit.symbol_unescaped, str_lit.span)); @@ -456,10 +456,10 @@ fn parse_clobber_abi<'a>(p: &mut Parser<'a>, args: &mut AsmArgs) -> PResult<'a, }; // Allow trailing commas - if p.eat(&token::CloseDelim(Delimiter::Parenthesis)) { + if p.eat(exp!(CloseParen)) { break; } - p.expect(&token::Comma)?; + p.expect(exp!(Comma))?; } let full_span = span_start.to(p.prev_token.span); @@ -482,7 +482,7 @@ fn parse_reg<'a>( p: &mut Parser<'a>, explicit_reg: &mut bool, ) -> PResult<'a, ast::InlineAsmRegOrRegClass> { - p.expect(&token::OpenDelim(Delimiter::Parenthesis))?; + p.expect(exp!(OpenParen))?; let result = match p.token.uninterpolate().kind { token::Ident(name, IdentIsRaw::No) => ast::InlineAsmRegOrRegClass::RegClass(name), token::Literal(token::Lit { kind: token::LitKind::Str, symbol, suffix: _ }) => { @@ -496,7 +496,7 @@ fn parse_reg<'a>( } }; p.bump(); - p.expect(&token::CloseDelim(Delimiter::Parenthesis))?; + p.expect(exp!(CloseParen))?; Ok(result) } diff --git a/compiler/rustc_builtin_macros/src/assert.rs b/compiler/rustc_builtin_macros/src/assert.rs index 95b31c7e47a2..c659b1cff59b 100644 --- a/compiler/rustc_builtin_macros/src/assert.rs +++ b/compiler/rustc_builtin_macros/src/assert.rs @@ -7,6 +7,7 @@ use rustc_ast::{DelimArgs, Expr, ExprKind, MacCall, Path, PathSegment, UnOp, tok use rustc_ast_pretty::pprust; use rustc_errors::PResult; use rustc_expand::base::{DummyResult, ExpandResult, ExtCtxt, MacEager, MacroExpanderResult}; +use rustc_parse::exp; use rustc_parse::parser::Parser; use rustc_span::{DUMMY_SP, Ident, Span, Symbol, sym}; use thin_vec::thin_vec; @@ -143,7 +144,7 @@ fn parse_assert<'a>(cx: &ExtCtxt<'a>, sp: Span, stream: TokenStream) -> PResult< cx.dcx().emit_err(errors::AssertMissingComma { span: parser.token.span, comma }); parse_custom_message(&mut parser) - } else if parser.eat(&token::Comma) { + } else if parser.eat(exp!(Comma)) { parse_custom_message(&mut parser) } else { None diff --git a/compiler/rustc_builtin_macros/src/cfg.rs b/compiler/rustc_builtin_macros/src/cfg.rs index 6e90f1682e30..85b8ef79c050 100644 --- a/compiler/rustc_builtin_macros/src/cfg.rs +++ b/compiler/rustc_builtin_macros/src/cfg.rs @@ -6,6 +6,7 @@ use rustc_ast::token; use rustc_ast::tokenstream::TokenStream; use rustc_errors::PResult; use rustc_expand::base::{DummyResult, ExpandResult, ExtCtxt, MacEager, MacroExpanderResult}; +use rustc_parse::exp; use rustc_span::Span; use {rustc_ast as ast, rustc_attr_parsing as attr}; @@ -48,9 +49,9 @@ fn parse_cfg<'a>( let cfg = p.parse_meta_item_inner()?; - let _ = p.eat(&token::Comma); + let _ = p.eat(exp!(Comma)); - if !p.eat(&token::Eof) { + if !p.eat(exp!(Eof)) { return Err(cx.dcx().create_err(errors::OneCfgPattern { span })); } diff --git a/compiler/rustc_builtin_macros/src/format.rs b/compiler/rustc_builtin_macros/src/format.rs index df3750049b71..528eb7725f5c 100644 --- a/compiler/rustc_builtin_macros/src/format.rs +++ b/compiler/rustc_builtin_macros/src/format.rs @@ -12,6 +12,7 @@ use rustc_errors::{Applicability, Diag, MultiSpan, PResult, SingleLabelManySpans use rustc_expand::base::*; use rustc_lint_defs::builtin::NAMED_ARGUMENTS_USED_POSITIONALLY; use rustc_lint_defs::{BufferedEarlyLint, BuiltinLintDiag, LintId}; +use rustc_parse::exp; use rustc_parse_format as parse; use rustc_span::{BytePos, ErrorGuaranteed, Ident, InnerSpan, Span, Symbol}; @@ -93,12 +94,12 @@ fn parse_args<'a>(ecx: &ExtCtxt<'a>, sp: Span, tts: TokenStream) -> PResult<'a, let mut first = true; while p.token != token::Eof { - if !p.eat(&token::Comma) { + if !p.eat(exp!(Comma)) { if first { p.clear_expected_token_types(); } - match p.expect(&token::Comma) { + match p.expect(exp!(Comma)) { Err(err) => { match token::TokenKind::Comma.similar_tokens() { Some(tks) if tks.contains(&p.token.kind) => { @@ -122,7 +123,7 @@ fn parse_args<'a>(ecx: &ExtCtxt<'a>, sp: Span, tts: TokenStream) -> PResult<'a, match p.token.ident() { Some((ident, _)) if p.look_ahead(1, |t| *t == token::Eq) => { p.bump(); - p.expect(&token::Eq)?; + p.expect(exp!(Eq))?; let expr = p.parse_expr()?; if let Some((_, prev)) = args.by_name(ident.name) { ecx.dcx().emit_err(errors::FormatDuplicateArg { diff --git a/compiler/rustc_builtin_macros/src/pattern_type.rs b/compiler/rustc_builtin_macros/src/pattern_type.rs index 90b5f097b32b..a600a9f316a7 100644 --- a/compiler/rustc_builtin_macros/src/pattern_type.rs +++ b/compiler/rustc_builtin_macros/src/pattern_type.rs @@ -3,7 +3,8 @@ use rustc_ast::tokenstream::TokenStream; use rustc_ast::{Pat, Ty, ast}; use rustc_errors::PResult; use rustc_expand::base::{self, DummyResult, ExpandResult, ExtCtxt, MacroExpanderResult}; -use rustc_span::{Span, sym}; +use rustc_parse::exp; +use rustc_span::Span; pub(crate) fn expand<'cx>( cx: &'cx mut ExtCtxt<'_>, @@ -24,7 +25,7 @@ fn parse_pat_ty<'a>(cx: &mut ExtCtxt<'a>, stream: TokenStream) -> PResult<'a, (P let mut parser = cx.new_parser_from_tts(stream); let ty = parser.parse_ty()?; - parser.expect_keyword(sym::is)?; + parser.expect_keyword(exp!(Is))?; let pat = parser.parse_pat_no_top_alt(None, None)?; Ok((ty, pat)) diff --git a/compiler/rustc_builtin_macros/src/util.rs b/compiler/rustc_builtin_macros/src/util.rs index 2a28dfaf3c43..be12d21a8000 100644 --- a/compiler/rustc_builtin_macros/src/util.rs +++ b/compiler/rustc_builtin_macros/src/util.rs @@ -7,7 +7,7 @@ use rustc_expand::expand::AstFragment; use rustc_feature::AttributeTemplate; use rustc_lint_defs::BuiltinLintDiag; use rustc_lint_defs::builtin::DUPLICATE_MACRO_ATTRIBUTES; -use rustc_parse::{parser, validate_attr}; +use rustc_parse::{exp, parser, validate_attr}; use rustc_session::errors::report_lit_error; use rustc_span::{BytePos, Span, Symbol}; @@ -204,7 +204,7 @@ pub(crate) fn get_single_expr_from_tts( Ok(ret) => ret, Err(guar) => return ExpandResult::Ready(Err(guar)), }; - let _ = p.eat(&token::Comma); + let _ = p.eat(exp!(Comma)); if p.token != token::Eof { cx.dcx().emit_err(errors::OnlyOneArgument { span, name }); @@ -237,7 +237,7 @@ pub(crate) fn get_exprs_from_tts( let expr = cx.expander().fully_expand_fragment(AstFragment::Expr(expr)).make_expr(); es.push(expr); - if p.eat(&token::Comma) { + if p.eat(exp!(Comma)) { continue; } if p.token != token::Eof { diff --git a/compiler/rustc_expand/src/module.rs b/compiler/rustc_expand/src/module.rs index a001b1d3dc8a..9c35b26772b6 100644 --- a/compiler/rustc_expand/src/module.rs +++ b/compiler/rustc_expand/src/module.rs @@ -2,9 +2,9 @@ use std::iter::once; use std::path::{self, Path, PathBuf}; use rustc_ast::ptr::P; -use rustc_ast::{AttrVec, Attribute, Inline, Item, ModSpans, token}; +use rustc_ast::{AttrVec, Attribute, Inline, Item, ModSpans}; use rustc_errors::{Diag, ErrorGuaranteed}; -use rustc_parse::{new_parser_from_file, unwrap_or_emit_fatal, validate_attr}; +use rustc_parse::{exp, new_parser_from_file, unwrap_or_emit_fatal, validate_attr}; use rustc_session::Session; use rustc_session::parse::ParseSess; use rustc_span::{Ident, Span, sym}; @@ -70,7 +70,7 @@ pub(crate) fn parse_external_mod( let mut parser = unwrap_or_emit_fatal(new_parser_from_file(&sess.psess, &mp.file_path, Some(span))); let (inner_attrs, items, inner_span) = - parser.parse_mod(&token::Eof).map_err(|err| ModError::ParserError(err))?; + parser.parse_mod(exp!(Eof)).map_err(|err| ModError::ParserError(err))?; attrs.extend(inner_attrs); (items, inner_span, mp.file_path) }; diff --git a/compiler/rustc_expand/src/proc_macro_server.rs b/compiler/rustc_expand/src/proc_macro_server.rs index 8577aa110af8..7eb09a64e96a 100644 --- a/compiler/rustc_expand/src/proc_macro_server.rs +++ b/compiler/rustc_expand/src/proc_macro_server.rs @@ -15,7 +15,7 @@ use rustc_data_structures::sync::Lrc; use rustc_errors::{Diag, ErrorGuaranteed, MultiSpan, PResult}; use rustc_parse::lexer::nfc_normalize; use rustc_parse::parser::Parser; -use rustc_parse::{new_parser_from_source_str, source_str_to_stream, unwrap_or_emit_fatal}; +use rustc_parse::{exp, new_parser_from_source_str, source_str_to_stream, unwrap_or_emit_fatal}; use rustc_session::parse::ParseSess; use rustc_span::def_id::CrateNum; use rustc_span::{BytePos, FileName, Pos, SourceFile, Span, Symbol, sym}; @@ -473,7 +473,7 @@ impl server::FreeFunctions for Rustc<'_, '_> { unwrap_or_emit_fatal(new_parser_from_source_str(self.psess(), name, s.to_owned())); let first_span = parser.token.span.data(); - let minus_present = parser.eat(&token::BinOp(token::Minus)); + let minus_present = parser.eat(exp!(Minus)); let lit_span = parser.token.span.data(); let token::Literal(mut lit) = parser.token.kind else { diff --git a/compiler/rustc_parse/src/parser/attr.rs b/compiler/rustc_parse/src/parser/attr.rs index 9da4ab5a7882..2691e6f56d68 100644 --- a/compiler/rustc_parse/src/parser/attr.rs +++ b/compiler/rustc_parse/src/parser/attr.rs @@ -1,8 +1,7 @@ -use rustc_ast::token::{self, Delimiter}; -use rustc_ast::{self as ast, Attribute, attr}; +use rustc_ast::{self as ast, Attribute, attr, token}; use rustc_errors::codes::*; use rustc_errors::{Diag, PResult}; -use rustc_span::{BytePos, Span, kw}; +use rustc_span::{BytePos, Span}; use thin_vec::ThinVec; use tracing::debug; @@ -10,7 +9,7 @@ use super::{ AttrWrapper, Capturing, FnParseMode, ForceCollect, Parser, ParserRange, PathStyle, Trailing, UsePreAttrPos, }; -use crate::{errors, fluent_generated as fluent, maybe_whole}; +use crate::{errors, exp, fluent_generated as fluent, maybe_whole}; // Public for rustfmt usage #[derive(Debug)] @@ -45,7 +44,7 @@ impl<'a> Parser<'a> { let mut just_parsed_doc_comment = false; let start_pos = self.num_bump_calls; loop { - let attr = if self.check(&token::Pound) { + let attr = if self.check(exp!(Pound)) { let prev_outer_attr_sp = outer_attrs.last().map(|attr: &Attribute| attr.span); let inner_error_reason = if just_parsed_doc_comment { @@ -126,14 +125,14 @@ impl<'a> Parser<'a> { let lo = self.token.span; // Attributes can't have attributes of their own [Editor's note: not with that attitude] self.collect_tokens_no_attrs(|this| { - assert!(this.eat(&token::Pound), "parse_attribute called in non-attribute position"); + assert!(this.eat(exp!(Pound)), "parse_attribute called in non-attribute position"); let style = - if this.eat(&token::Not) { ast::AttrStyle::Inner } else { ast::AttrStyle::Outer }; + if this.eat(exp!(Not)) { ast::AttrStyle::Inner } else { ast::AttrStyle::Outer }; - this.expect(&token::OpenDelim(Delimiter::Bracket))?; + this.expect(exp!(OpenBracket))?; let item = this.parse_attr_item(ForceCollect::No)?; - this.expect(&token::CloseDelim(Delimiter::Bracket))?; + this.expect(exp!(CloseBracket))?; let attr_sp = lo.to(this.prev_token.span); // Emit error if inner attribute is encountered and forbidden. @@ -274,10 +273,10 @@ impl<'a> Parser<'a> { // Attr items don't have attributes. self.collect_tokens(None, AttrWrapper::empty(), force_collect, |this, _empty_attrs| { - let is_unsafe = this.eat_keyword(kw::Unsafe); + let is_unsafe = this.eat_keyword(exp!(Unsafe)); let unsafety = if is_unsafe { let unsafe_span = this.prev_token.span; - this.expect(&token::OpenDelim(Delimiter::Parenthesis))?; + this.expect(exp!(OpenParen))?; ast::Safety::Unsafe(unsafe_span) } else { ast::Safety::Default @@ -286,7 +285,7 @@ impl<'a> Parser<'a> { let path = this.parse_path(PathStyle::Mod)?; let args = this.parse_attr_args()?; if is_unsafe { - this.expect(&token::CloseDelim(Delimiter::Parenthesis))?; + this.expect(exp!(CloseParen))?; } Ok(( ast::AttrItem { unsafety, path, args, tokens: None }, @@ -306,7 +305,7 @@ impl<'a> Parser<'a> { loop { let start_pos = self.num_bump_calls; // Only try to parse if it is an inner attribute (has `!`). - let attr = if self.check(&token::Pound) && self.look_ahead(1, |t| t == &token::Not) { + let attr = if self.check(exp!(Pound)) && self.look_ahead(1, |t| t == &token::Not) { Some(self.parse_attribute(InnerAttrPolicy::Permitted)?) } else if let token::DocComment(comment_kind, attr_style, data) = self.token.kind { if attr_style == ast::AttrStyle::Inner { @@ -358,7 +357,7 @@ impl<'a> Parser<'a> { &mut self, ) -> PResult<'a, (ast::MetaItemInner, Vec<(ast::AttrItem, Span)>)> { let cfg_predicate = self.parse_meta_item_inner()?; - self.expect(&token::Comma)?; + self.expect(exp!(Comma))?; // Presumably, the majority of the time there will only be one attr. let mut expanded_attrs = Vec::with_capacity(1); @@ -366,7 +365,7 @@ impl<'a> Parser<'a> { let lo = self.token.span; let item = self.parse_attr_item(ForceCollect::Yes)?; expanded_attrs.push((item, lo.to(self.prev_token.span))); - if !self.eat(&token::Comma) { + if !self.eat(exp!(Comma)) { break; } } @@ -380,7 +379,7 @@ impl<'a> Parser<'a> { let mut nmis = ThinVec::with_capacity(1); while self.token != token::Eof { nmis.push(self.parse_meta_item_inner()?); - if !self.eat(&token::Comma) { + if !self.eat(exp!(Comma)) { break; } } @@ -413,13 +412,13 @@ impl<'a> Parser<'a> { let lo = self.token.span; let is_unsafe = if unsafe_allowed == AllowLeadingUnsafe::Yes { - self.eat_keyword(kw::Unsafe) + self.eat_keyword(exp!(Unsafe)) } else { false }; let unsafety = if is_unsafe { let unsafe_span = self.prev_token.span; - self.expect(&token::OpenDelim(Delimiter::Parenthesis))?; + self.expect(exp!(OpenParen))?; ast::Safety::Unsafe(unsafe_span) } else { @@ -429,7 +428,7 @@ impl<'a> Parser<'a> { let path = self.parse_path(PathStyle::Mod)?; let kind = self.parse_meta_item_kind()?; if is_unsafe { - self.expect(&token::CloseDelim(Delimiter::Parenthesis))?; + self.expect(exp!(CloseParen))?; } let span = lo.to(self.prev_token.span); @@ -437,9 +436,9 @@ impl<'a> Parser<'a> { } pub(crate) fn parse_meta_item_kind(&mut self) -> PResult<'a, ast::MetaItemKind> { - Ok(if self.eat(&token::Eq) { + Ok(if self.eat(exp!(Eq)) { ast::MetaItemKind::NameValue(self.parse_unsuffixed_meta_item_lit()?) - } else if self.check(&token::OpenDelim(Delimiter::Parenthesis)) { + } else if self.check(exp!(OpenParen)) { let (list, _) = self.parse_paren_comma_seq(|p| p.parse_meta_item_inner())?; ast::MetaItemKind::List(list) } else { diff --git a/compiler/rustc_parse/src/parser/diagnostics.rs b/compiler/rustc_parse/src/parser/diagnostics.rs index 1a8f8f6069aa..7e9b9219e7ac 100644 --- a/compiler/rustc_parse/src/parser/diagnostics.rs +++ b/compiler/rustc_parse/src/parser/diagnostics.rs @@ -29,7 +29,8 @@ use tracing::{debug, trace}; use super::pat::Expected; use super::{ - BlockMode, CommaRecoveryMode, Parser, PathStyle, Restrictions, SemiColonMode, SeqSep, TokenType, + BlockMode, CommaRecoveryMode, ExpTokenPair, Parser, PathStyle, Restrictions, SemiColonMode, + SeqSep, TokenType, }; use crate::errors::{ AddParen, AmbiguousPlus, AsyncMoveBlockIn2015, AttributeOnParamType, AwaitSuggestion, @@ -47,7 +48,7 @@ use crate::errors::{ UnexpectedConstParamDeclarationSugg, UnmatchedAngleBrackets, UseEqInstead, WrapType, }; use crate::parser::attr::InnerAttrPolicy; -use crate::{fluent_generated as fluent, parser}; +use crate::{exp, fluent_generated as fluent}; /// Creates a placeholder argument. pub(super) fn dummy_arg(ident: Ident, guar: ErrorGuaranteed) -> Param { @@ -462,8 +463,8 @@ impl<'a> Parser<'a> { pub(super) fn expected_one_of_not_found( &mut self, - edible: &[TokenKind], - inedible: &[TokenKind], + edible: &[ExpTokenPair<'_>], + inedible: &[ExpTokenPair<'_>], ) -> PResult<'a, ErrorGuaranteed> { debug!("expected_one_of_not_found(edible: {:?}, inedible: {:?})", edible, inedible); fn tokens_to_string(tokens: &[TokenType]) -> String { @@ -483,50 +484,17 @@ impl<'a> Parser<'a> { }) } - self.expected_token_types - .extend(edible.iter().chain(inedible).cloned().map(TokenType::Token)); - let mut expected = self - .expected_token_types - .iter() - .filter(|token| { - // Filter out suggestions that suggest the same token which was found and deemed incorrect. - fn is_ident_eq_keyword(found: &TokenKind, expected: &TokenType) -> bool { - if let TokenKind::Ident(current_sym, _) = found - && let TokenType::Keyword(suggested_sym) = expected - { - return current_sym == suggested_sym; - } - false - } - - if **token != parser::TokenType::Token(self.token.kind.clone()) { - let eq = is_ident_eq_keyword(&self.token.kind, &token); - // If the suggestion is a keyword and the found token is an ident, - // the content of which are equal to the suggestion's content, - // we can remove that suggestion (see the `return false` below). - - // If this isn't the case however, and the suggestion is a token the - // content of which is the same as the found token's, we remove it as well. - if !eq { - if let TokenType::Token(kind) = token { - if self.token == *kind { - return false; - } - } - return true; - } - } - false - }) - .cloned() - .collect::>(); + for exp in edible.iter().chain(inedible.iter()) { + self.expected_token_types.insert(exp.token_type); + } + let mut expected: Vec<_> = self.expected_token_types.iter().collect(); expected.sort_by_cached_key(|x| x.to_string()); expected.dedup(); let sm = self.psess.source_map(); // Special-case "expected `;`" errors. - if expected.contains(&TokenType::Token(token::Semi)) { + if expected.contains(&TokenType::Semi) { // If the user is trying to write a ternary expression, recover it and // return an Err to prevent a cascade of irrelevant diagnostics. if self.prev_token == token::Question @@ -578,7 +546,7 @@ impl<'a> Parser<'a> { || (sm.is_multiline( self.prev_token.span.shrink_to_hi().until(self.token.span.shrink_to_lo()), ) && t == &token::Pound) - }) && !expected.contains(&TokenType::Token(token::Comma)) + }) && !expected.contains(&TokenType::Comma) { // Missing semicolon typo. This is triggered if the next token could either start a // new statement or is a block close. For example: @@ -598,7 +566,7 @@ impl<'a> Parser<'a> { if self.token == TokenKind::EqEq && self.prev_token.is_ident() - && expected.iter().any(|tok| matches!(tok, TokenType::Token(TokenKind::Eq))) + && expected.contains(&TokenType::Eq) { // Likely typo: `=` → `==` in let expr or enum item return Err(self.dcx().create_err(UseEqInstead { span: self.token.span })); @@ -637,15 +605,8 @@ impl<'a> Parser<'a> { // Look for usages of '=>' where '>=' was probably intended if self.token == token::FatArrow - && expected - .iter() - .any(|tok| matches!(tok, TokenType::Operator | TokenType::Token(TokenKind::Le))) - && !expected.iter().any(|tok| { - matches!( - tok, - TokenType::Token(TokenKind::FatArrow) | TokenType::Token(TokenKind::Comma) - ) - }) + && expected.iter().any(|tok| matches!(tok, TokenType::Operator | TokenType::Le)) + && !expected.iter().any(|tok| matches!(tok, TokenType::FatArrow | TokenType::Comma)) { err.span_suggestion( self.token.span, @@ -742,7 +703,7 @@ impl<'a> Parser<'a> { }; if self.check_too_many_raw_str_terminators(&mut err) { - if expected.contains(&TokenType::Token(token::Semi)) && self.eat(&token::Semi) { + if expected.contains(&TokenType::Semi) && self.eat(exp!(Semi)) { let guar = err.emit(); return Ok(guar); } else { @@ -788,10 +749,8 @@ impl<'a> Parser<'a> { }; let expected_token_types: &[TokenType] = expected.len().checked_sub(10).map_or(&expected, |index| &expected[index..]); - let expected_keywords: Vec = expected_token_types - .iter() - .filter_map(|token| if let TokenType::Keyword(kw) = token { Some(*kw) } else { None }) - .collect(); + let expected_keywords: Vec = + expected_token_types.iter().filter_map(|token| token.is_keyword()).collect(); // When there are a few keywords in the last ten elements of `self.expected_token_types` // and the current token is an identifier, it's probably a misspelled keyword. This handles @@ -1053,7 +1012,7 @@ impl<'a> Parser<'a> { (Err(snapshot_err), Err(err)) => { // We don't know what went wrong, emit the normal error. snapshot_err.cancel(); - self.consume_block(Delimiter::Brace, ConsumeClosingDelim::Yes); + self.consume_block(exp!(OpenBrace), exp!(CloseBrace), ConsumeClosingDelim::Yes); Err(err) } (Ok(_), Ok(mut tail)) => { @@ -1090,7 +1049,7 @@ impl<'a> Parser<'a> { Applicability::MaybeIncorrect, ); let guar = err.emit(); - self.eat_to_tokens(&[&token::CloseDelim(Delimiter::Brace)]); + self.eat_to_tokens(&[exp!(CloseBrace)]); guar } token::OpenDelim(Delimiter::Parenthesis) @@ -1098,7 +1057,7 @@ impl<'a> Parser<'a> { { // We are within a function call or tuple, we can emit the error // and recover. - self.eat_to_tokens(&[&token::CloseDelim(Delimiter::Parenthesis), &token::Comma]); + self.eat_to_tokens(&[exp!(CloseParen), exp!(Comma)]); err.multipart_suggestion_verbose( "you might have meant to open the body of the closure", @@ -1127,7 +1086,7 @@ impl<'a> Parser<'a> { /// Eats and discards tokens until one of `closes` is encountered. Respects token trees, /// passes through any errors encountered. Used for error recovery. - pub(super) fn eat_to_tokens(&mut self, closes: &[&TokenKind]) { + pub(super) fn eat_to_tokens(&mut self, closes: &[ExpTokenPair<'_>]) { if let Err(err) = self .parse_seq_to_before_tokens(closes, &[], SeqSep::none(), |p| Ok(p.parse_token_tree())) { @@ -1148,7 +1107,7 @@ impl<'a> Parser<'a> { pub(super) fn check_trailing_angle_brackets( &mut self, segment: &PathSegment, - end: &[&TokenKind], + end: &[ExpTokenPair<'_>], ) -> Option { if !self.may_recover() { return None; @@ -1231,7 +1190,7 @@ impl<'a> Parser<'a> { // second case. if self.look_ahead(position, |t| { trace!("check_trailing_angle_brackets: t={:?}", t); - end.contains(&&t.kind) + end.iter().any(|exp| exp.tok == &t.kind) }) { // Eat from where we started until the end token so that parsing can continue // as if we didn't have those extra angle brackets. @@ -1299,11 +1258,11 @@ impl<'a> Parser<'a> { ) -> PResult<'a, ErrorGuaranteed> { if let ExprKind::Binary(binop, _, _) = &expr.kind && let ast::BinOpKind::Lt = binop.node - && self.eat(&token::Comma) + && self.eat(exp!(Comma)) { let x = self.parse_seq_to_before_end( - &token::Gt, - SeqSep::trailing_allowed(token::Comma), + exp!(Gt), + SeqSep::trailing_allowed(exp!(Comma)), |p| match p.parse_generic_arg(None)? { Some(arg) => Ok(arg), // If we didn't eat a generic arg, then we should error. @@ -1312,7 +1271,7 @@ impl<'a> Parser<'a> { ); match x { Ok((_, _, Recovered::No)) => { - if self.eat(&token::Gt) { + if self.eat(exp!(Gt)) { // We made sense of it. Improve the error message. e.span_suggestion_verbose( binop.span.shrink_to_lo(), @@ -1875,7 +1834,7 @@ impl<'a> Parser<'a> { ty_span: Span, ty: P, ) -> PResult<'a, P> { - self.expect(&token::PathSep)?; + self.expect(exp!(PathSep))?; let mut path = ast::Path { segments: ThinVec::new(), span: DUMMY_SP, tokens: None }; self.parse_path_segments(&mut path.segments, T::PATH_STYLE, None)?; @@ -1957,10 +1916,10 @@ impl<'a> Parser<'a> { } pub(super) fn expect_semi(&mut self) -> PResult<'a, ()> { - if self.eat(&token::Semi) || self.recover_colon_as_semi() { + if self.eat(exp!(Semi)) || self.recover_colon_as_semi() { return Ok(()); } - self.expect(&token::Semi).map(drop) // Error unconditionally + self.expect(exp!(Semi)).map(drop) // Error unconditionally } pub(super) fn recover_colon_as_semi(&mut self) -> bool { @@ -2005,15 +1964,15 @@ impl<'a> Parser<'a> { } fn recover_await_macro(&mut self) -> PResult<'a, (Span, P, bool)> { - self.expect(&token::Not)?; - self.expect(&token::OpenDelim(Delimiter::Parenthesis))?; + self.expect(exp!(Not))?; + self.expect(exp!(OpenParen))?; let expr = self.parse_expr()?; - self.expect(&token::CloseDelim(Delimiter::Parenthesis))?; + self.expect(exp!(CloseParen))?; Ok((self.prev_token.span, expr, false)) } fn recover_await_prefix(&mut self, await_sp: Span) -> PResult<'a, (Span, P, bool)> { - let is_question = self.eat(&token::Question); // Handle `await? `. + let is_question = self.eat(exp!(Question)); // Handle `await? `. let expr = if self.token == token::OpenDelim(Delimiter::Brace) { // Handle `await { }`. // This needs to be handled separately from the next arm to avoid @@ -2075,7 +2034,7 @@ impl<'a> Parser<'a> { let try_span = lo.to(self.token.span); //we take the try!( span self.bump(); //remove ( let is_empty = self.token == token::CloseDelim(Delimiter::Parenthesis); //check if the block is empty - self.consume_block(Delimiter::Parenthesis, ConsumeClosingDelim::No); //eat the block + self.consume_block(exp!(OpenParen), exp!(CloseParen), ConsumeClosingDelim::No); //eat the block let hi = self.token.span; self.bump(); //remove ) let mut err = self.dcx().struct_span_err(lo.to(hi), "use of deprecated `try` macro"); @@ -2131,13 +2090,14 @@ impl<'a> Parser<'a> { pub(super) fn recover_seq_parse_error( &mut self, - delim: Delimiter, + open: ExpTokenPair<'_>, + close: ExpTokenPair<'_>, lo: Span, err: Diag<'a>, ) -> P { let guar = err.emit(); // Recover from parse error, callers expect the closing delim to be consumed. - self.consume_block(delim, ConsumeClosingDelim::Yes); + self.consume_block(open, close, ConsumeClosingDelim::Yes); self.mk_expr(lo.to(self.prev_token.span), ExprKind::Err(guar)) } @@ -2226,7 +2186,7 @@ impl<'a> Parser<'a> { } pub(super) fn check_for_for_in_in_typo(&mut self, in_span: Span) { - if self.eat_keyword(kw::In) { + if self.eat_keyword(exp!(In)) { // a common typo: `for _ in in bar {}` self.dcx().emit_err(InInTypo { span: self.prev_token.span, @@ -2367,7 +2327,7 @@ impl<'a> Parser<'a> { pub(super) fn recover_arg_parse(&mut self) -> PResult<'a, (P, P)> { let pat = self.parse_pat_no_top_alt(Some(Expected::ArgumentName), None)?; - self.expect(&token::Colon)?; + self.expect(exp!(Colon))?; let ty = self.parse_ty()?; self.dcx().emit_err(PatternMethodParamWithoutBody { span: pat.span }); @@ -2385,12 +2345,17 @@ impl<'a> Parser<'a> { Ok(param) } - pub(super) fn consume_block(&mut self, delim: Delimiter, consume_close: ConsumeClosingDelim) { + pub(super) fn consume_block( + &mut self, + open: ExpTokenPair<'_>, + close: ExpTokenPair<'_>, + consume_close: ConsumeClosingDelim, + ) { let mut brace_depth = 0; loop { - if self.eat(&token::OpenDelim(delim)) { + if self.eat(open) { brace_depth += 1; - } else if self.check(&token::CloseDelim(delim)) { + } else if self.check(close) { if brace_depth == 0 { if let ConsumeClosingDelim::Yes = consume_close { // Some of the callers of this method expect to be able to parse the @@ -2546,7 +2511,7 @@ impl<'a> Parser<'a> { match self.recover_const_arg(arg.span(), err) { Ok(arg) => { args.push(AngleBracketedArg::Arg(arg)); - if self.eat(&token::Comma) { + if self.eat(exp!(Comma)) { return Ok(true); // Continue } } @@ -3017,7 +2982,7 @@ impl<'a> Parser<'a> { /// Check for exclusive ranges written as `..<` pub(crate) fn maybe_err_dotdotlt_syntax(&self, maybe_lt: Token, mut err: Diag<'a>) -> Diag<'a> { if maybe_lt == token::Lt - && (self.expected_token_types.contains(&TokenType::Token(token::Gt)) + && (self.expected_token_types.contains(TokenType::Gt) || matches!(self.token.kind, token::Literal(..))) { err.span_suggestion( @@ -3147,9 +3112,9 @@ impl<'a> Parser<'a> { /// Parse and throw away a parenthesized comma separated /// sequence of patterns until `)` is reached. fn skip_pat_list(&mut self) -> PResult<'a, ()> { - while !self.check(&token::CloseDelim(Delimiter::Parenthesis)) { + while !self.check(exp!(CloseParen)) { self.parse_pat_no_top_alt(None, None)?; - if !self.eat(&token::Comma) { + if !self.eat(exp!(Comma)) { return Ok(()); } } diff --git a/compiler/rustc_parse/src/parser/expr.rs b/compiler/rustc_parse/src/parser/expr.rs index 1e84b2a0cf8e..2f4adf2af9e9 100644 --- a/compiler/rustc_parse/src/parser/expr.rs +++ b/compiler/rustc_parse/src/parser/expr.rs @@ -35,10 +35,10 @@ use super::diagnostics::SnapshotParser; use super::pat::{CommaRecoveryMode, Expected, RecoverColon, RecoverComma}; use super::ty::{AllowPlus, RecoverQPath, RecoverReturnSign}; use super::{ - AttrWrapper, BlockMode, ClosureSpans, ForceCollect, Parser, PathStyle, Restrictions, - SemiColonMode, SeqSep, TokenType, Trailing, UsePreAttrPos, + AttrWrapper, BlockMode, ClosureSpans, ExpTokenPair, ForceCollect, Parser, PathStyle, + Restrictions, SemiColonMode, SeqSep, TokenType, Trailing, UsePreAttrPos, }; -use crate::{errors, maybe_recover_from_interpolated_ty_qpath}; +use crate::{errors, exp, maybe_recover_from_interpolated_ty_qpath}; #[derive(Debug)] pub(super) enum DestructuredFloat { @@ -153,7 +153,7 @@ impl<'a> Parser<'a> { return Ok((lhs, parsed_something)); } - self.expected_token_types.push(TokenType::Operator); + self.expected_token_types.insert(TokenType::Operator); while let Some(op) = self.check_assoc_op() { let lhs_span = self.interpolated_or_expr_span(&lhs); let cur_op_span = self.token.span; @@ -873,9 +873,9 @@ impl<'a> Parser<'a> { /// Parse `mut?` or `raw [ const | mut ]`. fn parse_borrow_modifiers(&mut self) -> (ast::BorrowKind, ast::Mutability) { - if self.check_keyword(kw::Raw) && self.look_ahead(1, Token::is_mutability) { + if self.check_keyword(exp!(Raw)) && self.look_ahead(1, Token::is_mutability) { // `raw [ const | mut ]`. - let found_raw = self.eat_keyword(kw::Raw); + let found_raw = self.eat_keyword(exp!(Raw)); assert!(found_raw); let mutability = self.parse_const_or_mut().unwrap(); (ast::BorrowKind::Raw, mutability) @@ -908,7 +908,7 @@ impl<'a> Parser<'a> { // a `return` which could be suggested otherwise. self.eat_noexpect(&token::Question) } else { - self.eat(&token::Question) + self.eat(exp!(Question)) }; if has_question { // `expr?` @@ -926,7 +926,7 @@ impl<'a> Parser<'a> { self.dcx().emit_err(errors::ExprRArrowCall { span }); true } else { - self.eat(&token::Dot) + self.eat(exp!(Dot)) }; if has_dot { // expr.f @@ -1251,7 +1251,7 @@ impl<'a> Parser<'a> { .map(|args| self.mk_expr(lo.to(self.prev_token.span), self.mk_call(fun, args))); match self.maybe_recover_struct_lit_bad_delims(lo, open_paren, seq, snapshot) { Ok(expr) => expr, - Err(err) => self.recover_seq_parse_error(Delimiter::Parenthesis, lo, err), + Err(err) => self.recover_seq_parse_error(exp!(OpenParen), exp!(CloseParen), lo, err), } } @@ -1268,10 +1268,8 @@ impl<'a> Parser<'a> { match (self.may_recover(), seq, snapshot) { (true, Err(err), Some((mut snapshot, ExprKind::Path(None, path)))) => { snapshot.bump(); // `(` - match snapshot.parse_struct_fields(path.clone(), false, Delimiter::Parenthesis) { - Ok((fields, ..)) - if snapshot.eat(&token::CloseDelim(Delimiter::Parenthesis)) => - { + match snapshot.parse_struct_fields(path.clone(), false, exp!(CloseParen)) { + Ok((fields, ..)) if snapshot.eat(exp!(CloseParen)) => { // We are certain we have `Enum::Foo(a: 3, b: 4)`, suggest // `Enum::Foo { a: 3, b: 4 }` or `Enum::Foo(3, 4)`. self.restore_snapshot(snapshot); @@ -1328,7 +1326,7 @@ impl<'a> Parser<'a> { self.bump(); // `[` let index = self.parse_expr()?; self.suggest_missing_semicolon_before_array(prev_span, open_delim_span)?; - self.expect(&token::CloseDelim(Delimiter::Bracket))?; + self.expect(exp!(CloseBracket))?; Ok(self.mk_expr( lo.to(self.prev_token.span), self.mk_index(base, index, open_delim_span.to(self.prev_token.span)), @@ -1337,12 +1335,12 @@ impl<'a> Parser<'a> { /// Assuming we have just parsed `.`, continue parsing into an expression. fn parse_dot_suffix(&mut self, self_arg: P, lo: Span) -> PResult<'a, P> { - if self.token.uninterpolated_span().at_least_rust_2018() && self.eat_keyword(kw::Await) { + if self.token.uninterpolated_span().at_least_rust_2018() && self.eat_keyword(exp!(Await)) { return Ok(self.mk_await_expr(self_arg, lo)); } // Post-fix match - if self.eat_keyword(kw::Match) { + if self.eat_keyword(exp!(Match)) { let match_span = self.prev_token.span; self.psess.gated_spans.gate(sym::postfix_match, match_span); return self.parse_match_block(lo, match_span, self_arg, MatchKind::Postfix); @@ -1350,10 +1348,10 @@ impl<'a> Parser<'a> { let fn_span_lo = self.token.span; let mut seg = self.parse_path_segment(PathStyle::Expr, None)?; - self.check_trailing_angle_brackets(&seg, &[&token::OpenDelim(Delimiter::Parenthesis)]); + self.check_trailing_angle_brackets(&seg, &[exp!(OpenParen)]); self.check_turbofish_missing_angle_brackets(&mut seg); - if self.check(&token::OpenDelim(Delimiter::Parenthesis)) { + if self.check(exp!(OpenParen)) { // Method call `expr.f()` let args = self.parse_expr_paren_seq()?; let fn_span = fn_span_lo.to(self.prev_token.span); @@ -1415,18 +1413,18 @@ impl<'a> Parser<'a> { let restrictions = self.restrictions; self.with_res(restrictions - Restrictions::ALLOW_LET, |this| { - // Note: when adding new syntax here, don't forget to adjust `TokenKind::can_begin_expr()`. + // Note: adding new syntax here? Don't forget to adjust `TokenKind::can_begin_expr()`. let lo = this.token.span; if let token::Literal(_) = this.token.kind { // This match arm is a special-case of the `_` match arm below and // could be removed without changing functionality, but it's faster // to have it here, especially for programs with large constants. this.parse_expr_lit() - } else if this.check(&token::OpenDelim(Delimiter::Parenthesis)) { + } else if this.check(exp!(OpenParen)) { this.parse_expr_tuple_parens(restrictions) - } else if this.check(&token::OpenDelim(Delimiter::Brace)) { + } else if this.check(exp!(OpenBrace)) { this.parse_expr_block(None, lo, BlockCheckMode::Default) - } else if this.check(&token::BinOp(token::Or)) || this.check(&token::OrOr) { + } else if this.check(exp!(Or)) || this.check(exp!(OrOr)) { this.parse_expr_closure().map_err(|mut err| { // If the input is something like `if a { 1 } else { 2 } | if a { 3 } else { 4 }` // then suggest parens around the lhs. @@ -1435,41 +1433,41 @@ impl<'a> Parser<'a> { } err }) - } else if this.check(&token::OpenDelim(Delimiter::Bracket)) { - this.parse_expr_array_or_repeat(Delimiter::Bracket) + } else if this.check(exp!(OpenBracket)) { + this.parse_expr_array_or_repeat(exp!(CloseBracket)) } else if this.is_builtin() { this.parse_expr_builtin() } else if this.check_path() { this.parse_expr_path_start() - } else if this.check_keyword(kw::Move) - || this.check_keyword(kw::Static) + } else if this.check_keyword(exp!(Move)) + || this.check_keyword(exp!(Static)) || this.check_const_closure() { this.parse_expr_closure() - } else if this.eat_keyword(kw::If) { + } else if this.eat_keyword(exp!(If)) { this.parse_expr_if() - } else if this.check_keyword(kw::For) { + } else if this.check_keyword(exp!(For)) { if this.choose_generics_over_qpath(1) { this.parse_expr_closure() } else { - assert!(this.eat_keyword(kw::For)); + assert!(this.eat_keyword(exp!(For))); this.parse_expr_for(None, lo) } - } else if this.eat_keyword(kw::While) { + } else if this.eat_keyword(exp!(While)) { this.parse_expr_while(None, lo) } else if let Some(label) = this.eat_label() { this.parse_expr_labeled(label, true) - } else if this.eat_keyword(kw::Loop) { + } else if this.eat_keyword(exp!(Loop)) { this.parse_expr_loop(None, lo).map_err(|mut err| { err.span_label(lo, "while parsing this `loop` expression"); err }) - } else if this.eat_keyword(kw::Match) { + } else if this.eat_keyword(exp!(Match)) { this.parse_expr_match().map_err(|mut err| { err.span_label(lo, "while parsing this `match` expression"); err }) - } else if this.eat_keyword(kw::Unsafe) { + } else if this.eat_keyword(exp!(Unsafe)) { this.parse_expr_block(None, lo, BlockCheckMode::Unsafe(ast::UserProvided)).map_err( |mut err| { err.span_label(lo, "while parsing this `unsafe` expression"); @@ -1481,23 +1479,23 @@ impl<'a> Parser<'a> { } else if this.may_recover() && this.is_do_catch_block() { this.recover_do_catch() } else if this.is_try_block() { - this.expect_keyword(kw::Try)?; + this.expect_keyword(exp!(Try))?; this.parse_try_block(lo) - } else if this.eat_keyword(kw::Return) { + } else if this.eat_keyword(exp!(Return)) { this.parse_expr_return() - } else if this.eat_keyword(kw::Continue) { + } else if this.eat_keyword(exp!(Continue)) { this.parse_expr_continue(lo) - } else if this.eat_keyword(kw::Break) { + } else if this.eat_keyword(exp!(Break)) { this.parse_expr_break() - } else if this.eat_keyword(kw::Yield) { + } else if this.eat_keyword(exp!(Yield)) { this.parse_expr_yield() } else if this.is_do_yeet() { this.parse_expr_yeet() - } else if this.eat_keyword(kw::Become) { + } else if this.eat_keyword(exp!(Become)) { this.parse_expr_become() - } else if this.check_keyword(kw::Let) { + } else if this.check_keyword(exp!(Let)) { this.parse_expr_let(restrictions) - } else if this.eat_keyword(kw::Underscore) { + } else if this.eat_keyword(exp!(Underscore)) { Ok(this.mk_expr(this.prev_token.span, ExprKind::Underscore)) } else if this.token.uninterpolated_span().at_least_rust_2018() { // `Span::at_least_rust_2018()` is somewhat expensive; don't get it repeatedly. @@ -1505,11 +1503,11 @@ impl<'a> Parser<'a> { // check for `gen {}` and `gen move {}` // or `async gen {}` and `async gen move {}` && (this.is_gen_block(kw::Gen, 0) - || (this.check_keyword(kw::Async) && this.is_gen_block(kw::Gen, 1))) + || (this.check_keyword(exp!(Async)) && this.is_gen_block(kw::Gen, 1))) { // FIXME: (async) gen closures aren't yet parsed. this.parse_gen_block() - } else if this.check_keyword(kw::Async) { + } else if this.check_keyword(exp!(Async)) { // FIXME(gen_blocks): Parse `gen async` and suggest swap if this.is_gen_block(kw::Async, 0) { // Check for `async {` and `async move {`, @@ -1541,15 +1539,20 @@ impl<'a> Parser<'a> { fn parse_expr_tuple_parens(&mut self, restrictions: Restrictions) -> PResult<'a, P> { let lo = self.token.span; - self.expect(&token::OpenDelim(Delimiter::Parenthesis))?; + self.expect(exp!(OpenParen))?; let (es, trailing_comma) = match self.parse_seq_to_end( - &token::CloseDelim(Delimiter::Parenthesis), - SeqSep::trailing_allowed(token::Comma), + exp!(CloseParen), + SeqSep::trailing_allowed(exp!(Comma)), |p| p.parse_expr_catch_underscore(restrictions.intersection(Restrictions::ALLOW_LET)), ) { Ok(x) => x, Err(err) => { - return Ok(self.recover_seq_parse_error(Delimiter::Parenthesis, lo, err)); + return Ok(self.recover_seq_parse_error( + exp!(OpenParen), + exp!(CloseParen), + lo, + err, + )); } }; let kind = if es.len() == 1 && matches!(trailing_comma, Trailing::No) { @@ -1563,25 +1566,24 @@ impl<'a> Parser<'a> { self.maybe_recover_from_bad_qpath(expr) } - fn parse_expr_array_or_repeat(&mut self, close_delim: Delimiter) -> PResult<'a, P> { + fn parse_expr_array_or_repeat(&mut self, close: ExpTokenPair<'_>) -> PResult<'a, P> { let lo = self.token.span; self.bump(); // `[` or other open delim - let close = &token::CloseDelim(close_delim); let kind = if self.eat(close) { // Empty vector ExprKind::Array(ThinVec::new()) } else { // Non-empty vector let first_expr = self.parse_expr()?; - if self.eat(&token::Semi) { + if self.eat(exp!(Semi)) { // Repeating array syntax: `[ 0; 512 ]` let count = self.parse_expr_anon_const()?; self.expect(close)?; ExprKind::Repeat(first_expr, count) - } else if self.eat(&token::Comma) { + } else if self.eat(exp!(Comma)) { // Vector with two or more elements. - let sep = SeqSep::trailing_allowed(token::Comma); + let sep = SeqSep::trailing_allowed(exp!(Comma)); let (mut exprs, _) = self.parse_seq_to_end(close, sep, |p| p.parse_expr())?; exprs.insert(0, first_expr); ExprKind::Array(exprs) @@ -1615,7 +1617,7 @@ impl<'a> Parser<'a> { }; // `!`, as an operator, is prefix, so we know this isn't that. - let (span, kind) = if self.eat(&token::Not) { + let (span, kind) = if self.eat(exp!(Not)) { // MACRO INVOCATION expression if qself.is_some() { self.dcx().emit_err(errors::MacroInvocationWithQualifiedPath(path.span)); @@ -1623,7 +1625,7 @@ impl<'a> Parser<'a> { let lo = path.span; let mac = P(MacCall { path, args: self.parse_delim_args()? }); (lo.to(self.prev_token.span), ExprKind::MacCall(mac)) - } else if self.check(&token::OpenDelim(Delimiter::Brace)) + } else if self.check(exp!(OpenBrace)) && let Some(expr) = self.maybe_parse_struct_expr(&qself, &path) { if qself.is_some() { @@ -1646,13 +1648,13 @@ impl<'a> Parser<'a> { ) -> PResult<'a, P> { let lo = label_.ident.span; let label = Some(label_); - let ate_colon = self.eat(&token::Colon); + let ate_colon = self.eat(exp!(Colon)); let tok_sp = self.token.span; - let expr = if self.eat_keyword(kw::While) { + let expr = if self.eat_keyword(exp!(While)) { self.parse_expr_while(label, lo) - } else if self.eat_keyword(kw::For) { + } else if self.eat_keyword(exp!(For)) { self.parse_expr_for(label, lo) - } else if self.eat_keyword(kw::Loop) { + } else if self.eat_keyword(exp!(Loop)) { self.parse_expr_loop(label, lo) } else if self.check_noexpect(&token::OpenDelim(Delimiter::Brace)) || self.token.is_whole_block() @@ -1958,7 +1960,7 @@ impl<'a> Parser<'a> { self.psess.gated_spans.gate(sym::builtin_syntax, ident.span); self.bump(); - self.expect(&TokenKind::OpenDelim(Delimiter::Parenthesis))?; + self.expect(exp!(OpenParen))?; let ret = if let Some(res) = parse(self, lo, ident)? { Ok(res) } else { @@ -1968,7 +1970,7 @@ impl<'a> Parser<'a> { }); return Err(err); }; - self.expect(&TokenKind::CloseDelim(Delimiter::Parenthesis))?; + self.expect(exp!(CloseParen))?; ret } @@ -1976,14 +1978,12 @@ impl<'a> Parser<'a> { /// Built-in macro for `offset_of!` expressions. pub(crate) fn parse_expr_offset_of(&mut self, lo: Span) -> PResult<'a, P> { let container = self.parse_ty()?; - self.expect(&TokenKind::Comma)?; + self.expect(exp!(Comma))?; let fields = self.parse_floating_field_access()?; let trailing_comma = self.eat_noexpect(&TokenKind::Comma); - if let Err(mut e) = - self.expect_one_of(&[], &[TokenKind::CloseDelim(Delimiter::Parenthesis)]) - { + if let Err(mut e) = self.expect_one_of(&[], &[exp!(CloseParen)]) { if trailing_comma { e.note("unexpected third argument to offset_of"); } else { @@ -2006,7 +2006,7 @@ impl<'a> Parser<'a> { /// Built-in macro for type ascription expressions. pub(crate) fn parse_expr_type_ascribe(&mut self, lo: Span) -> PResult<'a, P> { let expr = self.parse_expr()?; - self.expect(&token::Comma)?; + self.expect(exp!(Comma))?; let ty = self.parse_ty()?; let span = lo.to(self.token.span); Ok(self.mk_expr(span, ExprKind::Type(expr, ty))) @@ -2018,7 +2018,7 @@ impl<'a> Parser<'a> { kind: UnsafeBinderCastKind, ) -> PResult<'a, P> { let expr = self.parse_expr()?; - let ty = if self.eat(&TokenKind::Comma) { Some(self.parse_ty()?) } else { None }; + let ty = if self.eat(exp!(Comma)) { Some(self.parse_ty()?) } else { None }; let span = lo.to(self.token.span); Ok(self.mk_expr(span, ExprKind::UnsafeBinderCast(kind, expr, ty))) } @@ -2214,7 +2214,7 @@ impl<'a> Parser<'a> { } let lo = self.token.span; - let minus_present = self.eat(&token::BinOp(token::Minus)); + let minus_present = self.eat(exp!(Minus)); let (token_lit, span) = self.parse_token_lit()?; let expr = self.mk_expr(span, ExprKind::Lit(token_lit)); @@ -2236,7 +2236,7 @@ impl<'a> Parser<'a> { /// expression. fn maybe_suggest_brackets_instead_of_braces(&mut self, lo: Span) -> Option> { let mut snapshot = self.create_snapshot_for_diagnostic(); - match snapshot.parse_expr_array_or_repeat(Delimiter::Brace) { + match snapshot.parse_expr_array_or_repeat(exp!(CloseBrace)) { Ok(arr) => { let guar = self.dcx().emit_err(errors::ArrayBracketsInsteadOfSpaces { span: arr.span, @@ -2272,8 +2272,8 @@ impl<'a> Parser<'a> { let mut snapshot = self.create_snapshot_for_diagnostic(); snapshot.bump(); match snapshot.parse_seq_to_before_end( - &token::CloseDelim(Delimiter::Bracket), - SeqSep::trailing_allowed(token::Comma), + exp!(CloseBracket), + SeqSep::trailing_allowed(exp!(Comma)), |p| p.parse_expr(), ) { Ok(_) @@ -2337,7 +2337,7 @@ impl<'a> Parser<'a> { let lo = self.token.span; let before = self.prev_token.clone(); - let binder = if self.check_keyword(kw::For) { + let binder = if self.check_keyword(exp!(For)) { let lo = self.token.span; let (lifetime_defs, _) = self.parse_late_bound_lifetime_defs()?; let span = lo.to(self.prev_token.span); @@ -2352,7 +2352,7 @@ impl<'a> Parser<'a> { let constness = self.parse_closure_constness(); let movability = - if self.eat_keyword(kw::Static) { Movability::Static } else { Movability::Movable }; + if self.eat_keyword(exp!(Static)) { Movability::Static } else { Movability::Movable }; let coroutine_kind = if self.token.uninterpolated_span().at_least_rust_2018() { self.parse_coroutine_kind(Case::Sensitive) @@ -2433,10 +2433,10 @@ impl<'a> Parser<'a> { /// Parses an optional `move` prefix to a closure-like construct. fn parse_capture_clause(&mut self) -> PResult<'a, CaptureBy> { - if self.eat_keyword(kw::Move) { + if self.eat_keyword(exp!(Move)) { let move_kw_span = self.prev_token.span; // Check for `move async` and recover - if self.check_keyword(kw::Async) { + if self.check_keyword(exp!(Async)) { let move_async_span = self.token.span.with_lo(self.prev_token.span.data().lo); Err(self .dcx() @@ -2453,15 +2453,15 @@ impl<'a> Parser<'a> { fn parse_fn_block_decl(&mut self) -> PResult<'a, (P, Span)> { let arg_start = self.token.span.lo(); - let inputs = if self.eat(&token::OrOr) { + let inputs = if self.eat(exp!(OrOr)) { ThinVec::new() } else { - self.expect(&token::BinOp(token::Or))?; + self.expect(exp!(Or))?; let args = self .parse_seq_to_before_tokens( - &[&token::BinOp(token::Or)], + &[exp!(Or)], &[&token::OrOr], - SeqSep::trailing_allowed(token::Comma), + SeqSep::trailing_allowed(exp!(Comma)), |p| p.parse_fn_block_param(), )? .0; @@ -2481,7 +2481,7 @@ impl<'a> Parser<'a> { let attrs = self.parse_outer_attributes()?; self.collect_tokens(None, attrs, ForceCollect::No, |this, attrs| { let pat = this.parse_pat_no_top_alt(Some(Expected::ParameterName), None)?; - let ty = if this.eat(&token::Colon) { + let ty = if this.eat(exp!(Colon)) { this.parse_ty()? } else { this.mk_ty(pat.span, TyKind::Infer) @@ -2566,7 +2566,7 @@ impl<'a> Parser<'a> { } else { let attrs = self.parse_outer_attributes()?; // For recovery. let maybe_fatarrow = self.token.clone(); - let block = if self.check(&token::OpenDelim(Delimiter::Brace)) { + let block = if self.check(exp!(OpenBrace)) { self.parse_block()? } else if let Some(block) = recover_block_from_condition(self) { block @@ -2609,7 +2609,7 @@ impl<'a> Parser<'a> { self.error_on_if_block_attrs(lo, false, block.span, attrs); block }; - let els = if self.eat_keyword(kw::Else) { Some(self.parse_expr_else()?) } else { None }; + let els = if self.eat_keyword(exp!(Else)) { Some(self.parse_expr_else()?) } else { None }; Ok(self.mk_expr(lo.to(self.prev_token.span), ExprKind::If(cond, thn, els))) } @@ -2662,7 +2662,7 @@ impl<'a> Parser<'a> { }); self.bump(); } else { - self.expect(&token::Eq)?; + self.expect(exp!(Eq))?; } let attrs = self.parse_outer_attributes()?; let (expr, _) = @@ -2675,9 +2675,9 @@ impl<'a> Parser<'a> { fn parse_expr_else(&mut self) -> PResult<'a, P> { let else_span = self.prev_token.span; // `else` let attrs = self.parse_outer_attributes()?; // For recovery. - let expr = if self.eat_keyword(kw::If) { + let expr = if self.eat_keyword(exp!(If)) { ensure_sufficient_stack(|| self.parse_expr_if())? - } else if self.check(&TokenKind::OpenDelim(Delimiter::Brace)) { + } else if self.check(exp!(OpenBrace)) { self.parse_simple_block()? } else { let snapshot = self.create_snapshot_for_diagnostic(); @@ -2719,7 +2719,7 @@ impl<'a> Parser<'a> { // while true {} // } // ^ - if self.check(&TokenKind::OpenDelim(Delimiter::Brace)) + if self.check(exp!(OpenBrace)) && (classify::expr_requires_semi_to_be_stmt(&cond) || matches!(cond.kind, ExprKind::MacCall(..))) => @@ -2805,7 +2805,7 @@ impl<'a> Parser<'a> { begin_paren, ) { (Ok(pat), _) => pat, // Happy path. - (Err(err), Some((start_span, left))) if self.eat_keyword(kw::In) => { + (Err(err), Some((start_span, left))) if self.eat_keyword(exp!(In)) => { // We know for sure we have seen `for ($SOMETHING in`. In the happy path this would // happen right before the return of this method. let attrs = self.parse_outer_attributes()?; @@ -2839,7 +2839,7 @@ impl<'a> Parser<'a> { } (Err(err), _) => return Err(err), // Some other error, bubble up. }; - if !self.eat_keyword(kw::In) { + if !self.eat_keyword(exp!(In)) { self.error_missing_in_for_loop(); } self.check_for_for_in_in_typo(self.prev_token.span); @@ -2851,7 +2851,7 @@ impl<'a> Parser<'a> { /// Parses `for await? in ` (`for` token already eaten). fn parse_expr_for(&mut self, opt_label: Option