diff --git a/compiler/rustc_abi/src/lib.rs b/compiler/rustc_abi/src/lib.rs index be42bc84932..4e27ad0c366 100644 --- a/compiler/rustc_abi/src/lib.rs +++ b/compiler/rustc_abi/src/lib.rs @@ -781,6 +781,14 @@ impl Align { } /// A pair of alignments, ABI-mandated and preferred. +/// +/// The "preferred" alignment is an LLVM concept that is virtually meaningless to Rust code: +/// it is not exposed semantically to programmers nor can they meaningfully affect it. +/// The only concern for us is that preferred alignment must not be less than the mandated alignment +/// and thus in practice the two values are almost always identical. +/// +/// An example of a rare thing actually affected by preferred alignment is aligning of statics. +/// It is of effectively no consequence for layout in structs and on the stack. #[derive(Copy, Clone, PartialEq, Eq, Hash, Debug)] #[cfg_attr(feature = "nightly", derive(HashStable_Generic))] pub struct AbiAndPrefAlign { diff --git a/compiler/rustc_arena/src/lib.rs b/compiler/rustc_arena/src/lib.rs index 260c9fe44ba..cecf223b961 100644 --- a/compiler/rustc_arena/src/lib.rs +++ b/compiler/rustc_arena/src/lib.rs @@ -614,34 +614,34 @@ pub macro declare_arena([$($a:tt $name:ident: $ty:ty,)*]) { pub trait ArenaAllocatable<'tcx, C = rustc_arena::IsNotCopy>: Sized { #[allow(clippy::mut_from_ref)] - fn allocate_on<'a>(self, arena: &'a Arena<'tcx>) -> &'a mut Self; + fn allocate_on(self, arena: &'tcx Arena<'tcx>) -> &'tcx mut Self; #[allow(clippy::mut_from_ref)] - fn allocate_from_iter<'a>( - arena: &'a Arena<'tcx>, + fn allocate_from_iter( + arena: &'tcx Arena<'tcx>, iter: impl ::std::iter::IntoIterator, - ) -> &'a mut [Self]; + ) -> &'tcx mut [Self]; } // Any type that impls `Copy` can be arena-allocated in the `DroplessArena`. impl<'tcx, T: Copy> ArenaAllocatable<'tcx, rustc_arena::IsCopy> for T { #[inline] #[allow(clippy::mut_from_ref)] - fn allocate_on<'a>(self, arena: &'a Arena<'tcx>) -> &'a mut Self { + fn allocate_on(self, arena: &'tcx Arena<'tcx>) -> &'tcx mut Self { arena.dropless.alloc(self) } #[inline] #[allow(clippy::mut_from_ref)] - fn allocate_from_iter<'a>( - arena: &'a Arena<'tcx>, + fn allocate_from_iter( + arena: &'tcx Arena<'tcx>, iter: impl ::std::iter::IntoIterator, - ) -> &'a mut [Self] { + ) -> &'tcx mut [Self] { arena.dropless.alloc_from_iter(iter) } } $( impl<'tcx> ArenaAllocatable<'tcx, rustc_arena::IsNotCopy> for $ty { #[inline] - fn allocate_on<'a>(self, arena: &'a Arena<'tcx>) -> &'a mut Self { + fn allocate_on(self, arena: &'tcx Arena<'tcx>) -> &'tcx mut Self { if !::std::mem::needs_drop::() { arena.dropless.alloc(self) } else { @@ -651,10 +651,10 @@ pub macro declare_arena([$($a:tt $name:ident: $ty:ty,)*]) { #[inline] #[allow(clippy::mut_from_ref)] - fn allocate_from_iter<'a>( - arena: &'a Arena<'tcx>, + fn allocate_from_iter( + arena: &'tcx Arena<'tcx>, iter: impl ::std::iter::IntoIterator, - ) -> &'a mut [Self] { + ) -> &'tcx mut [Self] { if !::std::mem::needs_drop::() { arena.dropless.alloc_from_iter(iter) } else { @@ -667,7 +667,7 @@ pub macro declare_arena([$($a:tt $name:ident: $ty:ty,)*]) { impl<'tcx> Arena<'tcx> { #[inline] #[allow(clippy::mut_from_ref)] - pub fn alloc, C>(&self, value: T) -> &mut T { + pub fn alloc, C>(&'tcx self, value: T) -> &mut T { value.allocate_on(self) } @@ -691,7 +691,7 @@ pub macro declare_arena([$($a:tt $name:ident: $ty:ty,)*]) { #[allow(clippy::mut_from_ref)] pub fn alloc_from_iter, C>( - &self, + &'tcx self, iter: impl ::std::iter::IntoIterator, ) -> &mut [T] { T::allocate_from_iter(self, iter) diff --git a/compiler/rustc_ast_passes/src/feature_gate.rs b/compiler/rustc_ast_passes/src/feature_gate.rs index 45e397a58c0..cfc534acd98 100644 --- a/compiler/rustc_ast_passes/src/feature_gate.rs +++ b/compiler/rustc_ast_passes/src/feature_gate.rs @@ -75,22 +75,9 @@ struct PostExpansionVisitor<'a> { impl<'a> PostExpansionVisitor<'a> { #[allow(rustc::untranslatable_diagnostic)] // FIXME: make this translatable - fn check_abi(&self, abi: ast::StrLit, constness: ast::Const) { + fn check_abi(&self, abi: ast::StrLit) { let ast::StrLit { symbol_unescaped, span, .. } = abi; - if let ast::Const::Yes(_) = constness { - match symbol_unescaped { - // Stable - sym::Rust | sym::C => {} - abi => gate!( - &self, - const_extern_fn, - span, - format!("`{}` as a `const fn` ABI is unstable", abi) - ), - } - } - match abi::is_enabled(self.features, span, symbol_unescaped.as_str()) { Ok(()) => (), Err(abi::AbiDisabled::Unstable { feature, explain }) => { @@ -110,9 +97,9 @@ impl<'a> PostExpansionVisitor<'a> { } } - fn check_extern(&self, ext: ast::Extern, constness: ast::Const) { + fn check_extern(&self, ext: ast::Extern) { if let ast::Extern::Explicit(abi, _) = ext { - self.check_abi(abi, constness); + self.check_abi(abi); } } @@ -239,7 +226,7 @@ impl<'a> Visitor<'a> for PostExpansionVisitor<'a> { match &i.kind { ast::ItemKind::ForeignMod(foreign_module) => { if let Some(abi) = foreign_module.abi { - self.check_abi(abi, ast::Const::No); + self.check_abi(abi); } } @@ -341,7 +328,7 @@ impl<'a> Visitor<'a> for PostExpansionVisitor<'a> { match &ty.kind { ast::TyKind::BareFn(bare_fn_ty) => { // Function pointers cannot be `const` - self.check_extern(bare_fn_ty.ext, ast::Const::No); + self.check_extern(bare_fn_ty.ext); self.check_late_bound_lifetime_defs(&bare_fn_ty.generic_params); } ast::TyKind::Never => { @@ -446,7 +433,7 @@ impl<'a> Visitor<'a> for PostExpansionVisitor<'a> { fn visit_fn(&mut self, fn_kind: FnKind<'a>, span: Span, _: NodeId) { if let Some(header) = fn_kind.header() { // Stability of const fn methods are covered in `visit_assoc_item` below. - self.check_extern(header.ext, header.constness); + self.check_extern(header.ext); } if let FnKind::Closure(ast::ClosureBinder::For { generic_params, .. }, ..) = fn_kind { diff --git a/compiler/rustc_borrowck/src/constraints/graph.rs b/compiler/rustc_borrowck/src/constraints/graph.rs index 0ae837898b9..9d500586f08 100644 --- a/compiler/rustc_borrowck/src/constraints/graph.rs +++ b/compiler/rustc_borrowck/src/constraints/graph.rs @@ -97,11 +97,11 @@ impl ConstraintGraph { /// Given the constraint set from which this graph was built /// creates a region graph so that you can iterate over *regions* /// and not constraints. - pub(crate) fn region_graph<'rg, 'tcx>( - &'rg self, - set: &'rg OutlivesConstraintSet<'tcx>, + pub(crate) fn region_graph<'a, 'tcx>( + &'a self, + set: &'a OutlivesConstraintSet<'tcx>, static_region: RegionVid, - ) -> RegionGraph<'rg, 'tcx, D> { + ) -> RegionGraph<'a, 'tcx, D> { RegionGraph::new(set, self, static_region) } @@ -130,15 +130,15 @@ impl ConstraintGraph { } } -pub(crate) struct Edges<'s, 'tcx, D: ConstraintGraphDirection> { - graph: &'s ConstraintGraph, - constraints: &'s OutlivesConstraintSet<'tcx>, +pub(crate) struct Edges<'a, 'tcx, D: ConstraintGraphDirection> { + graph: &'a ConstraintGraph, + constraints: &'a OutlivesConstraintSet<'tcx>, pointer: Option, next_static_idx: Option, static_region: RegionVid, } -impl<'s, 'tcx, D: ConstraintGraphDirection> Iterator for Edges<'s, 'tcx, D> { +impl<'a, 'tcx, D: ConstraintGraphDirection> Iterator for Edges<'a, 'tcx, D> { type Item = OutlivesConstraint<'tcx>; fn next(&mut self) -> Option { @@ -171,20 +171,20 @@ impl<'s, 'tcx, D: ConstraintGraphDirection> Iterator for Edges<'s, 'tcx, D> { /// This struct brings together a constraint set and a (normal, not /// reverse) constraint graph. It implements the graph traits and is /// usd for doing the SCC computation. -pub(crate) struct RegionGraph<'s, 'tcx, D: ConstraintGraphDirection> { - set: &'s OutlivesConstraintSet<'tcx>, - constraint_graph: &'s ConstraintGraph, +pub(crate) struct RegionGraph<'a, 'tcx, D: ConstraintGraphDirection> { + set: &'a OutlivesConstraintSet<'tcx>, + constraint_graph: &'a ConstraintGraph, static_region: RegionVid, } -impl<'s, 'tcx, D: ConstraintGraphDirection> RegionGraph<'s, 'tcx, D> { +impl<'a, 'tcx, D: ConstraintGraphDirection> RegionGraph<'a, 'tcx, D> { /// Creates a "dependency graph" where each region constraint `R1: /// R2` is treated as an edge `R1 -> R2`. We use this graph to /// construct SCCs for region inference but also for error /// reporting. pub(crate) fn new( - set: &'s OutlivesConstraintSet<'tcx>, - constraint_graph: &'s ConstraintGraph, + set: &'a OutlivesConstraintSet<'tcx>, + constraint_graph: &'a ConstraintGraph, static_region: RegionVid, ) -> Self { Self { set, constraint_graph, static_region } @@ -192,18 +192,18 @@ impl<'s, 'tcx, D: ConstraintGraphDirection> RegionGraph<'s, 'tcx, D> { /// Given a region `R`, iterate over all regions `R1` such that /// there exists a constraint `R: R1`. - pub(crate) fn outgoing_regions(&self, region_sup: RegionVid) -> Successors<'s, 'tcx, D> { + pub(crate) fn outgoing_regions(&self, region_sup: RegionVid) -> Successors<'a, 'tcx, D> { Successors { edges: self.constraint_graph.outgoing_edges(region_sup, self.set, self.static_region), } } } -pub(crate) struct Successors<'s, 'tcx, D: ConstraintGraphDirection> { - edges: Edges<'s, 'tcx, D>, +pub(crate) struct Successors<'a, 'tcx, D: ConstraintGraphDirection> { + edges: Edges<'a, 'tcx, D>, } -impl<'s, 'tcx, D: ConstraintGraphDirection> Iterator for Successors<'s, 'tcx, D> { +impl<'a, 'tcx, D: ConstraintGraphDirection> Iterator for Successors<'a, 'tcx, D> { type Item = RegionVid; fn next(&mut self) -> Option { @@ -211,7 +211,7 @@ impl<'s, 'tcx, D: ConstraintGraphDirection> Iterator for Successors<'s, 'tcx, D> } } -impl<'s, 'tcx, D: ConstraintGraphDirection> graph::DirectedGraph for RegionGraph<'s, 'tcx, D> { +impl<'a, 'tcx, D: ConstraintGraphDirection> graph::DirectedGraph for RegionGraph<'a, 'tcx, D> { type Node = RegionVid; fn num_nodes(&self) -> usize { @@ -219,7 +219,7 @@ impl<'s, 'tcx, D: ConstraintGraphDirection> graph::DirectedGraph for RegionGraph } } -impl<'s, 'tcx, D: ConstraintGraphDirection> graph::Successors for RegionGraph<'s, 'tcx, D> { +impl<'a, 'tcx, D: ConstraintGraphDirection> graph::Successors for RegionGraph<'a, 'tcx, D> { fn successors(&self, node: Self::Node) -> impl Iterator { self.outgoing_regions(node) } diff --git a/compiler/rustc_borrowck/src/dataflow.rs b/compiler/rustc_borrowck/src/dataflow.rs index 6725920746b..5e1043ec817 100644 --- a/compiler/rustc_borrowck/src/dataflow.rs +++ b/compiler/rustc_borrowck/src/dataflow.rs @@ -112,16 +112,16 @@ pub struct Borrows<'a, 'tcx> { borrows_out_of_scope_at_location: FxIndexMap>, } -struct OutOfScopePrecomputer<'mir, 'tcx> { +struct OutOfScopePrecomputer<'a, 'tcx> { visited: BitSet, visit_stack: Vec, - body: &'mir Body<'tcx>, - regioncx: &'mir RegionInferenceContext<'tcx>, + body: &'a Body<'tcx>, + regioncx: &'a RegionInferenceContext<'tcx>, borrows_out_of_scope_at_location: FxIndexMap>, } -impl<'mir, 'tcx> OutOfScopePrecomputer<'mir, 'tcx> { - fn new(body: &'mir Body<'tcx>, regioncx: &'mir RegionInferenceContext<'tcx>) -> Self { +impl<'a, 'tcx> OutOfScopePrecomputer<'a, 'tcx> { + fn new(body: &'a Body<'tcx>, regioncx: &'a RegionInferenceContext<'tcx>) -> Self { OutOfScopePrecomputer { visited: BitSet::new_empty(body.basic_blocks.len()), visit_stack: vec![], @@ -224,17 +224,17 @@ pub fn calculate_borrows_out_of_scope_at_location<'tcx>( prec.borrows_out_of_scope_at_location } -struct PoloniusOutOfScopePrecomputer<'mir, 'tcx> { +struct PoloniusOutOfScopePrecomputer<'a, 'tcx> { visited: BitSet, visit_stack: Vec, - body: &'mir Body<'tcx>, - regioncx: &'mir RegionInferenceContext<'tcx>, + body: &'a Body<'tcx>, + regioncx: &'a RegionInferenceContext<'tcx>, loans_out_of_scope_at_location: FxIndexMap>, } -impl<'mir, 'tcx> PoloniusOutOfScopePrecomputer<'mir, 'tcx> { - fn new(body: &'mir Body<'tcx>, regioncx: &'mir RegionInferenceContext<'tcx>) -> Self { +impl<'a, 'tcx> PoloniusOutOfScopePrecomputer<'a, 'tcx> { + fn new(body: &'a Body<'tcx>, regioncx: &'a RegionInferenceContext<'tcx>) -> Self { Self { visited: BitSet::new_empty(body.basic_blocks.len()), visit_stack: vec![], diff --git a/compiler/rustc_borrowck/src/diagnostics/conflict_errors.rs b/compiler/rustc_borrowck/src/diagnostics/conflict_errors.rs index 4a31aee5c96..c7a5d516ad7 100644 --- a/compiler/rustc_borrowck/src/diagnostics/conflict_errors.rs +++ b/compiler/rustc_borrowck/src/diagnostics/conflict_errors.rs @@ -3553,7 +3553,7 @@ impl<'infcx, 'tcx> MirBorrowckCtxt<'_, 'infcx, 'tcx> { location: Location, mpi: MovePathIndex, ) -> (Vec, Vec) { - fn predecessor_locations<'tcx, 'a>( + fn predecessor_locations<'a, 'tcx>( body: &'a mir::Body<'tcx>, location: Location, ) -> impl Iterator + Captures<'tcx> + 'a { diff --git a/compiler/rustc_borrowck/src/diagnostics/find_use.rs b/compiler/rustc_borrowck/src/diagnostics/find_use.rs index bea8d3bfdfb..d8fa5506a99 100644 --- a/compiler/rustc_borrowck/src/diagnostics/find_use.rs +++ b/compiler/rustc_borrowck/src/diagnostics/find_use.rs @@ -21,15 +21,15 @@ pub(crate) fn find<'tcx>( uf.find() } -struct UseFinder<'cx, 'tcx> { - body: &'cx Body<'tcx>, - regioncx: &'cx Rc>, +struct UseFinder<'a, 'tcx> { + body: &'a Body<'tcx>, + regioncx: &'a Rc>, tcx: TyCtxt<'tcx>, region_vid: RegionVid, start_point: Location, } -impl<'cx, 'tcx> UseFinder<'cx, 'tcx> { +impl<'a, 'tcx> UseFinder<'a, 'tcx> { fn find(&mut self) -> Option { let mut queue = VecDeque::new(); let mut visited = FxIndexSet::default(); @@ -93,8 +93,8 @@ impl<'cx, 'tcx> UseFinder<'cx, 'tcx> { } } -struct DefUseVisitor<'cx, 'tcx> { - body: &'cx Body<'tcx>, +struct DefUseVisitor<'a, 'tcx> { + body: &'a Body<'tcx>, tcx: TyCtxt<'tcx>, region_vid: RegionVid, def_use_result: Option, @@ -106,7 +106,7 @@ enum DefUseResult { UseDrop { local: Local }, } -impl<'cx, 'tcx> Visitor<'tcx> for DefUseVisitor<'cx, 'tcx> { +impl<'a, 'tcx> Visitor<'tcx> for DefUseVisitor<'a, 'tcx> { fn visit_local(&mut self, local: Local, context: PlaceContext, _: Location) { let local_ty = self.body.local_decls[local].ty; diff --git a/compiler/rustc_borrowck/src/diagnostics/mutability_errors.rs b/compiler/rustc_borrowck/src/diagnostics/mutability_errors.rs index 6e3fac1e680..2bbafb0163e 100644 --- a/compiler/rustc_borrowck/src/diagnostics/mutability_errors.rs +++ b/compiler/rustc_borrowck/src/diagnostics/mutability_errors.rs @@ -558,7 +558,7 @@ impl<'infcx, 'tcx> MirBorrowckCtxt<'_, 'infcx, 'tcx> { ty: Ty<'tcx>, suggested: bool, } - impl<'a, 'cx, 'tcx> Visitor<'tcx> for SuggestIndexOperatorAlternativeVisitor<'a, 'cx, 'tcx> { + impl<'a, 'infcx, 'tcx> Visitor<'tcx> for SuggestIndexOperatorAlternativeVisitor<'a, 'infcx, 'tcx> { fn visit_stmt(&mut self, stmt: &'tcx hir::Stmt<'tcx>) { hir::intravisit::walk_stmt(self, stmt); let expr = match stmt.kind { diff --git a/compiler/rustc_borrowck/src/polonius/loan_invalidations.rs b/compiler/rustc_borrowck/src/polonius/loan_invalidations.rs index 0b9b8768b56..afd811a0efb 100644 --- a/compiler/rustc_borrowck/src/polonius/loan_invalidations.rs +++ b/compiler/rustc_borrowck/src/polonius/loan_invalidations.rs @@ -32,18 +32,18 @@ pub(super) fn emit_loan_invalidations<'tcx>( visitor.visit_body(body); } -struct LoanInvalidationsGenerator<'cx, 'tcx> { +struct LoanInvalidationsGenerator<'a, 'tcx> { tcx: TyCtxt<'tcx>, - all_facts: &'cx mut AllFacts, - location_table: &'cx LocationTable, - body: &'cx Body<'tcx>, - dominators: &'cx Dominators, - borrow_set: &'cx BorrowSet<'tcx>, + all_facts: &'a mut AllFacts, + location_table: &'a LocationTable, + body: &'a Body<'tcx>, + dominators: &'a Dominators, + borrow_set: &'a BorrowSet<'tcx>, } /// Visits the whole MIR and generates `invalidates()` facts. /// Most of the code implementing this was stolen from `borrow_check/mod.rs`. -impl<'cx, 'tcx> Visitor<'tcx> for LoanInvalidationsGenerator<'cx, 'tcx> { +impl<'a, 'tcx> Visitor<'tcx> for LoanInvalidationsGenerator<'a, 'tcx> { fn visit_statement(&mut self, statement: &Statement<'tcx>, location: Location) { self.check_activations(location); @@ -212,7 +212,7 @@ impl<'cx, 'tcx> Visitor<'tcx> for LoanInvalidationsGenerator<'cx, 'tcx> { } } -impl<'cx, 'tcx> LoanInvalidationsGenerator<'cx, 'tcx> { +impl<'a, 'tcx> LoanInvalidationsGenerator<'a, 'tcx> { /// Simulates mutation of a place. fn mutate_place(&mut self, location: Location, place: Place<'tcx>, kind: AccessDepth) { self.access_place( diff --git a/compiler/rustc_borrowck/src/polonius/loan_kills.rs b/compiler/rustc_borrowck/src/polonius/loan_kills.rs index ed9f714e500..68e0865ab82 100644 --- a/compiler/rustc_borrowck/src/polonius/loan_kills.rs +++ b/compiler/rustc_borrowck/src/polonius/loan_kills.rs @@ -25,15 +25,15 @@ pub(super) fn emit_loan_kills<'tcx>( } } -struct LoanKillsGenerator<'cx, 'tcx> { +struct LoanKillsGenerator<'a, 'tcx> { tcx: TyCtxt<'tcx>, - all_facts: &'cx mut AllFacts, - location_table: &'cx LocationTable, - borrow_set: &'cx BorrowSet<'tcx>, - body: &'cx Body<'tcx>, + all_facts: &'a mut AllFacts, + location_table: &'a LocationTable, + borrow_set: &'a BorrowSet<'tcx>, + body: &'a Body<'tcx>, } -impl<'cx, 'tcx> Visitor<'tcx> for LoanKillsGenerator<'cx, 'tcx> { +impl<'a, 'tcx> Visitor<'tcx> for LoanKillsGenerator<'a, 'tcx> { fn visit_statement(&mut self, statement: &Statement<'tcx>, location: Location) { // Also record CFG facts here. self.all_facts.cfg_edge.push(( diff --git a/compiler/rustc_borrowck/src/type_check/free_region_relations.rs b/compiler/rustc_borrowck/src/type_check/free_region_relations.rs index 33cdb1b1f37..c711190cb97 100644 --- a/compiler/rustc_borrowck/src/type_check/free_region_relations.rs +++ b/compiler/rustc_borrowck/src/type_check/free_region_relations.rs @@ -181,12 +181,12 @@ impl UniversalRegionRelations<'_> { } } -struct UniversalRegionRelationsBuilder<'this, 'tcx> { - infcx: &'this InferCtxt<'tcx>, +struct UniversalRegionRelationsBuilder<'a, 'tcx> { + infcx: &'a InferCtxt<'tcx>, param_env: ty::ParamEnv<'tcx>, universal_regions: Rc>, implicit_region_bound: ty::Region<'tcx>, - constraints: &'this mut MirTypeckRegionConstraints<'tcx>, + constraints: &'a mut MirTypeckRegionConstraints<'tcx>, // outputs: outlives: TransitiveRelationBuilder, diff --git a/compiler/rustc_borrowck/src/type_check/liveness/mod.rs b/compiler/rustc_borrowck/src/type_check/liveness/mod.rs index 79db8f4252b..a73467824de 100644 --- a/compiler/rustc_borrowck/src/type_check/liveness/mod.rs +++ b/compiler/rustc_borrowck/src/type_check/liveness/mod.rs @@ -148,12 +148,12 @@ fn record_regular_live_regions<'tcx>( } /// Visitor looking for regions that should be live within rvalues or calls. -struct LiveVariablesVisitor<'cx, 'tcx> { +struct LiveVariablesVisitor<'a, 'tcx> { tcx: TyCtxt<'tcx>, - liveness_constraints: &'cx mut LivenessValues, + liveness_constraints: &'a mut LivenessValues, } -impl<'cx, 'tcx> Visitor<'tcx> for LiveVariablesVisitor<'cx, 'tcx> { +impl<'a, 'tcx> Visitor<'tcx> for LiveVariablesVisitor<'a, 'tcx> { /// We sometimes have `args` within an rvalue, or within a /// call. Make them live at the location where they appear. fn visit_args(&mut self, args: &GenericArgsRef<'tcx>, location: Location) { @@ -188,7 +188,7 @@ impl<'cx, 'tcx> Visitor<'tcx> for LiveVariablesVisitor<'cx, 'tcx> { } } -impl<'cx, 'tcx> LiveVariablesVisitor<'cx, 'tcx> { +impl<'a, 'tcx> LiveVariablesVisitor<'a, 'tcx> { /// Some variable is "regular live" at `location` -- i.e., it may be used later. This means that /// all regions appearing in the type of `value` must be live at `location`. fn record_regions_live_at(&mut self, value: T, location: Location) diff --git a/compiler/rustc_borrowck/src/type_check/liveness/polonius.rs b/compiler/rustc_borrowck/src/type_check/liveness/polonius.rs index 7f6aabf8841..3a458731f28 100644 --- a/compiler/rustc_borrowck/src/type_check/liveness/polonius.rs +++ b/compiler/rustc_borrowck/src/type_check/liveness/polonius.rs @@ -11,13 +11,13 @@ use crate::location::{LocationIndex, LocationTable}; type VarPointRelation = Vec<(Local, LocationIndex)>; type PathPointRelation = Vec<(MovePathIndex, LocationIndex)>; -struct UseFactsExtractor<'me, 'tcx> { - var_defined_at: &'me mut VarPointRelation, - var_used_at: &'me mut VarPointRelation, - location_table: &'me LocationTable, - var_dropped_at: &'me mut VarPointRelation, - move_data: &'me MoveData<'tcx>, - path_accessed_at_base: &'me mut PathPointRelation, +struct UseFactsExtractor<'a, 'tcx> { + var_defined_at: &'a mut VarPointRelation, + var_used_at: &'a mut VarPointRelation, + location_table: &'a LocationTable, + var_dropped_at: &'a mut VarPointRelation, + move_data: &'a MoveData<'tcx>, + path_accessed_at_base: &'a mut PathPointRelation, } // A Visitor to walk through the MIR and extract point-wise facts diff --git a/compiler/rustc_borrowck/src/type_check/relate_tys.rs b/compiler/rustc_borrowck/src/type_check/relate_tys.rs index 421f4e2efe0..71892a67ffc 100644 --- a/compiler/rustc_borrowck/src/type_check/relate_tys.rs +++ b/compiler/rustc_borrowck/src/type_check/relate_tys.rs @@ -58,8 +58,8 @@ impl<'a, 'tcx> TypeChecker<'a, 'tcx> { } } -struct NllTypeRelating<'me, 'bccx, 'tcx> { - type_checker: &'me mut TypeChecker<'bccx, 'tcx>, +struct NllTypeRelating<'a, 'b, 'tcx> { + type_checker: &'a mut TypeChecker<'b, 'tcx>, /// Where (and why) is this relation taking place? locations: Locations, @@ -82,9 +82,9 @@ struct NllTypeRelating<'me, 'bccx, 'tcx> { ambient_variance_info: ty::VarianceDiagInfo>, } -impl<'me, 'bccx, 'tcx> NllTypeRelating<'me, 'bccx, 'tcx> { +impl<'a, 'b, 'tcx> NllTypeRelating<'a, 'b, 'tcx> { fn new( - type_checker: &'me mut TypeChecker<'bccx, 'tcx>, + type_checker: &'a mut TypeChecker<'b, 'tcx>, locations: Locations, category: ConstraintCategory<'tcx>, universe_info: UniverseInfo<'tcx>, @@ -309,7 +309,7 @@ impl<'me, 'bccx, 'tcx> NllTypeRelating<'me, 'bccx, 'tcx> { } } -impl<'bccx, 'tcx> TypeRelation> for NllTypeRelating<'_, 'bccx, 'tcx> { +impl<'b, 'tcx> TypeRelation> for NllTypeRelating<'_, 'b, 'tcx> { fn cx(&self) -> TyCtxt<'tcx> { self.type_checker.infcx.tcx } @@ -520,7 +520,7 @@ impl<'bccx, 'tcx> TypeRelation> for NllTypeRelating<'_, 'bccx, 'tcx } } -impl<'bccx, 'tcx> PredicateEmittingRelation> for NllTypeRelating<'_, 'bccx, 'tcx> { +impl<'b, 'tcx> PredicateEmittingRelation> for NllTypeRelating<'_, 'b, 'tcx> { fn span(&self) -> Span { self.locations.span(self.type_checker.body) } diff --git a/compiler/rustc_builtin_macros/src/global_allocator.rs b/compiler/rustc_builtin_macros/src/global_allocator.rs index 734da318ac1..66df393b501 100644 --- a/compiler/rustc_builtin_macros/src/global_allocator.rs +++ b/compiler/rustc_builtin_macros/src/global_allocator.rs @@ -65,7 +65,7 @@ struct AllocFnFactory<'a, 'b> { span: Span, ty_span: Span, global: Ident, - cx: &'b ExtCtxt<'a>, + cx: &'a ExtCtxt<'b>, } impl AllocFnFactory<'_, '_> { diff --git a/compiler/rustc_codegen_cranelift/src/intrinsics/simd.rs b/compiler/rustc_codegen_cranelift/src/intrinsics/simd.rs index 604a88393fd..a5621aec244 100644 --- a/compiler/rustc_codegen_cranelift/src/intrinsics/simd.rs +++ b/compiler/rustc_codegen_cranelift/src/intrinsics/simd.rs @@ -180,34 +180,20 @@ pub(super) fn codegen_simd_intrinsic_call<'tcx>( return; } - // Make sure this is actually an array, since typeck only checks the length-suffixed - // version of this intrinsic. + // Make sure this is actually a SIMD vector. let idx_ty = fx.monomorphize(idx.node.ty(fx.mir, fx.tcx)); - let n: u16 = match idx_ty.kind() { - ty::Array(ty, len) if matches!(ty.kind(), ty::Uint(ty::UintTy::U32)) => len - .try_eval_target_usize(fx.tcx, ty::ParamEnv::reveal_all()) - .unwrap_or_else(|| { - span_bug!(span, "could not evaluate shuffle index array length") - }) - .try_into() - .unwrap(), - _ if idx_ty.is_simd() - && matches!( - idx_ty.simd_size_and_type(fx.tcx).1.kind(), - ty::Uint(ty::UintTy::U32) - ) => - { - idx_ty.simd_size_and_type(fx.tcx).0.try_into().unwrap() - } - _ => { - fx.tcx.dcx().span_err( - span, - format!("simd_shuffle index must be an array of `u32`, got `{}`", idx_ty), - ); - // Prevent verifier error - fx.bcx.ins().trap(TrapCode::UnreachableCodeReached); - return; - } + let n: u16 = if idx_ty.is_simd() + && matches!(idx_ty.simd_size_and_type(fx.tcx).1.kind(), ty::Uint(ty::UintTy::U32)) + { + idx_ty.simd_size_and_type(fx.tcx).0.try_into().unwrap() + } else { + fx.tcx.dcx().span_err( + span, + format!("simd_shuffle index must be a SIMD vector of `u32`, got `{}`", idx_ty), + ); + // Prevent verifier error + fx.bcx.ins().trap(TrapCode::UnreachableCodeReached); + return; }; assert_eq!(x.layout(), y.layout()); diff --git a/compiler/rustc_codegen_gcc/src/builder.rs b/compiler/rustc_codegen_gcc/src/builder.rs index 6ba678e2e7c..31d778823e0 100644 --- a/compiler/rustc_codegen_gcc/src/builder.rs +++ b/compiler/rustc_codegen_gcc/src/builder.rs @@ -1939,33 +1939,18 @@ impl<'a, 'gcc, 'tcx> Builder<'a, 'gcc, 'tcx> { self.int_type }; - let mut mask_elements = if let Some(vector_type) = mask.get_type().dyncast_vector() { - let mask_num_units = vector_type.get_num_units(); - let mut mask_elements = vec![]; - for i in 0..mask_num_units { - let index = self.context.new_rvalue_from_long(self.cx.type_u32(), i as _); - mask_elements.push(self.context.new_cast( - self.location, - self.extract_element(mask, index).to_rvalue(), - mask_element_type, - )); - } - mask_elements - } else { - let struct_type = mask.get_type().is_struct().expect("mask should be of struct type"); - let mask_num_units = struct_type.get_field_count(); - let mut mask_elements = vec![]; - for i in 0..mask_num_units { - let field = struct_type.get_field(i as i32); - mask_elements.push(self.context.new_cast( - self.location, - mask.access_field(self.location, field).to_rvalue(), - mask_element_type, - )); - } - mask_elements - }; - let mask_num_units = mask_elements.len(); + let vector_type = + mask.get_type().dyncast_vector().expect("simd_shuffle mask should be of vector type"); + let mask_num_units = vector_type.get_num_units(); + let mut mask_elements = vec![]; + for i in 0..mask_num_units { + let index = self.context.new_rvalue_from_long(self.cx.type_u32(), i as _); + mask_elements.push(self.context.new_cast( + self.location, + self.extract_element(mask, index).to_rvalue(), + mask_element_type, + )); + } // NOTE: the mask needs to be the same length as the input vectors, so add the missing // elements in the mask if needed. diff --git a/compiler/rustc_codegen_gcc/src/intrinsic/simd.rs b/compiler/rustc_codegen_gcc/src/intrinsic/simd.rs index 96a833ccaf2..2eabc1430db 100644 --- a/compiler/rustc_codegen_gcc/src/intrinsic/simd.rs +++ b/compiler/rustc_codegen_gcc/src/intrinsic/simd.rs @@ -14,7 +14,6 @@ use rustc_codegen_ssa::traits::{BaseTypeMethods, BuilderMethods}; #[cfg(feature = "master")] use rustc_hir as hir; use rustc_middle::mir::BinOp; -use rustc_middle::span_bug; use rustc_middle::ty::layout::HasTyCtxt; use rustc_middle::ty::{self, Ty}; use rustc_span::{sym, Span, Symbol}; @@ -353,24 +352,14 @@ pub fn generic_simd_intrinsic<'a, 'gcc, 'tcx>( } if name == sym::simd_shuffle { - // Make sure this is actually an array or SIMD vector, since typeck only checks the length-suffixed - // version of this intrinsic. + // Make sure this is actually a SIMD vector. let idx_ty = args[2].layout.ty; - let n: u64 = match idx_ty.kind() { - ty::Array(ty, len) if matches!(*ty.kind(), ty::Uint(ty::UintTy::U32)) => { - len.try_eval_target_usize(bx.cx.tcx, ty::ParamEnv::reveal_all()).unwrap_or_else( - || span_bug!(span, "could not evaluate shuffle index array length"), - ) - } - _ if idx_ty.is_simd() - && matches!( - idx_ty.simd_size_and_type(bx.cx.tcx).1.kind(), - ty::Uint(ty::UintTy::U32) - ) => - { - idx_ty.simd_size_and_type(bx.cx.tcx).0 - } - _ => return_error!(InvalidMonomorphization::SimdShuffle { span, name, ty: idx_ty }), + let n: u64 = if idx_ty.is_simd() + && matches!(idx_ty.simd_size_and_type(bx.cx.tcx).1.kind(), ty::Uint(ty::UintTy::U32)) + { + idx_ty.simd_size_and_type(bx.cx.tcx).0 + } else { + return_error!(InvalidMonomorphization::SimdShuffle { span, name, ty: idx_ty }) }; require_simd!(ret_ty, InvalidMonomorphization::SimdReturn { span, name, ty: ret_ty }); diff --git a/compiler/rustc_codegen_llvm/src/back/write.rs b/compiler/rustc_codegen_llvm/src/back/write.rs index a5c27d2282e..b1b692cc027 100644 --- a/compiler/rustc_codegen_llvm/src/back/write.rs +++ b/compiler/rustc_codegen_llvm/src/back/write.rs @@ -185,7 +185,13 @@ pub(crate) fn target_machine_factory( let reloc_model = to_llvm_relocation_model(sess.relocation_model()); let (opt_level, _) = to_llvm_opt_settings(optlvl); - let use_softfp = sess.opts.cg.soft_float; + let use_softfp = if sess.target.arch == "arm" && sess.target.abi == "eabihf" { + sess.opts.cg.soft_float + } else { + // `validate_commandline_args_with_session_available` has already warned about this being ignored. + // Let's make sure LLVM doesn't suddenly start using this flag on more targets. + false + }; let ffunction_sections = sess.opts.unstable_opts.function_sections.unwrap_or(sess.target.function_sections); diff --git a/compiler/rustc_codegen_llvm/src/intrinsic.rs b/compiler/rustc_codegen_llvm/src/intrinsic.rs index 05fb77a193a..9705dd506b9 100644 --- a/compiler/rustc_codegen_llvm/src/intrinsic.rs +++ b/compiler/rustc_codegen_llvm/src/intrinsic.rs @@ -573,6 +573,8 @@ impl<'ll, 'tcx> IntrinsicCallMethods<'tcx> for Builder<'_, 'll, 'tcx> { span, ) { Ok(llval) => llval, + // If there was an error, just skip this invocation... we'll abort compilation anyway, + // but we can keep codegen'ing to find more errors. Err(()) => return Ok(()), } } @@ -1290,24 +1292,14 @@ fn generic_simd_intrinsic<'ll, 'tcx>( } if name == sym::simd_shuffle { - // Make sure this is actually an array or SIMD vector, since typeck only checks the length-suffixed - // version of this intrinsic. + // Make sure this is actually a SIMD vector. let idx_ty = args[2].layout.ty; - let n: u64 = match idx_ty.kind() { - ty::Array(ty, len) if matches!(ty.kind(), ty::Uint(ty::UintTy::U32)) => { - len.try_eval_target_usize(bx.cx.tcx, ty::ParamEnv::reveal_all()).unwrap_or_else( - || span_bug!(span, "could not evaluate shuffle index array length"), - ) - } - _ if idx_ty.is_simd() - && matches!( - idx_ty.simd_size_and_type(bx.cx.tcx).1.kind(), - ty::Uint(ty::UintTy::U32) - ) => - { - idx_ty.simd_size_and_type(bx.cx.tcx).0 - } - _ => return_error!(InvalidMonomorphization::SimdShuffle { span, name, ty: idx_ty }), + let n: u64 = if idx_ty.is_simd() + && matches!(idx_ty.simd_size_and_type(bx.cx.tcx).1.kind(), ty::Uint(ty::UintTy::U32)) + { + idx_ty.simd_size_and_type(bx.cx.tcx).0 + } else { + return_error!(InvalidMonomorphization::SimdShuffle { span, name, ty: idx_ty }) }; let (out_len, out_ty) = require_simd!(ret_ty, SimdReturn); @@ -1322,38 +1314,24 @@ fn generic_simd_intrinsic<'ll, 'tcx>( let total_len = u128::from(in_len) * 2; - let vector = args[2].immediate(); + // Check that the indices are in-bounds. + let indices = args[2].immediate(); + for i in 0..n { + let val = bx.const_get_elt(indices, i as u64); + let idx = bx + .const_to_opt_u128(val, true) + .unwrap_or_else(|| bug!("typeck should have already ensured that these are const")); + if idx >= total_len { + return_error!(InvalidMonomorphization::SimdIndexOutOfBounds { + span, + name, + arg_idx: i, + total_len, + }); + } + } - let indices: Option> = (0..n) - .map(|i| { - let arg_idx = i; - let val = bx.const_get_elt(vector, i as u64); - match bx.const_to_opt_u128(val, true) { - None => { - bug!("typeck should have already ensured that these are const") - } - Some(idx) if idx >= total_len => { - bx.sess().dcx().emit_err(InvalidMonomorphization::SimdIndexOutOfBounds { - span, - name, - arg_idx, - total_len, - }); - None - } - Some(idx) => Some(bx.const_i32(idx as i32)), - } - }) - .collect(); - let Some(indices) = indices else { - return Ok(bx.const_null(llret_ty)); - }; - - return Ok(bx.shuffle_vector( - args[0].immediate(), - args[1].immediate(), - bx.const_vector(&indices), - )); + return Ok(bx.shuffle_vector(args[0].immediate(), args[1].immediate(), indices)); } if name == sym::simd_insert { @@ -1371,13 +1349,12 @@ fn generic_simd_intrinsic<'ll, 'tcx>( .const_to_opt_u128(args[1].immediate(), false) .expect("typeck should have ensure that this is a const"); if idx >= in_len.into() { - bx.sess().dcx().emit_err(InvalidMonomorphization::SimdIndexOutOfBounds { + return_error!(InvalidMonomorphization::SimdIndexOutOfBounds { span, name, arg_idx: 1, total_len: in_len.into(), }); - return Ok(bx.const_null(llret_ty)); } return Ok(bx.insert_element( args[0].immediate(), @@ -1394,13 +1371,12 @@ fn generic_simd_intrinsic<'ll, 'tcx>( .const_to_opt_u128(args[1].immediate(), false) .expect("typeck should have ensure that this is a const"); if idx >= in_len.into() { - bx.sess().dcx().emit_err(InvalidMonomorphization::SimdIndexOutOfBounds { + return_error!(InvalidMonomorphization::SimdIndexOutOfBounds { span, name, arg_idx: 1, total_len: in_len.into(), }); - return Ok(bx.const_null(llret_ty)); } return Ok(bx.extract_element(args[0].immediate(), bx.const_i32(idx as i32))); } diff --git a/compiler/rustc_codegen_ssa/messages.ftl b/compiler/rustc_codegen_ssa/messages.ftl index 8a6a2acd87d..9091602d75b 100644 --- a/compiler/rustc_codegen_ssa/messages.ftl +++ b/compiler/rustc_codegen_ssa/messages.ftl @@ -132,7 +132,7 @@ codegen_ssa_invalid_monomorphization_simd_return = invalid monomorphization of ` codegen_ssa_invalid_monomorphization_simd_second = invalid monomorphization of `{$name}` intrinsic: expected SIMD second type, found non-SIMD `{$ty}` -codegen_ssa_invalid_monomorphization_simd_shuffle = invalid monomorphization of `{$name}` intrinsic: simd_shuffle index must be an array of `u32`, got `{$ty}` +codegen_ssa_invalid_monomorphization_simd_shuffle = invalid monomorphization of `{$name}` intrinsic: simd_shuffle index must be a SIMD vector of `u32`, got `{$ty}` codegen_ssa_invalid_monomorphization_simd_third = invalid monomorphization of `{$name}` intrinsic: expected SIMD third type, found non-SIMD `{$ty}` diff --git a/compiler/rustc_codegen_ssa/src/back/link.rs b/compiler/rustc_codegen_ssa/src/back/link.rs index 40eb35deea5..8b855bd0dd5 100644 --- a/compiler/rustc_codegen_ssa/src/back/link.rs +++ b/compiler/rustc_codegen_ssa/src/back/link.rs @@ -3044,7 +3044,7 @@ fn get_apple_sdk_root(sdk_name: &str) -> Result { } - "macosx10.15" + "macosx" if sdkroot.contains("iPhoneOS.platform") || sdkroot.contains("iPhoneSimulator.platform") => {} "watchos" diff --git a/compiler/rustc_codegen_ssa/src/mir/block.rs b/compiler/rustc_codegen_ssa/src/mir/block.rs index 817e2ca72ec..8f96c462240 100644 --- a/compiler/rustc_codegen_ssa/src/mir/block.rs +++ b/compiler/rustc_codegen_ssa/src/mir/block.rs @@ -915,32 +915,8 @@ impl<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>> FunctionCx<'a, 'tcx, Bx> { } }; - let args: Vec<_> = args - .iter() - .enumerate() - .map(|(i, arg)| { - // The indices passed to simd_shuffle in the - // third argument must be constant. This is - // checked by the type-checker. - if i == 2 && intrinsic.name == sym::simd_shuffle { - // FIXME: the simd_shuffle argument is actually an array, - // not a vector, so we need this special hack to make sure - // it is passed as an immediate. We should pass the - // shuffle indices as a vector instead to avoid this hack. - if let mir::Operand::Constant(constant) = &arg.node { - let (llval, ty) = self.immediate_const_vector(bx, constant); - return OperandRef { - val: Immediate(llval), - layout: bx.layout_of(ty), - }; - } else { - span_bug!(span, "shuffle indices must be constant"); - } - } - - self.codegen_operand(bx, &arg.node) - }) - .collect(); + let args: Vec<_> = + args.iter().map(|arg| self.codegen_operand(bx, &arg.node)).collect(); if matches!(intrinsic, ty::IntrinsicDef { name: sym::caller_location, .. }) { let location = self diff --git a/compiler/rustc_codegen_ssa/src/mir/constant.rs b/compiler/rustc_codegen_ssa/src/mir/constant.rs index 0aa85b82038..8254fb3d866 100644 --- a/compiler/rustc_codegen_ssa/src/mir/constant.rs +++ b/compiler/rustc_codegen_ssa/src/mir/constant.rs @@ -1,6 +1,6 @@ use rustc_middle::mir::interpret::ErrorHandled; use rustc_middle::ty::layout::HasTyCtxt; -use rustc_middle::ty::{self, Ty, ValTree}; +use rustc_middle::ty::{self, Ty}; use rustc_middle::{bug, mir, span_bug}; use rustc_target::abi::Abi; @@ -66,15 +66,8 @@ impl<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>> FunctionCx<'a, 'tcx, Bx> { constant: &mir::ConstOperand<'tcx>, ) -> (Bx::Value, Ty<'tcx>) { let ty = self.monomorphize(constant.ty()); - let ty_is_simd = ty.is_simd(); - // FIXME: ideally we'd assert that this is a SIMD type, but simd_shuffle - // in its current form relies on a regular array being passed as an - // immediate argument. This hack can be removed once that is fixed. - let field_ty = if ty_is_simd { - ty.simd_size_and_type(bx.tcx()).1 - } else { - ty.builtin_index().unwrap() - }; + assert!(ty.is_simd()); + let field_ty = ty.simd_size_and_type(bx.tcx()).1; let val = self .eval_unevaluated_mir_constant_to_valtree(constant) @@ -82,19 +75,13 @@ impl<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>> FunctionCx<'a, 'tcx, Bx> { .map(|x| x.ok()) .flatten() .map(|val| { - // Depending on whether this is a SIMD type with an array field - // or a type with many fields (one for each elements), the valtree - // is either a single branch with N children, or a root node - // with exactly one child which then in turn has many children. - // So we look at the first child to determine whether it is a - // leaf or whether we have to go one more layer down. - let branch_or_leaf = val.unwrap_branch(); - let first = branch_or_leaf.get(0).unwrap(); - let field_iter = match first { - ValTree::Branch(_) => first.unwrap_branch().iter(), - ValTree::Leaf(_) => branch_or_leaf.iter(), - }; - let values: Vec<_> = field_iter + // A SIMD type has a single field, which is an array. + let fields = val.unwrap_branch(); + assert_eq!(fields.len(), 1); + let array = fields[0].unwrap_branch(); + // Iterate over the array elements to obtain the values in the vector. + let values: Vec<_> = array + .iter() .map(|field| { if let Some(prim) = field.try_to_scalar() { let layout = bx.layout_of(field_ty); @@ -107,7 +94,7 @@ impl<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>> FunctionCx<'a, 'tcx, Bx> { } }) .collect(); - if ty_is_simd { bx.const_vector(&values) } else { bx.const_struct(&values, false) } + bx.const_vector(&values) }) .unwrap_or_else(|| { bx.tcx().dcx().emit_err(errors::ShuffleIndicesEvaluation { span: constant.span }); diff --git a/compiler/rustc_const_eval/messages.ftl b/compiler/rustc_const_eval/messages.ftl index 8a6dfb89249..2dc9d57e3b5 100644 --- a/compiler/rustc_const_eval/messages.ftl +++ b/compiler/rustc_const_eval/messages.ftl @@ -134,9 +134,6 @@ const_eval_incompatible_return_types = const_eval_incompatible_types = calling a function with argument of type {$callee_ty} passing data of type {$caller_ty} -const_eval_interior_mutability_borrow = - cannot borrow here, since the borrowed element may contain interior mutability - const_eval_interior_mutable_data_refer = {const_eval_const_context}s cannot refer to interior mutable data .label = this borrow of an interior mutable value may end up in the final value @@ -230,9 +227,6 @@ const_eval_memory_exhausted = const_eval_modified_global = modifying a static's initial value from another static's initializer -const_eval_mut_deref = - mutation through a reference is not allowed in {const_eval_const_context}s - const_eval_mutable_ptr_in_final = encountered mutable pointer in final value of {const_eval_intern_kind} const_eval_nested_static_in_thread_local = #[thread_local] does not support implicit nested statics, please create explicit static items and refer to them instead @@ -363,10 +357,6 @@ const_eval_too_generic = const_eval_too_many_caller_args = calling a function with more arguments than it expected -const_eval_transient_mut_borrow = mutable references are not allowed in {const_eval_const_context}s - -const_eval_transient_mut_raw = raw mutable pointers are not allowed in {const_eval_const_context}s - const_eval_try_block_from_output_non_const = `try` block cannot convert `{$ty}` to the result in {const_eval_const_context}s const_eval_unallowed_fn_pointer_call = function pointer calls are not allowed in {const_eval_const_context}s diff --git a/compiler/rustc_const_eval/src/check_consts/check.rs b/compiler/rustc_const_eval/src/check_consts/check.rs index 828d8354c63..6d09ed5b4bf 100644 --- a/compiler/rustc_const_eval/src/check_consts/check.rs +++ b/compiler/rustc_const_eval/src/check_consts/check.rs @@ -11,18 +11,17 @@ use rustc_hir::{self as hir, LangItem}; use rustc_index::bit_set::BitSet; use rustc_infer::infer::TyCtxtInferExt; use rustc_infer::traits::ObligationCause; -use rustc_middle::mir::visit::{MutatingUseContext, NonMutatingUseContext, PlaceContext, Visitor}; +use rustc_middle::mir::visit::Visitor; use rustc_middle::mir::*; use rustc_middle::span_bug; use rustc_middle::ty::adjustment::PointerCoercion; -use rustc_middle::ty::{self, Instance, InstanceKind, Ty, TyCtxt, TypeVisitableExt}; +use rustc_middle::ty::{self, Instance, InstanceKind, Ty, TypeVisitableExt}; use rustc_mir_dataflow::impls::MaybeStorageLive; use rustc_mir_dataflow::storage::always_storage_live_locals; use rustc_mir_dataflow::Analysis; use rustc_span::{sym, Span, Symbol, DUMMY_SP}; use rustc_trait_selection::error_reporting::InferCtxtErrorExt; use rustc_trait_selection::traits::{self, ObligationCauseCode, ObligationCtxt}; -use rustc_type_ir::visit::{TypeSuperVisitable, TypeVisitor}; use tracing::{debug, instrument, trace}; use super::ops::{self, NonConstOp, Status}; @@ -166,24 +165,6 @@ impl<'mir, 'tcx> Qualifs<'mir, 'tcx> { } } -struct LocalReturnTyVisitor<'ck, 'mir, 'tcx> { - kind: LocalKind, - checker: &'ck mut Checker<'mir, 'tcx>, -} - -impl<'ck, 'mir, 'tcx> TypeVisitor> for LocalReturnTyVisitor<'ck, 'mir, 'tcx> { - fn visit_ty(&mut self, t: Ty<'tcx>) { - match t.kind() { - ty::FnPtr(..) => {} - ty::Ref(_, _, hir::Mutability::Mut) => { - self.checker.check_op(ops::mut_ref::MutRef(self.kind)); - t.super_visit_with(self) - } - _ => t.super_visit_with(self), - } - } -} - pub struct Checker<'mir, 'tcx> { ccx: &'mir ConstCx<'mir, 'tcx>, qualifs: Qualifs<'mir, 'tcx>, @@ -230,25 +211,6 @@ impl<'mir, 'tcx> Checker<'mir, 'tcx> { return; } - // The local type and predicate checks are not free and only relevant for `const fn`s. - if self.const_kind() == hir::ConstContext::ConstFn { - for (idx, local) in body.local_decls.iter_enumerated() { - // Handle the return place below. - if idx == RETURN_PLACE { - continue; - } - - self.span = local.source_info.span; - self.check_local_or_return_ty(local.ty, idx); - } - - // impl trait is gone in MIR, so check the return type of a const fn by its signature - // instead of the type of the return place. - self.span = body.local_decls[RETURN_PLACE].source_info.span; - let return_ty = self.ccx.fn_sig().output(); - self.check_local_or_return_ty(return_ty.skip_binder(), RETURN_PLACE); - } - if !tcx.has_attr(def_id, sym::rustc_do_not_const_check) { self.visit_body(body); } @@ -358,16 +320,11 @@ impl<'mir, 'tcx> Checker<'mir, 'tcx> { self.check_op_spanned(ops::StaticAccess, span) } - fn check_local_or_return_ty(&mut self, ty: Ty<'tcx>, local: Local) { - let kind = self.body.local_kind(local); - - let mut visitor = LocalReturnTyVisitor { kind, checker: self }; - - visitor.visit_ty(ty); - } - - fn check_mut_borrow(&mut self, place: &Place<'_>, kind: hir::BorrowKind) { - match self.const_kind() { + /// Returns whether this place can possibly escape the evaluation of the current const/static + /// initializer. The check assumes that all already existing pointers and references point to + /// non-escaping places. + fn place_may_escape(&mut self, place: &Place<'_>) -> bool { + let is_transient = match self.const_kind() { // In a const fn all borrows are transient or point to the places given via // references in the arguments (so we already checked them with // TransientMutBorrow/MutBorrow as appropriate). @@ -375,7 +332,7 @@ impl<'mir, 'tcx> Checker<'mir, 'tcx> { // NOTE: Once we have heap allocations during CTFE we need to figure out // how to prevent `const fn` to create long-lived allocations that point // to mutable memory. - hir::ConstContext::ConstFn => self.check_op(ops::TransientMutBorrow(kind)), + hir::ConstContext::ConstFn => true, _ => { // For indirect places, we are not creating a new permanent borrow, it's just as // transient as the already existing one. For reborrowing references this is handled @@ -387,15 +344,16 @@ impl<'mir, 'tcx> Checker<'mir, 'tcx> { // value of the constant. // Note: This is only sound if every local that has a `StorageDead` has a // `StorageDead` in every control flow path leading to a `return` terminator. - // The good news is that interning will detect if any unexpected mutable - // pointer slips through. - if place.is_indirect() || self.local_is_transient(place.local) { - self.check_op(ops::TransientMutBorrow(kind)); - } else { - self.check_op(ops::MutBorrow(kind)); - } + // If anything slips through, there's no safety net -- safe code can create + // references to variants of `!Freeze` enums as long as that variant is `Freeze`, so + // interning can't protect us here. (There *is* a safety net for mutable references + // though, interning will ICE if we miss something here.) + place.is_indirect() || self.local_is_transient(place.local) } - } + }; + // Transient places cannot possibly escape because the place doesn't exist any more at the + // end of evaluation. + !is_transient } } @@ -420,47 +378,6 @@ impl<'tcx> Visitor<'tcx> for Checker<'_, 'tcx> { fn visit_rvalue(&mut self, rvalue: &Rvalue<'tcx>, location: Location) { trace!("visit_rvalue: rvalue={:?} location={:?}", rvalue, location); - // Special-case reborrows to be more like a copy of a reference. - // FIXME: this does not actually handle all reborrows. It only detects cases where `*` is the outermost - // projection of the borrowed place, it skips deref'ing raw pointers and it skips `static`. - // All those cases are handled below with shared/mutable borrows. - // Once `const_mut_refs` is stable, we should be able to entirely remove this special case. - // (`const_refs_to_cell` is not needed, we already allow all borrows of indirect places anyway.) - match *rvalue { - Rvalue::Ref(_, kind, place) => { - if let Some(reborrowed_place_ref) = place_as_reborrow(self.tcx, self.body, place) { - let ctx = match kind { - BorrowKind::Shared => { - PlaceContext::NonMutatingUse(NonMutatingUseContext::SharedBorrow) - } - BorrowKind::Fake(_) => { - PlaceContext::NonMutatingUse(NonMutatingUseContext::FakeBorrow) - } - BorrowKind::Mut { .. } => { - PlaceContext::MutatingUse(MutatingUseContext::Borrow) - } - }; - self.visit_local(reborrowed_place_ref.local, ctx, location); - self.visit_projection(reborrowed_place_ref, ctx, location); - return; - } - } - Rvalue::RawPtr(mutbl, place) => { - if let Some(reborrowed_place_ref) = place_as_reborrow(self.tcx, self.body, place) { - let ctx = match mutbl { - Mutability::Not => { - PlaceContext::NonMutatingUse(NonMutatingUseContext::RawBorrow) - } - Mutability::Mut => PlaceContext::MutatingUse(MutatingUseContext::RawBorrow), - }; - self.visit_local(reborrowed_place_ref.local, ctx, location); - self.visit_projection(reborrowed_place_ref, ctx, location); - return; - } - } - _ => {} - } - self.super_rvalue(rvalue, location); match rvalue { @@ -494,15 +411,12 @@ impl<'tcx> Visitor<'tcx> for Checker<'_, 'tcx> { let is_allowed = self.const_kind() == hir::ConstContext::Static(hir::Mutability::Mut); - if !is_allowed { - self.check_mut_borrow( - place, - if matches!(rvalue, Rvalue::Ref(..)) { - hir::BorrowKind::Ref - } else { - hir::BorrowKind::Raw - }, - ); + if !is_allowed && self.place_may_escape(place) { + self.check_op(ops::EscapingMutBorrow(if matches!(rvalue, Rvalue::Ref(..)) { + hir::BorrowKind::Ref + } else { + hir::BorrowKind::Raw + })); } } @@ -514,40 +428,8 @@ impl<'tcx> Visitor<'tcx> for Checker<'_, 'tcx> { place.as_ref(), ); - // If the place is indirect, this is basically a reborrow. We have a reborrow - // special case above, but for raw pointers and pointers/references to `static` and - // when the `*` is not the first projection, `place_as_reborrow` does not recognize - // them as such, so we end up here. This should probably be considered a - // `TransientCellBorrow` (we consider the equivalent mutable case a - // `TransientMutBorrow`), but such reborrows got accidentally stabilized already and - // it is too much of a breaking change to take back. - if borrowed_place_has_mut_interior && !place.is_indirect() { - match self.const_kind() { - // In a const fn all borrows are transient or point to the places given via - // references in the arguments (so we already checked them with - // TransientCellBorrow/CellBorrow as appropriate). - // The borrow checker guarantees that no new non-transient borrows are created. - // NOTE: Once we have heap allocations during CTFE we need to figure out - // how to prevent `const fn` to create long-lived allocations that point - // to (interior) mutable memory. - hir::ConstContext::ConstFn => self.check_op(ops::TransientCellBorrow), - _ => { - // Locals with StorageDead are definitely not part of the final constant value, and - // it is thus inherently safe to permit such locals to have their - // address taken as we can't end up with a reference to them in the - // final value. - // Note: This is only sound if every local that has a `StorageDead` has a - // `StorageDead` in every control flow path leading to a `return` terminator. - // If anything slips through, there's no safety net -- safe code can create - // references to variants of `!Freeze` enums as long as that variant is `Freeze`, - // so interning can't protect us here. - if self.local_is_transient(place.local) { - self.check_op(ops::TransientCellBorrow); - } else { - self.check_op(ops::CellBorrow); - } - } - } + if borrowed_place_has_mut_interior && self.place_may_escape(place) { + self.check_op(ops::EscapingCellBorrow); } } @@ -636,58 +518,6 @@ impl<'tcx> Visitor<'tcx> for Checker<'_, 'tcx> { } } } - fn visit_projection_elem( - &mut self, - place_ref: PlaceRef<'tcx>, - elem: PlaceElem<'tcx>, - context: PlaceContext, - location: Location, - ) { - trace!( - "visit_projection_elem: place_ref={:?} elem={:?} \ - context={:?} location={:?}", - place_ref, elem, context, location, - ); - - self.super_projection_elem(place_ref, elem, context, location); - - match elem { - ProjectionElem::Deref => { - let base_ty = place_ref.ty(self.body, self.tcx).ty; - if base_ty.is_unsafe_ptr() { - if place_ref.projection.is_empty() { - let decl = &self.body.local_decls[place_ref.local]; - // If this is a static, then this is not really dereferencing a pointer, - // just directly accessing a static. That is not subject to any feature - // gates (except for the one about whether statics can even be used, but - // that is checked already by `visit_operand`). - if let LocalInfo::StaticRef { .. } = *decl.local_info() { - return; - } - } - - // `*const T` is stable, `*mut T` is not - if !base_ty.is_mutable_ptr() { - return; - } - - self.check_op(ops::RawMutPtrDeref); - } - - if context.is_mutating_use() { - self.check_op(ops::MutDeref); - } - } - - ProjectionElem::ConstantIndex { .. } - | ProjectionElem::Downcast(..) - | ProjectionElem::OpaqueCast(..) - | ProjectionElem::Subslice { .. } - | ProjectionElem::Subtype(..) - | ProjectionElem::Field(..) - | ProjectionElem::Index(_) => {} - } - } fn visit_source_info(&mut self, source_info: &SourceInfo) { trace!("visit_source_info: source_info={:?}", source_info); @@ -984,40 +814,6 @@ impl<'tcx> Visitor<'tcx> for Checker<'_, 'tcx> { } } -fn place_as_reborrow<'tcx>( - tcx: TyCtxt<'tcx>, - body: &Body<'tcx>, - place: Place<'tcx>, -) -> Option> { - match place.as_ref().last_projection() { - Some((place_base, ProjectionElem::Deref)) => { - // FIXME: why do statics and raw pointers get excluded here? This makes - // some code involving mutable pointers unstable, but it is unclear - // why that code is treated differently from mutable references. - // Once TransientMutBorrow and TransientCellBorrow are stable, - // this can probably be cleaned up without any behavioral changes. - - // A borrow of a `static` also looks like `&(*_1)` in the MIR, but `_1` is a `const` - // that points to the allocation for the static. Don't treat these as reborrows. - if body.local_decls[place_base.local].is_ref_to_static() { - None - } else { - // Ensure the type being derefed is a reference and not a raw pointer. - // This is sufficient to prevent an access to a `static mut` from being marked as a - // reborrow, even if the check above were to disappear. - let inner_ty = place_base.ty(body, tcx).ty; - - if let ty::Ref(..) = inner_ty.kind() { - return Some(place_base); - } else { - return None; - } - } - } - _ => None, - } -} - fn is_int_bool_float_or_char(ty: Ty<'_>) -> bool { ty.is_bool() || ty.is_integral() || ty.is_char() || ty.is_floating_point() } diff --git a/compiler/rustc_const_eval/src/check_consts/ops.rs b/compiler/rustc_const_eval/src/check_consts/ops.rs index e8f10c88408..a52fc6a077b 100644 --- a/compiler/rustc_const_eval/src/check_consts/ops.rs +++ b/compiler/rustc_const_eval/src/check_consts/ops.rs @@ -8,7 +8,7 @@ use rustc_hir as hir; use rustc_hir::def_id::DefId; use rustc_infer::infer::TyCtxtInferExt; use rustc_infer::traits::{ImplSource, Obligation, ObligationCause}; -use rustc_middle::mir::{self, CallSource}; +use rustc_middle::mir::CallSource; use rustc_middle::span_bug; use rustc_middle::ty::print::{with_no_trimmed_paths, PrintTraitRefExt as _}; use rustc_middle::ty::{ @@ -391,27 +391,12 @@ impl<'tcx> NonConstOp<'tcx> for LiveDrop<'tcx> { } } -#[derive(Debug)] -/// A borrow of a type that contains an `UnsafeCell` somewhere. The borrow never escapes to -/// the final value of the constant. -pub(crate) struct TransientCellBorrow; -impl<'tcx> NonConstOp<'tcx> for TransientCellBorrow { - fn status_in_item(&self, _: &ConstCx<'_, 'tcx>) -> Status { - Status::Unstable(sym::const_refs_to_cell) - } - fn build_error(&self, ccx: &ConstCx<'_, 'tcx>, span: Span) -> Diag<'tcx> { - ccx.tcx - .sess - .create_feature_err(errors::InteriorMutabilityBorrow { span }, sym::const_refs_to_cell) - } -} - #[derive(Debug)] /// A borrow of a type that contains an `UnsafeCell` somewhere. The borrow might escape to /// the final value of the constant, and thus we cannot allow this (for now). We may allow /// it in the future for static items. -pub(crate) struct CellBorrow; -impl<'tcx> NonConstOp<'tcx> for CellBorrow { +pub(crate) struct EscapingCellBorrow; +impl<'tcx> NonConstOp<'tcx> for EscapingCellBorrow { fn importance(&self) -> DiagImportance { // Most likely the code will try to do mutation with these borrows, which // triggers its own errors. Only show this one if that does not happen. @@ -431,9 +416,9 @@ impl<'tcx> NonConstOp<'tcx> for CellBorrow { /// This op is for `&mut` borrows in the trailing expression of a constant /// which uses the "enclosing scopes rule" to leak its locals into anonymous /// static or const items. -pub(crate) struct MutBorrow(pub hir::BorrowKind); +pub(crate) struct EscapingMutBorrow(pub hir::BorrowKind); -impl<'tcx> NonConstOp<'tcx> for MutBorrow { +impl<'tcx> NonConstOp<'tcx> for EscapingMutBorrow { fn status_in_item(&self, _ccx: &ConstCx<'_, 'tcx>) -> Status { Status::Forbidden } @@ -460,49 +445,6 @@ impl<'tcx> NonConstOp<'tcx> for MutBorrow { } } -#[derive(Debug)] -pub(crate) struct TransientMutBorrow(pub hir::BorrowKind); - -impl<'tcx> NonConstOp<'tcx> for TransientMutBorrow { - fn status_in_item(&self, _: &ConstCx<'_, 'tcx>) -> Status { - Status::Unstable(sym::const_mut_refs) - } - - fn build_error(&self, ccx: &ConstCx<'_, 'tcx>, span: Span) -> Diag<'tcx> { - let kind = ccx.const_kind(); - match self.0 { - hir::BorrowKind::Raw => ccx - .tcx - .sess - .create_feature_err(errors::TransientMutRawErr { span, kind }, sym::const_mut_refs), - hir::BorrowKind::Ref => ccx.tcx.sess.create_feature_err( - errors::TransientMutBorrowErr { span, kind }, - sym::const_mut_refs, - ), - } - } -} - -#[derive(Debug)] -pub(crate) struct MutDeref; -impl<'tcx> NonConstOp<'tcx> for MutDeref { - fn status_in_item(&self, _: &ConstCx<'_, 'tcx>) -> Status { - Status::Unstable(sym::const_mut_refs) - } - - fn importance(&self) -> DiagImportance { - // Usually a side-effect of a `TransientMutBorrow` somewhere. - DiagImportance::Secondary - } - - fn build_error(&self, ccx: &ConstCx<'_, 'tcx>, span: Span) -> Diag<'tcx> { - ccx.tcx.sess.create_feature_err( - errors::MutDerefErr { span, kind: ccx.const_kind() }, - sym::const_mut_refs, - ) - } -} - /// A call to a `panic()` lang item where the first argument is _not_ a `&str`. #[derive(Debug)] pub(crate) struct PanicNonStr; @@ -524,24 +466,6 @@ impl<'tcx> NonConstOp<'tcx> for RawPtrComparison { } } -#[derive(Debug)] -pub(crate) struct RawMutPtrDeref; -impl<'tcx> NonConstOp<'tcx> for RawMutPtrDeref { - fn status_in_item(&self, _: &ConstCx<'_, '_>) -> Status { - Status::Unstable(sym::const_mut_refs) - } - - #[allow(rustc::untranslatable_diagnostic)] // FIXME: make this translatable - fn build_error(&self, ccx: &ConstCx<'_, 'tcx>, span: Span) -> Diag<'tcx> { - feature_err( - &ccx.tcx.sess, - sym::const_mut_refs, - span, - format!("dereferencing raw mutable pointers in {}s is unstable", ccx.const_kind(),), - ) - } -} - /// Casting raw pointer or function pointer to an integer. /// Not currently intended to ever be allowed, even behind a feature gate: operation depends on /// allocation base addresses that are not known at compile-time. @@ -588,33 +512,3 @@ impl<'tcx> NonConstOp<'tcx> for ThreadLocalAccess { ccx.dcx().create_err(errors::ThreadLocalAccessErr { span }) } } - -/// Types that cannot appear in the signature or locals of a `const fn`. -pub(crate) mod mut_ref { - use super::*; - - #[derive(Debug)] - pub(crate) struct MutRef(pub mir::LocalKind); - impl<'tcx> NonConstOp<'tcx> for MutRef { - fn status_in_item(&self, _ccx: &ConstCx<'_, 'tcx>) -> Status { - Status::Unstable(sym::const_mut_refs) - } - - fn importance(&self) -> DiagImportance { - match self.0 { - mir::LocalKind::Temp => DiagImportance::Secondary, - mir::LocalKind::ReturnPointer | mir::LocalKind::Arg => DiagImportance::Primary, - } - } - - #[allow(rustc::untranslatable_diagnostic)] // FIXME: make this translatable - fn build_error(&self, ccx: &ConstCx<'_, 'tcx>, span: Span) -> Diag<'tcx> { - feature_err( - &ccx.tcx.sess, - sym::const_mut_refs, - span, - format!("mutable references are not allowed in {}s", ccx.const_kind()), - ) - } - } -} diff --git a/compiler/rustc_const_eval/src/errors.rs b/compiler/rustc_const_eval/src/errors.rs index 57e52254757..b66b5c0a00a 100644 --- a/compiler/rustc_const_eval/src/errors.rs +++ b/compiler/rustc_const_eval/src/errors.rs @@ -93,30 +93,6 @@ pub(crate) struct PanicNonStrErr { pub span: Span, } -#[derive(Diagnostic)] -#[diag(const_eval_mut_deref, code = E0658)] -pub(crate) struct MutDerefErr { - #[primary_span] - pub span: Span, - pub kind: ConstContext, -} - -#[derive(Diagnostic)] -#[diag(const_eval_transient_mut_borrow, code = E0658)] -pub(crate) struct TransientMutBorrowErr { - #[primary_span] - pub span: Span, - pub kind: ConstContext, -} - -#[derive(Diagnostic)] -#[diag(const_eval_transient_mut_raw, code = E0658)] -pub(crate) struct TransientMutRawErr { - #[primary_span] - pub span: Span, - pub kind: ConstContext, -} - #[derive(Diagnostic)] #[diag(const_eval_max_num_nodes_in_const)] pub(crate) struct MaxNumNodesInConstErr { @@ -217,13 +193,6 @@ pub(crate) struct InteriorMutableDataRefer { pub teach: bool, } -#[derive(Diagnostic)] -#[diag(const_eval_interior_mutability_borrow)] -pub(crate) struct InteriorMutabilityBorrow { - #[primary_span] - pub span: Span, -} - #[derive(LintDiagnostic)] #[diag(const_eval_long_running)] #[note] diff --git a/compiler/rustc_const_eval/src/interpret/intrinsics.rs b/compiler/rustc_const_eval/src/interpret/intrinsics.rs index 8a07f90c951..b3f4fd5e2a1 100644 --- a/compiler/rustc_const_eval/src/interpret/intrinsics.rs +++ b/compiler/rustc_const_eval/src/interpret/intrinsics.rs @@ -216,7 +216,7 @@ impl<'tcx, M: Machine<'tcx>> InterpCx<'tcx, M> { self.copy_intrinsic(&args[0], &args[1], &args[2], /*nonoverlapping*/ false)?; } sym::write_bytes => { - self.write_bytes_intrinsic(&args[0], &args[1], &args[2])?; + self.write_bytes_intrinsic(&args[0], &args[1], &args[2], "write_bytes")?; } sym::compare_bytes => { let result = self.compare_bytes_intrinsic(&args[0], &args[1], &args[2])?; @@ -599,9 +599,8 @@ impl<'tcx, M: Machine<'tcx>> InterpCx<'tcx, M> { let count = self.read_target_usize(count)?; let layout = self.layout_of(src.layout.ty.builtin_deref(true).unwrap())?; let (size, align) = (layout.size, layout.align.abi); - // `checked_mul` enforces a too small bound (the correct one would probably be target_isize_max), - // but no actual allocation can be big enough for the difference to be noticeable. - let size = size.checked_mul(count, self).ok_or_else(|| { + + let size = self.compute_size_in_bytes(size, count).ok_or_else(|| { err_ub_custom!( fluent::const_eval_size_overflow, name = if nonoverlapping { "copy_nonoverlapping" } else { "copy" } @@ -635,11 +634,12 @@ impl<'tcx, M: Machine<'tcx>> InterpCx<'tcx, M> { Ok(()) } - pub(crate) fn write_bytes_intrinsic( + pub fn write_bytes_intrinsic( &mut self, dst: &OpTy<'tcx, >::Provenance>, byte: &OpTy<'tcx, >::Provenance>, count: &OpTy<'tcx, >::Provenance>, + name: &'static str, ) -> InterpResult<'tcx> { let layout = self.layout_of(dst.layout.ty.builtin_deref(true).unwrap())?; @@ -649,9 +649,9 @@ impl<'tcx, M: Machine<'tcx>> InterpCx<'tcx, M> { // `checked_mul` enforces a too small bound (the correct one would probably be target_isize_max), // but no actual allocation can be big enough for the difference to be noticeable. - let len = layout.size.checked_mul(count, self).ok_or_else(|| { - err_ub_custom!(fluent::const_eval_size_overflow, name = "write_bytes") - })?; + let len = self + .compute_size_in_bytes(layout.size, count) + .ok_or_else(|| err_ub_custom!(fluent::const_eval_size_overflow, name = name))?; let bytes = std::iter::repeat(byte).take(len.bytes_usize()); self.write_bytes_ptr(dst, bytes) diff --git a/compiler/rustc_const_eval/src/interpret/machine.rs b/compiler/rustc_const_eval/src/interpret/machine.rs index 8cab3c34eed..67c99934059 100644 --- a/compiler/rustc_const_eval/src/interpret/machine.rs +++ b/compiler/rustc_const_eval/src/interpret/machine.rs @@ -540,10 +540,29 @@ pub trait Machine<'tcx>: Sized { Ok(ReturnAction::Normal) } + /// Called immediately after an "immediate" local variable is read + /// (i.e., this is called for reads that do not end up accessing addressable memory). + #[inline(always)] + fn after_local_read(_ecx: &InterpCx<'tcx, Self>, _local: mir::Local) -> InterpResult<'tcx> { + Ok(()) + } + + /// Called immediately after an "immediate" local variable is assigned a new value + /// (i.e., this is called for writes that do not end up in memory). + /// `storage_live` indicates whether this is the initial write upon `StorageLive`. + #[inline(always)] + fn after_local_write( + _ecx: &mut InterpCx<'tcx, Self>, + _local: mir::Local, + _storage_live: bool, + ) -> InterpResult<'tcx> { + Ok(()) + } + /// Called immediately after actual memory was allocated for a local /// but before the local's stack frame is updated to point to that memory. #[inline(always)] - fn after_local_allocated( + fn after_local_moved_to_memory( _ecx: &mut InterpCx<'tcx, Self>, _local: mir::Local, _mplace: &MPlaceTy<'tcx, Self::Provenance>, diff --git a/compiler/rustc_const_eval/src/interpret/memory.rs b/compiler/rustc_const_eval/src/interpret/memory.rs index d87588496c0..b1d1dab7c16 100644 --- a/compiler/rustc_const_eval/src/interpret/memory.rs +++ b/compiler/rustc_const_eval/src/interpret/memory.rs @@ -7,7 +7,7 @@ //! short-circuiting the empty case! use std::assert_matches::assert_matches; -use std::borrow::Cow; +use std::borrow::{Borrow, Cow}; use std::collections::VecDeque; use std::{fmt, mem, ptr}; @@ -222,7 +222,7 @@ impl<'tcx, M: Machine<'tcx>> InterpCx<'tcx, M> { } else { Allocation::try_uninit(size, align)? }; - self.allocate_raw_ptr(alloc, kind) + self.insert_allocation(alloc, kind) } pub fn allocate_bytes_ptr( @@ -233,14 +233,15 @@ impl<'tcx, M: Machine<'tcx>> InterpCx<'tcx, M> { mutability: Mutability, ) -> InterpResult<'tcx, Pointer> { let alloc = Allocation::from_bytes(bytes, align, mutability); - self.allocate_raw_ptr(alloc, kind) + self.insert_allocation(alloc, kind) } - pub fn allocate_raw_ptr( + pub fn insert_allocation( &mut self, alloc: Allocation, kind: MemoryKind, ) -> InterpResult<'tcx, Pointer> { + assert!(alloc.size() <= self.max_size_of_val()); let id = self.tcx.reserve_alloc_id(); debug_assert_ne!( Some(kind), @@ -386,12 +387,13 @@ impl<'tcx, M: Machine<'tcx>> InterpCx<'tcx, M> { size: Size, ) -> InterpResult<'tcx, Option<(AllocId, Size, M::ProvenanceExtra)>> { let size = i64::try_from(size.bytes()).unwrap(); // it would be an error to even ask for more than isize::MAX bytes - self.check_and_deref_ptr( + Self::check_and_deref_ptr( + self, ptr, size, CheckInAllocMsg::MemoryAccessTest, - |alloc_id, offset, prov| { - let (size, align) = self + |this, alloc_id, offset, prov| { + let (size, align) = this .get_live_alloc_size_and_align(alloc_id, CheckInAllocMsg::MemoryAccessTest)?; Ok((size, align, (alloc_id, offset, prov))) }, @@ -408,8 +410,8 @@ impl<'tcx, M: Machine<'tcx>> InterpCx<'tcx, M> { msg: CheckInAllocMsg, ) -> InterpResult<'tcx> { let size = i64::try_from(size.bytes()).unwrap(); // it would be an error to even ask for more than isize::MAX bytes - self.check_and_deref_ptr(ptr, size, msg, |alloc_id, _, _| { - let (size, align) = self.get_live_alloc_size_and_align(alloc_id, msg)?; + Self::check_and_deref_ptr(self, ptr, size, msg, |this, alloc_id, _, _| { + let (size, align) = this.get_live_alloc_size_and_align(alloc_id, msg)?; Ok((size, align, ())) })?; Ok(()) @@ -424,8 +426,8 @@ impl<'tcx, M: Machine<'tcx>> InterpCx<'tcx, M> { size: i64, msg: CheckInAllocMsg, ) -> InterpResult<'tcx> { - self.check_and_deref_ptr(ptr, size, msg, |alloc_id, _, _| { - let (size, align) = self.get_live_alloc_size_and_align(alloc_id, msg)?; + Self::check_and_deref_ptr(self, ptr, size, msg, |this, alloc_id, _, _| { + let (size, align) = this.get_live_alloc_size_and_align(alloc_id, msg)?; Ok((size, align, ())) })?; Ok(()) @@ -439,12 +441,13 @@ impl<'tcx, M: Machine<'tcx>> InterpCx<'tcx, M> { /// `alloc_size` will only get called for non-zero-sized accesses. /// /// Returns `None` if and only if the size is 0. - fn check_and_deref_ptr( - &self, + fn check_and_deref_ptr>( + this: R, ptr: Pointer>, size: i64, msg: CheckInAllocMsg, alloc_size: impl FnOnce( + R, AllocId, Size, M::ProvenanceExtra, @@ -455,13 +458,14 @@ impl<'tcx, M: Machine<'tcx>> InterpCx<'tcx, M> { return Ok(None); } - Ok(match self.ptr_try_get_alloc_id(ptr, size) { + Ok(match this.borrow().ptr_try_get_alloc_id(ptr, size) { Err(addr) => { // We couldn't get a proper allocation. throw_ub!(DanglingIntPointer { addr, inbounds_size: size, msg }); } Ok((alloc_id, offset, prov)) => { - let (alloc_size, _alloc_align, ret_val) = alloc_size(alloc_id, offset, prov)?; + let tcx = this.borrow().tcx; + let (alloc_size, _alloc_align, ret_val) = alloc_size(this, alloc_id, offset, prov)?; let offset = offset.bytes(); // Compute absolute begin and end of the range. let (begin, end) = if size >= 0 { @@ -475,7 +479,7 @@ impl<'tcx, M: Machine<'tcx>> InterpCx<'tcx, M> { throw_ub!(PointerOutOfBounds { alloc_id, alloc_size, - ptr_offset: self.sign_extend_to_target_isize(offset), + ptr_offset: tcx.sign_extend_to_target_isize(offset), inbounds_size: size, msg, }) @@ -669,12 +673,13 @@ impl<'tcx, M: Machine<'tcx>> InterpCx<'tcx, M> { ) -> InterpResult<'tcx, Option>> { let size_i64 = i64::try_from(size.bytes()).unwrap(); // it would be an error to even ask for more than isize::MAX bytes - let ptr_and_alloc = self.check_and_deref_ptr( + let ptr_and_alloc = Self::check_and_deref_ptr( + self, ptr, size_i64, CheckInAllocMsg::MemoryAccessTest, - |alloc_id, offset, prov| { - let alloc = self.get_alloc_raw(alloc_id)?; + |this, alloc_id, offset, prov| { + let alloc = this.get_alloc_raw(alloc_id)?; Ok((alloc.size(), alloc.align, (alloc_id, offset, prov, alloc))) }, )?; @@ -726,7 +731,10 @@ impl<'tcx, M: Machine<'tcx>> InterpCx<'tcx, M> { // We have "NLL problem case #3" here, which cannot be worked around without loss of // efficiency even for the common case where the key is in the map. // - // (Cannot use `get_mut_or` since `get_global_alloc` needs `&self`.) + // (Cannot use `get_mut_or` since `get_global_alloc` needs `&self`, and that boils down to + // Miri's `adjust_alloc_root_pointer` needing to look up the size of the allocation. + // It could be avoided with a totally separate codepath in Miri for handling the absolute address + // of global allocations, but that's not worth it.) if self.memory.alloc_map.get_mut(id).is_none() { // Slow path. // Allocation not found locally, go look global. @@ -762,13 +770,22 @@ impl<'tcx, M: Machine<'tcx>> InterpCx<'tcx, M> { size: Size, ) -> InterpResult<'tcx, Option>> { - let parts = self.get_ptr_access(ptr, size)?; - if let Some((alloc_id, offset, prov)) = parts { - let tcx = self.tcx; - let validation_in_progress = self.memory.validation_in_progress; - // FIXME: can we somehow avoid looking up the allocation twice here? - // We cannot call `get_raw_mut` inside `check_and_deref_ptr` as that would duplicate `&mut self`. - let (alloc, machine) = self.get_alloc_raw_mut(alloc_id)?; + let tcx = self.tcx; + let validation_in_progress = self.memory.validation_in_progress; + + let size_i64 = i64::try_from(size.bytes()).unwrap(); // it would be an error to even ask for more than isize::MAX bytes + let ptr_and_alloc = Self::check_and_deref_ptr( + self, + ptr, + size_i64, + CheckInAllocMsg::MemoryAccessTest, + |this, alloc_id, offset, prov| { + let (alloc, machine) = this.get_alloc_raw_mut(alloc_id)?; + Ok((alloc.size(), alloc.align, (alloc_id, offset, prov, alloc, machine))) + }, + )?; + + if let Some((alloc_id, offset, prov, alloc, machine)) = ptr_and_alloc { let range = alloc_range(offset, size); if !validation_in_progress { M::before_memory_write(tcx, machine, &mut alloc.extra, (alloc_id, prov), range)?; @@ -1030,6 +1047,10 @@ impl<'tcx, M: Machine<'tcx>> InterpCx<'tcx, M> { ); res } + + pub(super) fn validation_in_progress(&self) -> bool { + self.memory.validation_in_progress + } } #[doc(hidden)] @@ -1114,7 +1135,7 @@ impl<'a, 'tcx, M: Machine<'tcx>> std::fmt::Debug for DumpAllocs<'a, 'tcx, M> { } /// Reading and writing. -impl<'tcx, 'a, Prov: Provenance, Extra, Bytes: AllocBytes> +impl<'a, 'tcx, Prov: Provenance, Extra, Bytes: AllocBytes> AllocRefMut<'a, 'tcx, Prov, Extra, Bytes> { pub fn as_ref<'b>(&'b self) -> AllocRef<'b, 'tcx, Prov, Extra, Bytes> { @@ -1162,7 +1183,7 @@ impl<'tcx, 'a, Prov: Provenance, Extra, Bytes: AllocBytes> } } -impl<'tcx, 'a, Prov: Provenance, Extra, Bytes: AllocBytes> AllocRef<'a, 'tcx, Prov, Extra, Bytes> { +impl<'a, 'tcx, Prov: Provenance, Extra, Bytes: AllocBytes> AllocRef<'a, 'tcx, Prov, Extra, Bytes> { /// `range` is relative to this allocation reference, not the base of the allocation. pub fn read_scalar( &self, diff --git a/compiler/rustc_const_eval/src/interpret/operand.rs b/compiler/rustc_const_eval/src/interpret/operand.rs index 2e02d1001c8..ead3ef6861a 100644 --- a/compiler/rustc_const_eval/src/interpret/operand.rs +++ b/compiler/rustc_const_eval/src/interpret/operand.rs @@ -697,6 +697,7 @@ impl<'tcx, M: Machine<'tcx>> InterpCx<'tcx, M> { if matches!(op, Operand::Immediate(_)) { assert!(!layout.is_unsized()); } + M::after_local_read(self, local)?; Ok(OpTy { op, layout }) } diff --git a/compiler/rustc_const_eval/src/interpret/operator.rs b/compiler/rustc_const_eval/src/interpret/operator.rs index b390bb87789..7d32fcbb664 100644 --- a/compiler/rustc_const_eval/src/interpret/operator.rs +++ b/compiler/rustc_const_eval/src/interpret/operator.rs @@ -1,11 +1,12 @@ use either::Either; use rustc_apfloat::{Float, FloatConvert}; -use rustc_middle::mir::interpret::{InterpResult, Scalar}; +use rustc_middle::mir::interpret::{InterpResult, PointerArithmetic, Scalar}; use rustc_middle::mir::NullOp; use rustc_middle::ty::layout::{LayoutOf, TyAndLayout}; use rustc_middle::ty::{self, FloatTy, ScalarInt, Ty}; use rustc_middle::{bug, mir, span_bug}; use rustc_span::symbol::sym; +use rustc_target::abi::Size; use tracing::trace; use super::{throw_ub, ImmTy, InterpCx, Machine, MemPlaceMeta}; @@ -287,6 +288,20 @@ impl<'tcx, M: Machine<'tcx>> InterpCx<'tcx, M> { }) } + /// Computes the total size of this access, `count * elem_size`, + /// checking for overflow beyond isize::MAX. + pub fn compute_size_in_bytes(&self, elem_size: Size, count: u64) -> Option { + // `checked_mul` applies `u64` limits independent of the target pointer size... but the + // subsequent check for `max_size_of_val` means we also handle 32bit targets correctly. + // (We cannot use `Size::checked_mul` as that enforces `obj_size_bound` as the limit, which + // would be wrong here.) + elem_size + .bytes() + .checked_mul(count) + .map(Size::from_bytes) + .filter(|&total| total <= self.max_size_of_val()) + } + fn binary_ptr_op( &self, bin_op: mir::BinOp, diff --git a/compiler/rustc_const_eval/src/interpret/place.rs b/compiler/rustc_const_eval/src/interpret/place.rs index 9dd9ca80385..e398c4c0742 100644 --- a/compiler/rustc_const_eval/src/interpret/place.rs +++ b/compiler/rustc_const_eval/src/interpret/place.rs @@ -500,15 +500,13 @@ where &self, local: mir::Local, ) -> InterpResult<'tcx, PlaceTy<'tcx, M::Provenance>> { - // Other parts of the system rely on `Place::Local` never being unsized. - // So we eagerly check here if this local has an MPlace, and if yes we use it. let frame = self.frame(); let layout = self.layout_of_local(frame, local, None)?; let place = if layout.is_sized() { // We can just always use the `Local` for sized values. Place::Local { local, offset: None, locals_addr: frame.locals_addr() } } else { - // Unsized `Local` isn't okay (we cannot store the metadata). + // Other parts of the system rely on `Place::Local` never being unsized. match frame.locals[local].access()? { Operand::Immediate(_) => bug!(), Operand::Indirect(mplace) => Place::Ptr(*mplace), @@ -562,7 +560,10 @@ where place: &PlaceTy<'tcx, M::Provenance>, ) -> InterpResult< 'tcx, - Either, (&mut Immediate, TyAndLayout<'tcx>)>, + Either< + MPlaceTy<'tcx, M::Provenance>, + (&mut Immediate, TyAndLayout<'tcx>, mir::Local), + >, > { Ok(match place.to_place().as_mplace_or_local() { Left(mplace) => Left(mplace), @@ -581,7 +582,7 @@ where } Operand::Immediate(local_val) => { // The local still has the optimized representation. - Right((local_val, layout)) + Right((local_val, layout, local)) } } } @@ -643,9 +644,13 @@ where assert!(dest.layout().is_sized(), "Cannot write unsized immediate data"); match self.as_mplace_or_mutable_local(&dest.to_place())? { - Right((local_val, local_layout)) => { + Right((local_val, local_layout, local)) => { // Local can be updated in-place. *local_val = src; + // Call the machine hook (the data race detector needs to know about this write). + if !self.validation_in_progress() { + M::after_local_write(self, local, /*storage_live*/ false)?; + } // Double-check that the value we are storing and the local fit to each other. if cfg!(debug_assertions) { src.assert_matches_abi(local_layout.abi, self); @@ -714,8 +719,12 @@ where dest: &impl Writeable<'tcx, M::Provenance>, ) -> InterpResult<'tcx> { match self.as_mplace_or_mutable_local(&dest.to_place())? { - Right((local_val, _local_layout)) => { + Right((local_val, _local_layout, local)) => { *local_val = Immediate::Uninit; + // Call the machine hook (the data race detector needs to know about this write). + if !self.validation_in_progress() { + M::after_local_write(self, local, /*storage_live*/ false)?; + } } Left(mplace) => { let Some(mut alloc) = self.get_place_alloc_mut(&mplace)? else { @@ -734,8 +743,12 @@ where dest: &impl Writeable<'tcx, M::Provenance>, ) -> InterpResult<'tcx> { match self.as_mplace_or_mutable_local(&dest.to_place())? { - Right((local_val, _local_layout)) => { + Right((local_val, _local_layout, local)) => { local_val.clear_provenance()?; + // Call the machine hook (the data race detector needs to know about this write). + if !self.validation_in_progress() { + M::after_local_write(self, local, /*storage_live*/ false)?; + } } Left(mplace) => { let Some(mut alloc) = self.get_place_alloc_mut(&mplace)? else { @@ -941,7 +954,7 @@ where mplace.mplace, )?; } - M::after_local_allocated(self, local, &mplace)?; + M::after_local_moved_to_memory(self, local, &mplace)?; // Now we can call `access_mut` again, asserting it goes well, and actually // overwrite things. This points to the entire allocation, not just the part // the place refers to, i.e. we do this before we apply `offset`. diff --git a/compiler/rustc_const_eval/src/interpret/projection.rs b/compiler/rustc_const_eval/src/interpret/projection.rs index 641ed5bb7c0..58ce44e4014 100644 --- a/compiler/rustc_const_eval/src/interpret/projection.rs +++ b/compiler/rustc_const_eval/src/interpret/projection.rs @@ -17,7 +17,7 @@ use rustc_target::abi::{self, Size, VariantIdx}; use tracing::{debug, instrument}; use super::{ - throw_ub, throw_unsup, InterpCx, InterpResult, MPlaceTy, Machine, MemPlaceMeta, OpTy, + err_ub, throw_ub, throw_unsup, InterpCx, InterpResult, MPlaceTy, Machine, MemPlaceMeta, OpTy, Provenance, Scalar, }; @@ -101,7 +101,7 @@ pub trait Projectable<'tcx, Prov: Provenance>: Sized + std::fmt::Debug { } /// A type representing iteration over the elements of an array. -pub struct ArrayIterator<'tcx, 'a, Prov: Provenance, P: Projectable<'tcx, Prov>> { +pub struct ArrayIterator<'a, 'tcx, Prov: Provenance, P: Projectable<'tcx, Prov>> { base: &'a P, range: Range, stride: Size, @@ -109,7 +109,7 @@ pub struct ArrayIterator<'tcx, 'a, Prov: Provenance, P: Projectable<'tcx, Prov>> _phantom: PhantomData, // otherwise it says `Prov` is never used... } -impl<'tcx, 'a, Prov: Provenance, P: Projectable<'tcx, Prov>> ArrayIterator<'tcx, 'a, Prov, P> { +impl<'a, 'tcx, Prov: Provenance, P: Projectable<'tcx, Prov>> ArrayIterator<'a, 'tcx, Prov, P> { /// Should be the same `ecx` on each call, and match the one used to create the iterator. pub fn next>( &mut self, @@ -229,7 +229,11 @@ where // This can only be reached in ConstProp and non-rustc-MIR. throw_ub!(BoundsCheckFailed { len, index }); } - let offset = stride * index; // `Size` multiplication + // With raw slices, `len` can be so big that this *can* overflow. + let offset = self + .compute_size_in_bytes(stride, index) + .ok_or_else(|| err_ub!(PointerArithOverflow))?; + // All fields have the same layout. let field_layout = base.layout().field(self, 0); (offset, field_layout) @@ -286,7 +290,7 @@ where pub fn project_array_fields<'a, P: Projectable<'tcx, M::Provenance>>( &self, base: &'a P, - ) -> InterpResult<'tcx, ArrayIterator<'tcx, 'a, M::Provenance, P>> { + ) -> InterpResult<'tcx, ArrayIterator<'a, 'tcx, M::Provenance, P>> { let abi::FieldsShape::Array { stride, .. } = base.layout().fields else { span_bug!(self.cur_span(), "project_array_fields: expected an array layout"); }; diff --git a/compiler/rustc_const_eval/src/interpret/stack.rs b/compiler/rustc_const_eval/src/interpret/stack.rs index b6e83715e39..db418c82f66 100644 --- a/compiler/rustc_const_eval/src/interpret/stack.rs +++ b/compiler/rustc_const_eval/src/interpret/stack.rs @@ -534,8 +534,11 @@ impl<'tcx, M: Machine<'tcx>> InterpCx<'tcx, M> { let dest_place = self.allocate_dyn(layout, MemoryKind::Stack, meta)?; Operand::Indirect(*dest_place.mplace()) } else { - assert!(!meta.has_meta()); // we're dropping the metadata // Just make this an efficient immediate. + assert!(!meta.has_meta()); // we're dropping the metadata + // Make sure the machine knows this "write" is happening. (This is important so that + // races involving local variable allocation can be detected by Miri.) + M::after_local_write(self, local, /*storage_live*/ true)?; // Note that not calling `layout_of` here does have one real consequence: // if the type is too big, we'll only notice this when the local is actually initialized, // which is a bit too late -- we should ideally notice this already here, when the memory diff --git a/compiler/rustc_const_eval/src/interpret/validity.rs b/compiler/rustc_const_eval/src/interpret/validity.rs index 469af35ec1b..ca38f779256 100644 --- a/compiler/rustc_const_eval/src/interpret/validity.rs +++ b/compiler/rustc_const_eval/src/interpret/validity.rs @@ -14,6 +14,7 @@ use hir::def::DefKind; use rustc_ast::Mutability; use rustc_data_structures::fx::FxHashSet; use rustc_hir as hir; +use rustc_middle::bug; use rustc_middle::mir::interpret::ValidationErrorKind::{self, *}; use rustc_middle::mir::interpret::{ alloc_range, ExpectedKind, InterpError, InvalidMetaKind, Misalignment, PointerKind, Provenance, @@ -21,7 +22,6 @@ use rustc_middle::mir::interpret::{ }; use rustc_middle::ty::layout::{LayoutCx, LayoutOf, TyAndLayout}; use rustc_middle::ty::{self, Ty, TyCtxt}; -use rustc_middle::{bug, span_bug}; use rustc_span::symbol::{sym, Symbol}; use rustc_target::abi::{ Abi, FieldIdx, FieldsShape, Scalar as ScalarAbi, Size, VariantIdx, Variants, WrappingRange, @@ -617,13 +617,7 @@ impl<'rt, 'tcx, M: Machine<'tcx>> ValidityVisitor<'rt, 'tcx, M> { if ptr_expected_mutbl == Mutability::Mut && alloc_actual_mutbl == Mutability::Not { - if !self.ecx.tcx.sess.opts.unstable_opts.unleash_the_miri_inside_of_you - { - span_bug!( - self.ecx.tcx.span, - "the static const safety checks accepted mutable references they should not have accepted" - ); - } + // This can actually occur with transmutes. throw_validation_failure!(self.path, MutableRefToImmutable); } // In a const, everything must be completely immutable. diff --git a/compiler/rustc_driver_impl/src/lib.rs b/compiler/rustc_driver_impl/src/lib.rs index 1b7ca61cee8..9d4061d16a1 100644 --- a/compiler/rustc_driver_impl/src/lib.rs +++ b/compiler/rustc_driver_impl/src/lib.rs @@ -207,17 +207,17 @@ pub fn diagnostics_registry() -> Registry { } /// This is the primary entry point for rustc. -pub struct RunCompiler<'a, 'b> { +pub struct RunCompiler<'a> { at_args: &'a [String], - callbacks: &'b mut (dyn Callbacks + Send), + callbacks: &'a mut (dyn Callbacks + Send), file_loader: Option>, make_codegen_backend: Option Box + Send>>, using_internal_features: Arc, } -impl<'a, 'b> RunCompiler<'a, 'b> { - pub fn new(at_args: &'a [String], callbacks: &'b mut (dyn Callbacks + Send)) -> Self { +impl<'a> RunCompiler<'a> { + pub fn new(at_args: &'a [String], callbacks: &'a mut (dyn Callbacks + Send)) -> Self { Self { at_args, callbacks, diff --git a/compiler/rustc_error_codes/src/error_codes/E0764.md b/compiler/rustc_error_codes/src/error_codes/E0764.md index 152627cf654..4d5091cd954 100644 --- a/compiler/rustc_error_codes/src/error_codes/E0764.md +++ b/compiler/rustc_error_codes/src/error_codes/E0764.md @@ -3,8 +3,6 @@ A mutable reference was used in a constant. Erroneous code example: ```compile_fail,E0764 -#![feature(const_mut_refs)] - fn main() { const OH_NO: &'static mut usize = &mut 1; // error! } @@ -26,8 +24,6 @@ Remember: you cannot use a function call inside a constant or static. However, you can totally use it in constant functions: ``` -#![feature(const_mut_refs)] - const fn foo(x: usize) -> usize { let mut y = 1; let z = &mut y; diff --git a/compiler/rustc_expand/src/proc_macro.rs b/compiler/rustc_expand/src/proc_macro.rs index 24f631ed5dc..d1dcec0cc15 100644 --- a/compiler/rustc_expand/src/proc_macro.rs +++ b/compiler/rustc_expand/src/proc_macro.rs @@ -43,9 +43,9 @@ pub struct BangProcMacro { } impl base::BangProcMacro for BangProcMacro { - fn expand<'cx>( + fn expand( &self, - ecx: &'cx mut ExtCtxt<'_>, + ecx: &mut ExtCtxt<'_>, span: Span, input: TokenStream, ) -> Result { @@ -73,9 +73,9 @@ pub struct AttrProcMacro { } impl base::AttrProcMacro for AttrProcMacro { - fn expand<'cx>( + fn expand( &self, - ecx: &'cx mut ExtCtxt<'_>, + ecx: &mut ExtCtxt<'_>, span: Span, annotation: TokenStream, annotated: TokenStream, diff --git a/compiler/rustc_feature/src/accepted.rs b/compiler/rustc_feature/src/accepted.rs index 8949fdffdae..0088a7bbc1e 100644 --- a/compiler/rustc_feature/src/accepted.rs +++ b/compiler/rustc_feature/src/accepted.rs @@ -115,6 +115,8 @@ declare_features! ( (accepted, conservative_impl_trait, "1.26.0", Some(34511)), /// Allows calling constructor functions in `const fn`. (accepted, const_constructor, "1.40.0", Some(61456)), + /// Allows the definition of `const extern fn` and `const unsafe extern fn`. + (accepted, const_extern_fn, "CURRENT_RUSTC_VERSION", Some(64926)), /// Allows basic arithmetic on floating point types in a `const fn`. (accepted, const_fn_floating_point_arithmetic, "1.82.0", Some(57241)), /// Allows using and casting function pointers in a `const fn`. @@ -141,10 +143,14 @@ declare_features! ( (accepted, const_let, "1.33.0", Some(48821)), /// Allows the use of `loop` and `while` in constants. (accepted, const_loop, "1.46.0", Some(52000)), + /// Allows using `&mut` in constant functions. + (accepted, const_mut_refs, "CURRENT_RUSTC_VERSION", Some(57349)), /// Allows panicking during const eval (producing compile-time errors). (accepted, const_panic, "1.57.0", Some(51999)), /// Allows dereferencing raw pointers during const eval. (accepted, const_raw_ptr_deref, "1.58.0", Some(51911)), + /// Allows references to types with interior mutability within constants + (accepted, const_refs_to_cell, "CURRENT_RUSTC_VERSION", Some(80384)), /// Allows implementing `Copy` for closures where possible (RFC 2132). (accepted, copy_closures, "1.26.0", Some(44490)), /// Allows `crate` in paths. diff --git a/compiler/rustc_feature/src/unstable.rs b/compiler/rustc_feature/src/unstable.rs index 6ed5ea9f8bb..d0c0460ddfe 100644 --- a/compiler/rustc_feature/src/unstable.rs +++ b/compiler/rustc_feature/src/unstable.rs @@ -401,16 +401,10 @@ declare_features! ( (unstable, const_async_blocks, "1.53.0", Some(85368)), /// Allows `const || {}` closures in const contexts. (incomplete, const_closures, "1.68.0", Some(106003)), - /// Allows the definition of `const extern fn` and `const unsafe extern fn`. - (unstable, const_extern_fn, "1.40.0", Some(64926)), /// Allows `for _ in _` loops in const contexts. (unstable, const_for, "1.56.0", Some(87575)), - /// Allows using `&mut` in constant functions. - (unstable, const_mut_refs, "1.41.0", Some(57349)), /// Be more precise when looking for live drops in a const context. (unstable, const_precise_live_drops, "1.46.0", Some(73255)), - /// Allows references to types with interior mutability within constants - (unstable, const_refs_to_cell, "1.51.0", Some(80384)), /// Allows creating pointers and references to `static` items in constants. (unstable, const_refs_to_static, "1.78.0", Some(119618)), /// Allows `impl const Trait for T` syntax. diff --git a/compiler/rustc_hir_typeck/src/errors.rs b/compiler/rustc_hir_typeck/src/errors.rs index 4d2770d2e50..a692642ccfc 100644 --- a/compiler/rustc_hir_typeck/src/errors.rs +++ b/compiler/rustc_hir_typeck/src/errors.rs @@ -711,7 +711,7 @@ pub(crate) struct CastThinPointerToFatPointer<'tcx> { #[derive(Diagnostic)] #[diag(hir_typeck_pass_to_variadic_function, code = E0617)] -pub(crate) struct PassToVariadicFunction<'tcx, 'a> { +pub(crate) struct PassToVariadicFunction<'a, 'tcx> { #[primary_span] pub span: Span, pub ty: Ty<'tcx>, diff --git a/compiler/rustc_hir_typeck/src/fallback.rs b/compiler/rustc_hir_typeck/src/fallback.rs index 79b02a7f045..7a6ebf15fa9 100644 --- a/compiler/rustc_hir_typeck/src/fallback.rs +++ b/compiler/rustc_hir_typeck/src/fallback.rs @@ -603,12 +603,12 @@ fn compute_unsafe_infer_vars<'a, 'tcx>( root_ctxt.tcx.hir().maybe_body_owned_by(body_id).expect("body id must have an owner"); let mut res = UnordMap::default(); - struct UnsafeInferVarsVisitor<'a, 'tcx, 'r> { + struct UnsafeInferVarsVisitor<'a, 'tcx> { root_ctxt: &'a TypeckRootCtxt<'tcx>, - res: &'r mut UnordMap, + res: &'a mut UnordMap, } - impl Visitor<'_> for UnsafeInferVarsVisitor<'_, '_, '_> { + impl Visitor<'_> for UnsafeInferVarsVisitor<'_, '_> { fn visit_expr(&mut self, ex: &'_ hir::Expr<'_>) { let typeck_results = self.root_ctxt.typeck_results.borrow(); diff --git a/compiler/rustc_hir_typeck/src/fn_ctxt/_impl.rs b/compiler/rustc_hir_typeck/src/fn_ctxt/_impl.rs index 178dc47aa1f..7318d02d24c 100644 --- a/compiler/rustc_hir_typeck/src/fn_ctxt/_impl.rs +++ b/compiler/rustc_hir_typeck/src/fn_ctxt/_impl.rs @@ -1234,7 +1234,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { infer_args_for_err: &'a FxHashSet, segments: &'tcx [hir::PathSegment<'tcx>], } - impl<'tcx, 'a> GenericArgsLowerer<'a, 'tcx> for CtorGenericArgsCtxt<'a, 'tcx> { + impl<'a, 'tcx> GenericArgsLowerer<'a, 'tcx> for CtorGenericArgsCtxt<'a, 'tcx> { fn args_for_def_id( &mut self, def_id: DefId, diff --git a/compiler/rustc_hir_typeck/src/pat.rs b/compiler/rustc_hir_typeck/src/pat.rs index 25f9340eeb7..c8c95ddcfce 100644 --- a/compiler/rustc_hir_typeck/src/pat.rs +++ b/compiler/rustc_hir_typeck/src/pat.rs @@ -83,7 +83,7 @@ struct TopInfo<'tcx> { } #[derive(Copy, Clone)] -struct PatInfo<'tcx, 'a> { +struct PatInfo<'a, 'tcx> { binding_mode: ByRef, max_ref_mutbl: MutblCap, top_info: &'a TopInfo<'tcx>, @@ -222,7 +222,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { /// Outside of this module, `check_pat_top` should always be used. /// Conversely, inside this module, `check_pat_top` should never be used. #[instrument(level = "debug", skip(self, pat_info))] - fn check_pat(&self, pat: &'tcx Pat<'tcx>, expected: Ty<'tcx>, pat_info: PatInfo<'tcx, '_>) { + fn check_pat(&self, pat: &'tcx Pat<'tcx>, expected: Ty<'tcx>, pat_info: PatInfo<'_, 'tcx>) { let PatInfo { binding_mode, max_ref_mutbl, top_info: ti, current_depth, .. } = pat_info; let path_res = match &pat.kind { @@ -668,7 +668,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { ident: Ident, sub: Option<&'tcx Pat<'tcx>>, expected: Ty<'tcx>, - pat_info: PatInfo<'tcx, '_>, + pat_info: PatInfo<'_, 'tcx>, ) -> Ty<'tcx> { let PatInfo { binding_mode: def_br, top_info: ti, .. } = pat_info; @@ -981,7 +981,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { fields: &'tcx [hir::PatField<'tcx>], has_rest_pat: bool, expected: Ty<'tcx>, - pat_info: PatInfo<'tcx, '_>, + pat_info: PatInfo<'_, 'tcx>, ) -> Ty<'tcx> { // Resolve the path and check the definition for errors. let (variant, pat_ty) = match self.check_struct_path(qpath, pat.hir_id) { @@ -1184,7 +1184,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { subpats: &'tcx [Pat<'tcx>], ddpos: hir::DotDotPos, expected: Ty<'tcx>, - pat_info: PatInfo<'tcx, '_>, + pat_info: PatInfo<'_, 'tcx>, ) -> Ty<'tcx> { let tcx = self.tcx; let on_error = |e| { @@ -1441,7 +1441,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { elements: &'tcx [Pat<'tcx>], ddpos: hir::DotDotPos, expected: Ty<'tcx>, - pat_info: PatInfo<'tcx, '_>, + pat_info: PatInfo<'_, 'tcx>, ) -> Ty<'tcx> { let tcx = self.tcx; let mut expected_len = elements.len(); @@ -1479,7 +1479,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { variant: &'tcx ty::VariantDef, fields: &'tcx [hir::PatField<'tcx>], has_rest_pat: bool, - pat_info: PatInfo<'tcx, '_>, + pat_info: PatInfo<'_, 'tcx>, ) -> Result<(), ErrorGuaranteed> { let tcx = self.tcx; @@ -2070,7 +2070,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { span: Span, inner: &'tcx Pat<'tcx>, expected: Ty<'tcx>, - pat_info: PatInfo<'tcx, '_>, + pat_info: PatInfo<'_, 'tcx>, ) -> Ty<'tcx> { let tcx = self.tcx; let (box_ty, inner_ty) = self @@ -2096,7 +2096,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { span: Span, inner: &'tcx Pat<'tcx>, expected: Ty<'tcx>, - pat_info: PatInfo<'tcx, '_>, + pat_info: PatInfo<'_, 'tcx>, ) -> Ty<'tcx> { let tcx = self.tcx; // Register a `DerefPure` bound, which is required by all `deref!()` pats. @@ -2137,7 +2137,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { inner: &'tcx Pat<'tcx>, pat_mutbl: Mutability, mut expected: Ty<'tcx>, - mut pat_info: PatInfo<'tcx, '_>, + mut pat_info: PatInfo<'_, 'tcx>, ) -> Ty<'tcx> { let tcx = self.tcx; let features = tcx.features(); @@ -2345,7 +2345,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { slice: Option<&'tcx Pat<'tcx>>, after: &'tcx [Pat<'tcx>], expected: Ty<'tcx>, - pat_info: PatInfo<'tcx, '_>, + pat_info: PatInfo<'_, 'tcx>, ) -> Ty<'tcx> { let expected = self.try_structurally_resolve_type(span, expected); @@ -2517,7 +2517,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { &self, span: Span, expected_ty: Ty<'tcx>, - pat_info: PatInfo<'tcx, '_>, + pat_info: PatInfo<'_, 'tcx>, ) -> ErrorGuaranteed { let PatInfo { top_info: ti, current_depth, .. } = pat_info; diff --git a/compiler/rustc_interface/src/passes.rs b/compiler/rustc_interface/src/passes.rs index c4a38047b5e..b93bc3ed84f 100644 --- a/compiler/rustc_interface/src/passes.rs +++ b/compiler/rustc_interface/src/passes.rs @@ -788,7 +788,7 @@ fn run_required_analyses(tcx: TyCtxt<'_>) { rustc_hir_analysis::check_crate(tcx); sess.time("MIR_coroutine_by_move_body", || { tcx.hir().par_body_owners(|def_id| { - if tcx.needs_coroutine_by_move_body_def_id(def_id) { + if tcx.needs_coroutine_by_move_body_def_id(def_id.to_def_id()) { tcx.ensure_with_value().coroutine_by_move_body_def_id(def_id); } }); diff --git a/compiler/rustc_lint/src/async_closures.rs b/compiler/rustc_lint/src/async_closures.rs index 33cc5738262..2a821b71103 100644 --- a/compiler/rustc_lint/src/async_closures.rs +++ b/compiler/rustc_lint/src/async_closures.rs @@ -12,6 +12,7 @@ declare_lint! { /// ### Example /// /// ```rust + /// #![feature(async_closure)] /// #![warn(closure_returning_async_block)] /// let c = |x: &str| async {}; /// ``` diff --git a/compiler/rustc_lint/src/if_let_rescope.rs b/compiler/rustc_lint/src/if_let_rescope.rs index 5b65541bea6..7138d40a48f 100644 --- a/compiler/rustc_lint/src/if_let_rescope.rs +++ b/compiler/rustc_lint/src/if_let_rescope.rs @@ -24,7 +24,7 @@ declare_lint! { /// ### Example /// /// ```rust,edition2021 - /// #![feature(if_let_rescope)] + /// #![cfg_attr(not(bootstrap), feature(if_let_rescope))] // Simplify this in bootstrap bump. /// #![warn(if_let_rescope)] /// #![allow(unused_variables)] /// diff --git a/compiler/rustc_lint/src/levels.rs b/compiler/rustc_lint/src/levels.rs index 65289de980e..796d66f13d4 100644 --- a/compiler/rustc_lint/src/levels.rs +++ b/compiler/rustc_lint/src/levels.rs @@ -255,11 +255,9 @@ impl<'tcx> Visitor<'tcx> for LintLevelsBuilder<'_, LintLevelQueryMap<'tcx>> { intravisit::walk_foreign_item(self, it); } - fn visit_stmt(&mut self, e: &'tcx hir::Stmt<'tcx>) { - // We will call `add_id` when we walk - // the `StmtKind`. The outer statement itself doesn't - // define the lint levels. - intravisit::walk_stmt(self, e); + fn visit_stmt(&mut self, s: &'tcx hir::Stmt<'tcx>) { + self.add_id(s.hir_id); + intravisit::walk_stmt(self, s); } fn visit_expr(&mut self, e: &'tcx hir::Expr<'tcx>) { diff --git a/compiler/rustc_lint/src/lints.rs b/compiler/rustc_lint/src/lints.rs index e49b102cb39..a2ccb93347a 100644 --- a/compiler/rustc_lint/src/lints.rs +++ b/compiler/rustc_lint/src/lints.rs @@ -267,16 +267,16 @@ pub(crate) struct MacroExprFragment2024 { pub suggestion: Span, } -pub(crate) struct BuiltinTypeAliasBounds<'a, 'hir> { +pub(crate) struct BuiltinTypeAliasBounds<'hir> { pub in_where_clause: bool, pub label: Span, pub enable_feat_help: bool, pub suggestions: Vec<(Span, String)>, pub preds: &'hir [hir::WherePredicate<'hir>], - pub ty: Option<&'a hir::Ty<'hir>>, + pub ty: Option<&'hir hir::Ty<'hir>>, } -impl<'a> LintDiagnostic<'a, ()> for BuiltinTypeAliasBounds<'_, '_> { +impl<'a> LintDiagnostic<'a, ()> for BuiltinTypeAliasBounds<'_> { fn decorate_lint<'b>(self, diag: &'b mut Diag<'a, ()>) { diag.primary_message(if self.in_where_clause { fluent::lint_builtin_type_alias_bounds_where_clause diff --git a/compiler/rustc_lint/src/tail_expr_drop_order.rs b/compiler/rustc_lint/src/tail_expr_drop_order.rs index f9ecc8c9806..91f3e2e3bb6 100644 --- a/compiler/rustc_lint/src/tail_expr_drop_order.rs +++ b/compiler/rustc_lint/src/tail_expr_drop_order.rs @@ -143,18 +143,18 @@ impl<'tcx> LateLintPass<'tcx> for TailExprDropOrder { } } -struct LintVisitor<'tcx, 'a> { +struct LintVisitor<'a, 'tcx> { cx: &'a LateContext<'tcx>, // We only record locals that have significant drops locals: Vec, } -struct LocalCollector<'tcx, 'a> { +struct LocalCollector<'a, 'tcx> { cx: &'a LateContext<'tcx>, locals: &'a mut Vec, } -impl<'tcx, 'a> Visitor<'tcx> for LocalCollector<'tcx, 'a> { +impl<'a, 'tcx> Visitor<'tcx> for LocalCollector<'a, 'tcx> { type Result = (); fn visit_pat(&mut self, pat: &'tcx Pat<'tcx>) { if let PatKind::Binding(_binding_mode, id, ident, pat) = pat.kind { @@ -171,7 +171,7 @@ impl<'tcx, 'a> Visitor<'tcx> for LocalCollector<'tcx, 'a> { } } -impl<'tcx, 'a> Visitor<'tcx> for LintVisitor<'tcx, 'a> { +impl<'a, 'tcx> Visitor<'tcx> for LintVisitor<'a, 'tcx> { fn visit_block(&mut self, block: &'tcx Block<'tcx>) { let mut locals = <_>::default(); swap(&mut locals, &mut self.locals); @@ -183,7 +183,7 @@ impl<'tcx, 'a> Visitor<'tcx> for LintVisitor<'tcx, 'a> { } } -impl<'tcx, 'a> LintVisitor<'tcx, 'a> { +impl<'a, 'tcx> LintVisitor<'a, 'tcx> { fn check_block_inner(&mut self, block: &Block<'tcx>) { if !block.span.at_least_rust_2024() { // We only lint for Edition 2024 onwards @@ -205,13 +205,13 @@ impl<'tcx, 'a> LintVisitor<'tcx, 'a> { } } -struct LintTailExpr<'tcx, 'a> { +struct LintTailExpr<'a, 'tcx> { cx: &'a LateContext<'tcx>, is_root_tail_expr: bool, locals: &'a [Span], } -impl<'tcx, 'a> LintTailExpr<'tcx, 'a> { +impl<'a, 'tcx> LintTailExpr<'a, 'tcx> { fn expr_eventually_point_into_local(mut expr: &Expr<'tcx>) -> bool { loop { match expr.kind { @@ -239,7 +239,7 @@ impl<'tcx, 'a> LintTailExpr<'tcx, 'a> { } } -impl<'tcx, 'a> Visitor<'tcx> for LintTailExpr<'tcx, 'a> { +impl<'a, 'tcx> Visitor<'tcx> for LintTailExpr<'a, 'tcx> { fn visit_expr(&mut self, expr: &'tcx Expr<'tcx>) { if self.is_root_tail_expr { self.is_root_tail_expr = false; diff --git a/compiler/rustc_lint/src/types.rs b/compiler/rustc_lint/src/types.rs index b5e501b92f0..900c496e033 100644 --- a/compiler/rustc_lint/src/types.rs +++ b/compiler/rustc_lint/src/types.rs @@ -1713,13 +1713,13 @@ impl<'a, 'tcx> ImproperCTypesVisitor<'a, 'tcx> { hir_ty: &hir::Ty<'tcx>, ty: Ty<'tcx>, ) -> Vec<(Ty<'tcx>, Span)> { - struct FnPtrFinder<'parent, 'a, 'tcx> { - visitor: &'parent ImproperCTypesVisitor<'a, 'tcx>, + struct FnPtrFinder<'a, 'b, 'tcx> { + visitor: &'a ImproperCTypesVisitor<'b, 'tcx>, spans: Vec, tys: Vec>, } - impl<'parent, 'a, 'tcx> hir::intravisit::Visitor<'_> for FnPtrFinder<'parent, 'a, 'tcx> { + impl<'a, 'b, 'tcx> hir::intravisit::Visitor<'_> for FnPtrFinder<'a, 'b, 'tcx> { fn visit_ty(&mut self, ty: &'_ hir::Ty<'_>) { debug!(?ty); if let hir::TyKind::BareFn(hir::BareFnTy { abi, .. }) = ty.kind @@ -1732,7 +1732,7 @@ impl<'a, 'tcx> ImproperCTypesVisitor<'a, 'tcx> { } } - impl<'vis, 'a, 'tcx> ty::visit::TypeVisitor> for FnPtrFinder<'vis, 'a, 'tcx> { + impl<'a, 'b, 'tcx> ty::visit::TypeVisitor> for FnPtrFinder<'a, 'b, 'tcx> { type Result = ControlFlow>; fn visit_ty(&mut self, ty: Ty<'tcx>) -> Self::Result { @@ -1746,7 +1746,7 @@ impl<'a, 'tcx> ImproperCTypesVisitor<'a, 'tcx> { } } - let mut visitor = FnPtrFinder { visitor: &*self, spans: Vec::new(), tys: Vec::new() }; + let mut visitor = FnPtrFinder { visitor: self, spans: Vec::new(), tys: Vec::new() }; ty.visit_with(&mut visitor); hir::intravisit::Visitor::visit_ty(&mut visitor, hir_ty); diff --git a/compiler/rustc_lint_defs/src/builtin.rs b/compiler/rustc_lint_defs/src/builtin.rs index f42f35c594b..9b6d63c2ef4 100644 --- a/compiler/rustc_lint_defs/src/builtin.rs +++ b/compiler/rustc_lint_defs/src/builtin.rs @@ -1870,6 +1870,7 @@ declare_lint! { /// ### Example /// /// ```rust,compile_fail + /// # #[cfg_attr(bootstrap)] compile_error!(); // Remove this in bootstrap bump. /// #![deny(elided_named_lifetimes)] /// struct Foo; /// impl Foo { diff --git a/compiler/rustc_middle/src/mir/syntax.rs b/compiler/rustc_middle/src/mir/syntax.rs index 22a4b688c51..f5590aa2762 100644 --- a/compiler/rustc_middle/src/mir/syntax.rs +++ b/compiler/rustc_middle/src/mir/syntax.rs @@ -1094,7 +1094,7 @@ pub struct Place<'tcx> { pub projection: &'tcx List>, } -#[derive(Copy, Clone, Debug, PartialEq, Eq, PartialOrd, Ord, Hash)] +#[derive(Copy, Clone, Debug, PartialEq, Eq, Hash)] #[derive(TyEncodable, TyDecodable, HashStable, TypeFoldable, TypeVisitable)] pub enum ProjectionElem { Deref, @@ -1468,7 +1468,7 @@ pub enum NullOp<'tcx> { UbChecks, } -#[derive(Copy, Clone, Debug, PartialEq, Eq, PartialOrd, Ord, Hash)] +#[derive(Copy, Clone, Debug, PartialEq, Eq, Hash)] #[derive(HashStable, TyEncodable, TyDecodable, TypeFoldable, TypeVisitable)] pub enum UnOp { /// The `!` operator for logical inversion @@ -1486,7 +1486,7 @@ pub enum UnOp { PtrMetadata, } -#[derive(Copy, Clone, Debug, PartialEq, PartialOrd, Ord, Eq, Hash)] +#[derive(Copy, Clone, Debug, PartialEq, Eq, Hash)] #[derive(TyEncodable, TyDecodable, HashStable, TypeFoldable, TypeVisitable)] pub enum BinOp { /// The `+` operator (addition) diff --git a/compiler/rustc_middle/src/ty/context.rs b/compiler/rustc_middle/src/ty/context.rs index 5ec7e80ee45..cd06d7b8e53 100644 --- a/compiler/rustc_middle/src/ty/context.rs +++ b/compiler/rustc_middle/src/ty/context.rs @@ -3171,7 +3171,7 @@ impl<'tcx> TyCtxt<'tcx> { self.impl_trait_header(def_id).map_or(ty::ImplPolarity::Positive, |h| h.polarity) } - pub fn needs_coroutine_by_move_body_def_id(self, def_id: LocalDefId) -> bool { + pub fn needs_coroutine_by_move_body_def_id(self, def_id: DefId) -> bool { if let Some(hir::CoroutineKind::Desugared(_, hir::CoroutineSource::Closure)) = self.coroutine_kind(def_id) && let ty::Coroutine(_, args) = self.type_of(def_id).instantiate_identity().kind() diff --git a/compiler/rustc_mir_build/messages.ftl b/compiler/rustc_mir_build/messages.ftl index 7a10e627ccd..1c4e9fd11cb 100644 --- a/compiler/rustc_mir_build/messages.ftl +++ b/compiler/rustc_mir_build/messages.ftl @@ -338,6 +338,7 @@ mir_build_unreachable_pattern = unreachable pattern .unreachable_covered_by_catchall = matches any value .unreachable_covered_by_one = matches all the relevant values .unreachable_covered_by_many = multiple earlier patterns match some of the same values + .suggestion = remove the match arm mir_build_unsafe_fn_safe_body = an unsafe function restricts its caller, but its body is safe by default mir_build_unsafe_not_inherited = items do not inherit unsafety from separate enclosing items diff --git a/compiler/rustc_mir_build/src/build/custom/mod.rs b/compiler/rustc_mir_build/src/build/custom/mod.rs index 28477e527c7..1e1fa21b5f3 100644 --- a/compiler/rustc_mir_build/src/build/custom/mod.rs +++ b/compiler/rustc_mir_build/src/build/custom/mod.rs @@ -134,13 +134,12 @@ fn parse_attribute(attr: &Attribute) -> MirPhase { MirPhase::parse(dialect, phase) } -struct ParseCtxt<'tcx, 'body> { +struct ParseCtxt<'a, 'tcx> { tcx: TyCtxt<'tcx>, param_env: ParamEnv<'tcx>, - thir: &'body Thir<'tcx>, + thir: &'a Thir<'tcx>, source_scope: SourceScope, - - body: &'body mut Body<'tcx>, + body: &'a mut Body<'tcx>, local_map: FxHashMap, block_map: FxHashMap, } @@ -151,7 +150,7 @@ struct ParseError { expected: String, } -impl<'tcx, 'body> ParseCtxt<'tcx, 'body> { +impl<'a, 'tcx> ParseCtxt<'a, 'tcx> { fn expr_error(&self, expr: ExprId, expected: &'static str) -> ParseError { let expr = &self.thir[expr]; ParseError { diff --git a/compiler/rustc_mir_build/src/build/custom/parse.rs b/compiler/rustc_mir_build/src/build/custom/parse.rs index 1f186c8f99a..538068e1fac 100644 --- a/compiler/rustc_mir_build/src/build/custom/parse.rs +++ b/compiler/rustc_mir_build/src/build/custom/parse.rs @@ -68,7 +68,7 @@ macro_rules! parse_by_kind { } pub(crate) use parse_by_kind; -impl<'tcx, 'body> ParseCtxt<'tcx, 'body> { +impl<'a, 'tcx> ParseCtxt<'a, 'tcx> { /// Expressions should only ever be matched on after preparsing them. This removes extra scopes /// we don't care about. fn preparse(&self, expr_id: ExprId) -> ExprId { diff --git a/compiler/rustc_mir_build/src/build/custom/parse/instruction.rs b/compiler/rustc_mir_build/src/build/custom/parse/instruction.rs index 0b13ceb574d..0cbd2da10db 100644 --- a/compiler/rustc_mir_build/src/build/custom/parse/instruction.rs +++ b/compiler/rustc_mir_build/src/build/custom/parse/instruction.rs @@ -12,7 +12,7 @@ use super::{parse_by_kind, PResult, ParseCtxt}; use crate::build::custom::ParseError; use crate::build::expr::as_constant::as_constant_inner; -impl<'tcx, 'body> ParseCtxt<'tcx, 'body> { +impl<'a, 'tcx> ParseCtxt<'a, 'tcx> { pub(crate) fn parse_statement(&self, expr_id: ExprId) -> PResult> { parse_by_kind!(self, expr_id, _, "statement", @call(mir_storage_live, args) => { diff --git a/compiler/rustc_mir_build/src/errors.rs b/compiler/rustc_mir_build/src/errors.rs index 7f9eefd1d52..411e9420914 100644 --- a/compiler/rustc_mir_build/src/errors.rs +++ b/compiler/rustc_mir_build/src/errors.rs @@ -598,6 +598,8 @@ pub(crate) struct UnreachablePattern<'tcx> { #[note(mir_build_unreachable_covered_by_many)] pub(crate) covered_by_many: Option, pub(crate) covered_by_many_n_more_count: usize, + #[suggestion(code = "", applicability = "machine-applicable")] + pub(crate) suggest_remove: Option, } #[derive(Diagnostic)] diff --git a/compiler/rustc_mir_build/src/thir/pattern/check_match.rs b/compiler/rustc_mir_build/src/thir/pattern/check_match.rs index 4c066a68ef9..3fde6466d8c 100644 --- a/compiler/rustc_mir_build/src/thir/pattern/check_match.rs +++ b/compiler/rustc_mir_build/src/thir/pattern/check_match.rs @@ -413,7 +413,7 @@ impl<'p, 'tcx> MatchVisitor<'p, 'tcx> { // Emit lints in the order in which they occur in the file. redundant_subpats.sort_unstable_by_key(|(pat, _)| pat.data().span); for (pat, explanation) in redundant_subpats { - report_unreachable_pattern(cx, arm.arm_data, pat, &explanation) + report_unreachable_pattern(cx, arm.arm_data, pat, &explanation, None) } } } @@ -474,7 +474,11 @@ impl<'p, 'tcx> MatchVisitor<'p, 'tcx> { hir::MatchSource::ForLoopDesugar | hir::MatchSource::Postfix | hir::MatchSource::Normal - | hir::MatchSource::FormatArgs => report_arm_reachability(&cx, &report), + | hir::MatchSource::FormatArgs => { + let is_match_arm = + matches!(source, hir::MatchSource::Postfix | hir::MatchSource::Normal); + report_arm_reachability(&cx, &report, is_match_arm); + } // Unreachable patterns in try and await expressions occur when one of // the arms are an uninhabited type. Which is OK. hir::MatchSource::AwaitDesugar | hir::MatchSource::TryDesugar(_) => {} @@ -626,7 +630,7 @@ impl<'p, 'tcx> MatchVisitor<'p, 'tcx> { ) -> Result { let (cx, report) = self.analyze_binding(pat, Refutable, scrut)?; // Report if the pattern is unreachable, which can only occur when the type is uninhabited. - report_arm_reachability(&cx, &report); + report_arm_reachability(&cx, &report, false); // If the list of witnesses is empty, the match is exhaustive, i.e. the `if let` pattern is // irrefutable. Ok(if report.non_exhaustiveness_witnesses.is_empty() { Irrefutable } else { Refutable }) @@ -916,6 +920,7 @@ fn report_unreachable_pattern<'p, 'tcx>( hir_id: HirId, pat: &DeconstructedPat<'p, 'tcx>, explanation: &RedundancyExplanation<'p, 'tcx>, + whole_arm_span: Option, ) { static CAP_COVERED_BY_MANY: usize = 4; let pat_span = pat.data().span; @@ -928,6 +933,7 @@ fn report_unreachable_pattern<'p, 'tcx>( covered_by_one: None, covered_by_many: None, covered_by_many_n_more_count: 0, + suggest_remove: None, }; match explanation.covered_by.as_slice() { [] => { @@ -935,6 +941,7 @@ fn report_unreachable_pattern<'p, 'tcx>( lint.span = None; // Don't label the pattern itself lint.uninhabited_note = Some(()); // Give a link about empty types lint.matches_no_values = Some(pat_span); + lint.suggest_remove = whole_arm_span; // Suggest to remove the match arm pat.walk(&mut |subpat| { let ty = **subpat.ty(); if cx.is_uninhabited(ty) { @@ -982,10 +989,28 @@ fn report_unreachable_pattern<'p, 'tcx>( } /// Report unreachable arms, if any. -fn report_arm_reachability<'p, 'tcx>(cx: &PatCtxt<'p, 'tcx>, report: &UsefulnessReport<'p, 'tcx>) { +fn report_arm_reachability<'p, 'tcx>( + cx: &PatCtxt<'p, 'tcx>, + report: &UsefulnessReport<'p, 'tcx>, + is_match_arm: bool, +) { + let sm = cx.tcx.sess.source_map(); for (arm, is_useful) in report.arm_usefulness.iter() { if let Usefulness::Redundant(explanation) = is_useful { - report_unreachable_pattern(cx, arm.arm_data, arm.pat, explanation) + let hir_id = arm.arm_data; + let arm_span = cx.tcx.hir().span(hir_id); + let whole_arm_span = if is_match_arm { + // If the arm is followed by a comma, extend the span to include it. + let with_whitespace = sm.span_extend_while_whitespace(arm_span); + if let Some(comma) = sm.span_look_ahead(with_whitespace, ",", Some(1)) { + Some(arm_span.to(comma)) + } else { + Some(arm_span) + } + } else { + None + }; + report_unreachable_pattern(cx, hir_id, arm.pat, explanation, whole_arm_span) } } } diff --git a/compiler/rustc_mir_dataflow/src/elaborate_drops.rs b/compiler/rustc_mir_dataflow/src/elaborate_drops.rs index d7e738b8829..c4d06cbb1b0 100644 --- a/compiler/rustc_mir_dataflow/src/elaborate_drops.rs +++ b/compiler/rustc_mir_dataflow/src/elaborate_drops.rs @@ -155,11 +155,11 @@ pub trait DropElaborator<'a, 'tcx>: fmt::Debug { } #[derive(Debug)] -struct DropCtxt<'l, 'b, 'tcx, D> +struct DropCtxt<'a, 'b, 'tcx, D> where D: DropElaborator<'b, 'tcx>, { - elaborator: &'l mut D, + elaborator: &'a mut D, source_info: SourceInfo, @@ -192,7 +192,7 @@ pub fn elaborate_drop<'b, 'tcx, D>( DropCtxt { elaborator, source_info, place, path, succ, unwind }.elaborate_drop(bb) } -impl<'l, 'b, 'tcx, D> DropCtxt<'l, 'b, 'tcx, D> +impl<'a, 'b, 'tcx, D> DropCtxt<'a, 'b, 'tcx, D> where D: DropElaborator<'b, 'tcx>, 'tcx: 'b, diff --git a/compiler/rustc_mir_dataflow/src/impls/storage_liveness.rs b/compiler/rustc_mir_dataflow/src/impls/storage_liveness.rs index 6bf54c8db41..34ac5809a2e 100644 --- a/compiler/rustc_mir_dataflow/src/impls/storage_liveness.rs +++ b/compiler/rustc_mir_dataflow/src/impls/storage_liveness.rs @@ -17,7 +17,7 @@ impl<'a> MaybeStorageLive<'a> { } } -impl<'tcx, 'a> crate::AnalysisDomain<'tcx> for MaybeStorageLive<'a> { +impl<'a, 'tcx> crate::AnalysisDomain<'tcx> for MaybeStorageLive<'a> { type Domain = BitSet; const NAME: &'static str = "maybe_storage_live"; @@ -39,7 +39,7 @@ impl<'tcx, 'a> crate::AnalysisDomain<'tcx> for MaybeStorageLive<'a> { } } -impl<'tcx, 'a> crate::GenKillAnalysis<'tcx> for MaybeStorageLive<'a> { +impl<'a, 'tcx> crate::GenKillAnalysis<'tcx> for MaybeStorageLive<'a> { type Idx = Local; fn domain_size(&self, body: &Body<'tcx>) -> usize { @@ -89,7 +89,7 @@ impl<'a> MaybeStorageDead<'a> { } } -impl<'tcx, 'a> crate::AnalysisDomain<'tcx> for MaybeStorageDead<'a> { +impl<'a, 'tcx> crate::AnalysisDomain<'tcx> for MaybeStorageDead<'a> { type Domain = BitSet; const NAME: &'static str = "maybe_storage_dead"; @@ -110,7 +110,7 @@ impl<'tcx, 'a> crate::AnalysisDomain<'tcx> for MaybeStorageDead<'a> { } } -impl<'tcx, 'a> crate::GenKillAnalysis<'tcx> for MaybeStorageDead<'a> { +impl<'a, 'tcx> crate::GenKillAnalysis<'tcx> for MaybeStorageDead<'a> { type Idx = Local; fn domain_size(&self, body: &Body<'tcx>) -> usize { diff --git a/compiler/rustc_mir_transform/src/check_alignment.rs b/compiler/rustc_mir_transform/src/check_alignment.rs index e1d5152ae51..a9600f77c0b 100644 --- a/compiler/rustc_mir_transform/src/check_alignment.rs +++ b/compiler/rustc_mir_transform/src/check_alignment.rs @@ -62,14 +62,14 @@ impl<'tcx> crate::MirPass<'tcx> for CheckAlignment { } } -struct PointerFinder<'tcx, 'a> { +struct PointerFinder<'a, 'tcx> { tcx: TyCtxt<'tcx>, local_decls: &'a mut LocalDecls<'tcx>, param_env: ParamEnv<'tcx>, pointers: Vec<(Place<'tcx>, Ty<'tcx>)>, } -impl<'tcx, 'a> Visitor<'tcx> for PointerFinder<'tcx, 'a> { +impl<'a, 'tcx> Visitor<'tcx> for PointerFinder<'a, 'tcx> { fn visit_place(&mut self, place: &Place<'tcx>, context: PlaceContext, location: Location) { // We want to only check reads and writes to Places, so we specifically exclude // Borrow and RawBorrow. diff --git a/compiler/rustc_mir_transform/src/dataflow_const_prop.rs b/compiler/rustc_mir_transform/src/dataflow_const_prop.rs index ad9f9162606..997b8c06a96 100644 --- a/compiler/rustc_mir_transform/src/dataflow_const_prop.rs +++ b/compiler/rustc_mir_transform/src/dataflow_const_prop.rs @@ -554,13 +554,13 @@ impl<'tcx> Patch<'tcx> { } } -struct Collector<'tcx, 'locals> { +struct Collector<'a, 'tcx> { patch: Patch<'tcx>, - local_decls: &'locals LocalDecls<'tcx>, + local_decls: &'a LocalDecls<'tcx>, } -impl<'tcx, 'locals> Collector<'tcx, 'locals> { - pub(crate) fn new(tcx: TyCtxt<'tcx>, local_decls: &'locals LocalDecls<'tcx>) -> Self { +impl<'a, 'tcx> Collector<'a, 'tcx> { + pub(crate) fn new(tcx: TyCtxt<'tcx>, local_decls: &'a LocalDecls<'tcx>) -> Self { Self { patch: Patch::new(tcx), local_decls } } @@ -722,7 +722,7 @@ fn try_write_constant<'tcx>( impl<'mir, 'tcx> ResultsVisitor<'mir, 'tcx, Results<'tcx, ValueAnalysisWrapper>>> - for Collector<'tcx, '_> + for Collector<'_, 'tcx> { type Domain = State>; @@ -839,9 +839,9 @@ impl<'tcx> MutVisitor<'tcx> for Patch<'tcx> { } } -struct OperandCollector<'a, 'locals, 'tcx> { +struct OperandCollector<'a, 'b, 'tcx> { state: &'a State>, - visitor: &'a mut Collector<'tcx, 'locals>, + visitor: &'a mut Collector<'b, 'tcx>, ecx: &'a mut InterpCx<'tcx, DummyMachine>, map: &'a Map<'tcx>, } diff --git a/compiler/rustc_mir_transform/src/deduplicate_blocks.rs b/compiler/rustc_mir_transform/src/deduplicate_blocks.rs index ad204e76d0d..26b28c8c487 100644 --- a/compiler/rustc_mir_transform/src/deduplicate_blocks.rs +++ b/compiler/rustc_mir_transform/src/deduplicate_blocks.rs @@ -98,7 +98,7 @@ fn find_duplicates(body: &Body<'_>) -> FxHashMap { duplicates } -struct BasicBlockHashable<'tcx, 'a> { +struct BasicBlockHashable<'a, 'tcx> { basic_block_data: &'a BasicBlockData<'tcx>, } diff --git a/compiler/rustc_mir_transform/src/elaborate_box_derefs.rs b/compiler/rustc_mir_transform/src/elaborate_box_derefs.rs index 367a8c07593..57f7a9ef7f5 100644 --- a/compiler/rustc_mir_transform/src/elaborate_box_derefs.rs +++ b/compiler/rustc_mir_transform/src/elaborate_box_derefs.rs @@ -38,7 +38,7 @@ pub(super) fn build_projection<'tcx>( ] } -struct ElaborateBoxDerefVisitor<'tcx, 'a> { +struct ElaborateBoxDerefVisitor<'a, 'tcx> { tcx: TyCtxt<'tcx>, unique_did: DefId, nonnull_did: DefId, @@ -46,7 +46,7 @@ struct ElaborateBoxDerefVisitor<'tcx, 'a> { patch: MirPatch<'tcx>, } -impl<'tcx, 'a> MutVisitor<'tcx> for ElaborateBoxDerefVisitor<'tcx, 'a> { +impl<'a, 'tcx> MutVisitor<'tcx> for ElaborateBoxDerefVisitor<'a, 'tcx> { fn tcx(&self) -> TyCtxt<'tcx> { self.tcx } diff --git a/compiler/rustc_mir_transform/src/errors.rs b/compiler/rustc_mir_transform/src/errors.rs index 9a93c3a72b1..4550ef06315 100644 --- a/compiler/rustc_mir_transform/src/errors.rs +++ b/compiler/rustc_mir_transform/src/errors.rs @@ -89,7 +89,7 @@ pub(crate) struct FnItemRef { pub ident: String, } -pub(crate) struct MustNotSupend<'tcx, 'a> { +pub(crate) struct MustNotSupend<'a, 'tcx> { pub tcx: TyCtxt<'tcx>, pub yield_sp: Span, pub reason: Option, diff --git a/compiler/rustc_mir_transform/src/gvn.rs b/compiler/rustc_mir_transform/src/gvn.rs index 598bf61483d..0f08d920c5e 100644 --- a/compiler/rustc_mir_transform/src/gvn.rs +++ b/compiler/rustc_mir_transform/src/gvn.rs @@ -875,6 +875,95 @@ impl<'body, 'tcx> VnState<'body, 'tcx> { None } + fn try_as_place_elem( + &mut self, + proj: ProjectionElem>, + loc: Location, + ) -> Option> { + Some(match proj { + ProjectionElem::Deref => ProjectionElem::Deref, + ProjectionElem::Field(idx, ty) => ProjectionElem::Field(idx, ty), + ProjectionElem::Index(idx) => { + let Some(local) = self.try_as_local(idx, loc) else { + return None; + }; + self.reused_locals.insert(local); + ProjectionElem::Index(local) + } + ProjectionElem::ConstantIndex { offset, min_length, from_end } => { + ProjectionElem::ConstantIndex { offset, min_length, from_end } + } + ProjectionElem::Subslice { from, to, from_end } => { + ProjectionElem::Subslice { from, to, from_end } + } + ProjectionElem::Downcast(symbol, idx) => ProjectionElem::Downcast(symbol, idx), + ProjectionElem::OpaqueCast(idx) => ProjectionElem::OpaqueCast(idx), + ProjectionElem::Subtype(idx) => ProjectionElem::Subtype(idx), + }) + } + + fn simplify_aggregate_to_copy( + &mut self, + rvalue: &mut Rvalue<'tcx>, + location: Location, + fields: &[VnIndex], + variant_index: VariantIdx, + ) -> Option { + let Some(&first_field) = fields.first() else { + return None; + }; + let Value::Projection(copy_from_value, _) = *self.get(first_field) else { + return None; + }; + // All fields must correspond one-to-one and come from the same aggregate value. + if fields.iter().enumerate().any(|(index, &v)| { + if let Value::Projection(pointer, ProjectionElem::Field(from_index, _)) = *self.get(v) + && copy_from_value == pointer + && from_index.index() == index + { + return false; + } + true + }) { + return None; + } + + let mut copy_from_local_value = copy_from_value; + if let Value::Projection(pointer, proj) = *self.get(copy_from_value) + && let ProjectionElem::Downcast(_, read_variant) = proj + { + if variant_index == read_variant { + // When copying a variant, there is no need to downcast. + copy_from_local_value = pointer; + } else { + // The copied variant must be identical. + return None; + } + } + + let tcx = self.tcx; + let mut projection = SmallVec::<[PlaceElem<'tcx>; 1]>::new(); + loop { + if let Some(local) = self.try_as_local(copy_from_local_value, location) { + projection.reverse(); + let place = Place { local, projection: tcx.mk_place_elems(projection.as_slice()) }; + if rvalue.ty(self.local_decls, tcx) == place.ty(self.local_decls, tcx).ty { + self.reused_locals.insert(local); + *rvalue = Rvalue::Use(Operand::Copy(place)); + return Some(copy_from_value); + } + return None; + } else if let Value::Projection(pointer, proj) = *self.get(copy_from_local_value) + && let Some(proj) = self.try_as_place_elem(proj, location) + { + projection.push(proj); + copy_from_local_value = pointer; + } else { + return None; + } + } + } + fn simplify_aggregate( &mut self, rvalue: &mut Rvalue<'tcx>, @@ -971,6 +1060,13 @@ impl<'body, 'tcx> VnState<'body, 'tcx> { } } + if let AggregateTy::Def(_, _) = ty + && let Some(value) = + self.simplify_aggregate_to_copy(rvalue, location, &fields, variant_index) + { + return Some(value); + } + Some(self.insert(Value::Aggregate(ty, variant_index, fields))) } @@ -1485,7 +1581,7 @@ impl<'tcx> VnState<'_, 'tcx> { } /// If there is a local which is assigned `index`, and its assignment strictly dominates `loc`, - /// return it. + /// return it. If you used this local, add it to `reused_locals` to remove storage statements. fn try_as_local(&mut self, index: VnIndex, loc: Location) -> Option { let other = self.rev_locals.get(index)?; other diff --git a/compiler/rustc_mir_transform/src/instsimplify.rs b/compiler/rustc_mir_transform/src/instsimplify.rs index 0b344f29b07..5c8958924fb 100644 --- a/compiler/rustc_mir_transform/src/instsimplify.rs +++ b/compiler/rustc_mir_transform/src/instsimplify.rs @@ -63,13 +63,13 @@ impl<'tcx> crate::MirPass<'tcx> for InstSimplify { } } -struct InstSimplifyContext<'tcx, 'a> { +struct InstSimplifyContext<'a, 'tcx> { tcx: TyCtxt<'tcx>, local_decls: &'a LocalDecls<'tcx>, param_env: ParamEnv<'tcx>, } -impl<'tcx> InstSimplifyContext<'tcx, '_> { +impl<'tcx> InstSimplifyContext<'_, 'tcx> { fn should_simplify(&self, source_info: &SourceInfo, rvalue: &Rvalue<'tcx>) -> bool { self.should_simplify_custom(source_info, "Rvalue", rvalue) } diff --git a/compiler/rustc_mir_transform/src/jump_threading.rs b/compiler/rustc_mir_transform/src/jump_threading.rs index d48df59ada8..1810569bc8e 100644 --- a/compiler/rustc_mir_transform/src/jump_threading.rs +++ b/compiler/rustc_mir_transform/src/jump_threading.rs @@ -117,7 +117,7 @@ struct ThreadingOpportunity { target: BasicBlock, } -struct TOFinder<'tcx, 'a> { +struct TOFinder<'a, 'tcx> { tcx: TyCtxt<'tcx>, param_env: ty::ParamEnv<'tcx>, ecx: InterpCx<'tcx, DummyMachine>, @@ -183,7 +183,7 @@ impl<'a> ConditionSet<'a> { } } -impl<'tcx, 'a> TOFinder<'tcx, 'a> { +impl<'a, 'tcx> TOFinder<'a, 'tcx> { fn is_empty(&self, state: &State>) -> bool { state.all_bottom() } diff --git a/compiler/rustc_mir_transform/src/lib.rs b/compiler/rustc_mir_transform/src/lib.rs index 84d07d38330..424e7008326 100644 --- a/compiler/rustc_mir_transform/src/lib.rs +++ b/compiler/rustc_mir_transform/src/lib.rs @@ -330,7 +330,7 @@ fn mir_promoted( tcx.ensure_with_value().has_ffi_unwind_calls(def); // the `by_move_body` query uses the raw mir, so make sure it is run. - if tcx.needs_coroutine_by_move_body_def_id(def) { + if tcx.needs_coroutine_by_move_body_def_id(def.to_def_id()) { tcx.ensure_with_value().coroutine_by_move_body_def_id(def); } diff --git a/compiler/rustc_mir_transform/src/match_branches.rs b/compiler/rustc_mir_transform/src/match_branches.rs index 0f981425cfd..ad3126f66a6 100644 --- a/compiler/rustc_mir_transform/src/match_branches.rs +++ b/compiler/rustc_mir_transform/src/match_branches.rs @@ -295,7 +295,7 @@ struct SimplifyToExp { } #[derive(Clone, Copy)] -enum ExpectedTransformKind<'tcx, 'a> { +enum ExpectedTransformKind<'a, 'tcx> { /// Identical statements. Same(&'a StatementKind<'tcx>), /// Assignment statements have the same value. diff --git a/compiler/rustc_mir_transform/src/ssa.rs b/compiler/rustc_mir_transform/src/ssa.rs index cf8622cadd1..ba64216f9e1 100644 --- a/compiler/rustc_mir_transform/src/ssa.rs +++ b/compiler/rustc_mir_transform/src/ssa.rs @@ -235,7 +235,7 @@ impl SsaLocals { } } -struct SsaVisitor<'tcx, 'a> { +struct SsaVisitor<'a, 'tcx> { body: &'a Body<'tcx>, dominators: &'a Dominators, assignments: IndexVec>, @@ -261,7 +261,7 @@ impl SsaVisitor<'_, '_> { } } -impl<'tcx> Visitor<'tcx> for SsaVisitor<'tcx, '_> { +impl<'tcx> Visitor<'tcx> for SsaVisitor<'_, 'tcx> { fn visit_local(&mut self, local: Local, ctxt: PlaceContext, loc: Location) { match ctxt { PlaceContext::MutatingUse(MutatingUseContext::Projection) diff --git a/compiler/rustc_mir_transform/src/validate.rs b/compiler/rustc_mir_transform/src/validate.rs index 3b84755dded..e5837b1b475 100644 --- a/compiler/rustc_mir_transform/src/validate.rs +++ b/compiler/rustc_mir_transform/src/validate.rs @@ -1,7 +1,6 @@ //! Validates the MIR to ensure that invariants are upheld. use rustc_data_structures::fx::{FxHashMap, FxHashSet}; -use rustc_hir as hir; use rustc_hir::LangItem; use rustc_index::bit_set::BitSet; use rustc_index::IndexVec; @@ -717,10 +716,7 @@ impl<'a, 'tcx> Visitor<'tcx> for TypeChecker<'a, 'tcx> { // first place. let layout = if def_id == self.caller_body.source.def_id() { self.caller_body.coroutine_layout_raw() - } else if let Some(hir::CoroutineKind::Desugared( - _, - hir::CoroutineSource::Closure, - )) = self.tcx.coroutine_kind(def_id) + } else if self.tcx.needs_coroutine_by_move_body_def_id(def_id) && let ty::ClosureKind::FnOnce = args.as_coroutine().kind_ty().to_opt_closure_kind().unwrap() && self.caller_body.source.def_id() diff --git a/compiler/rustc_parse/src/parser/expr.rs b/compiler/rustc_parse/src/parser/expr.rs index 2d6edad2977..2d5a1914fa6 100644 --- a/compiler/rustc_parse/src/parser/expr.rs +++ b/compiler/rustc_parse/src/parser/expr.rs @@ -49,7 +49,7 @@ enum DestructuredFloat { /// 1.2 | 1.2e3 MiddleDot(Symbol, Span, Span, Symbol, Span), /// Invalid - Error, + Error(ErrorGuaranteed), } impl<'a> Parser<'a> { @@ -1008,7 +1008,7 @@ impl<'a> Parser<'a> { self.mk_expr_tuple_field_access(lo, ident1_span, base, sym1, None); self.mk_expr_tuple_field_access(lo, ident2_span, base1, sym2, suffix) } - DestructuredFloat::Error => base, + DestructuredFloat::Error(_) => base, }) } _ => { @@ -1018,7 +1018,7 @@ impl<'a> Parser<'a> { } } - fn error_unexpected_after_dot(&self) { + fn error_unexpected_after_dot(&self) -> ErrorGuaranteed { let actual = pprust::token_to_string(&self.token); let span = self.token.span; let sm = self.psess.source_map(); @@ -1028,17 +1028,19 @@ impl<'a> Parser<'a> { } _ => (span, actual), }; - self.dcx().emit_err(errors::UnexpectedTokenAfterDot { span, actual }); + self.dcx().emit_err(errors::UnexpectedTokenAfterDot { span, actual }) } - // We need an identifier or integer, but the next token is a float. - // Break the float into components to extract the identifier or integer. + /// We need an identifier or integer, but the next token is a float. + /// Break the float into components to extract the identifier or integer. + /// + /// See also [`TokenKind::break_two_token_op`] which does similar splitting of `>>` into `>`. + // // FIXME: With current `TokenCursor` it's hard to break tokens into more than 2 - // parts unless those parts are processed immediately. `TokenCursor` should either - // support pushing "future tokens" (would be also helpful to `break_and_eat`), or - // we should break everything including floats into more basic proc-macro style - // tokens in the lexer (probably preferable). - // See also `TokenKind::break_two_token_op` which does similar splitting of `>>` into `>`. + // parts unless those parts are processed immediately. `TokenCursor` should either + // support pushing "future tokens" (would be also helpful to `break_and_eat`), or + // we should break everything including floats into more basic proc-macro style + // tokens in the lexer (probably preferable). fn break_up_float(&self, float: Symbol, span: Span) -> DestructuredFloat { #[derive(Debug)] enum FloatComponent { @@ -1078,34 +1080,30 @@ impl<'a> Parser<'a> { DestructuredFloat::Single(Symbol::intern(i), span) } // 1. - [IdentLike(i), Punct('.')] => { - let (ident_span, dot_span) = if can_take_span_apart() { - let (span, ident_len) = (span.data(), BytePos::from_usize(i.len())); - let ident_span = span.with_hi(span.lo + ident_len); - let dot_span = span.with_lo(span.lo + ident_len); - (ident_span, dot_span) + [IdentLike(left), Punct('.')] => { + let (left_span, dot_span) = if can_take_span_apart() { + let left_span = span.with_hi(span.lo() + BytePos::from_usize(left.len())); + let dot_span = span.with_lo(left_span.hi()); + (left_span, dot_span) } else { (span, span) }; - let symbol = Symbol::intern(i); - DestructuredFloat::TrailingDot(symbol, ident_span, dot_span) + let left = Symbol::intern(left); + DestructuredFloat::TrailingDot(left, left_span, dot_span) } // 1.2 | 1.2e3 - [IdentLike(i1), Punct('.'), IdentLike(i2)] => { - let (ident1_span, dot_span, ident2_span) = if can_take_span_apart() { - let (span, ident1_len) = (span.data(), BytePos::from_usize(i1.len())); - let ident1_span = span.with_hi(span.lo + ident1_len); - let dot_span = span - .with_lo(span.lo + ident1_len) - .with_hi(span.lo + ident1_len + BytePos(1)); - let ident2_span = self.token.span.with_lo(span.lo + ident1_len + BytePos(1)); - (ident1_span, dot_span, ident2_span) + [IdentLike(left), Punct('.'), IdentLike(right)] => { + let (left_span, dot_span, right_span) = if can_take_span_apart() { + let left_span = span.with_hi(span.lo() + BytePos::from_usize(left.len())); + let dot_span = span.with_lo(left_span.hi()).with_hi(left_span.hi() + BytePos(1)); + let right_span = span.with_lo(dot_span.hi()); + (left_span, dot_span, right_span) } else { (span, span, span) }; - let symbol1 = Symbol::intern(i1); - let symbol2 = Symbol::intern(i2); - DestructuredFloat::MiddleDot(symbol1, ident1_span, dot_span, symbol2, ident2_span) + let left = Symbol::intern(left); + let right = Symbol::intern(right); + DestructuredFloat::MiddleDot(left, left_span, dot_span, right, right_span) } // 1e+ | 1e- (recovered) [IdentLike(_), Punct('+' | '-')] | @@ -1116,8 +1114,8 @@ impl<'a> Parser<'a> { // 1.2e+3 | 1.2e-3 [IdentLike(_), Punct('.'), IdentLike(_), Punct('+' | '-'), IdentLike(_)] => { // See the FIXME about `TokenCursor` above. - self.error_unexpected_after_dot(); - DestructuredFloat::Error + let guar = self.error_unexpected_after_dot(); + DestructuredFloat::Error(guar) } _ => panic!("unexpected components in a float token: {components:?}"), } @@ -1183,7 +1181,7 @@ impl<'a> Parser<'a> { fields.insert(start_idx, Ident::new(symbol2, span2)); fields.insert(start_idx, Ident::new(symbol1, span1)); } - DestructuredFloat::Error => { + DestructuredFloat::Error(_) => { trailing_dot = None; fields.insert(start_idx, Ident::new(symbol, self.prev_token.span)); } diff --git a/compiler/rustc_parse/src/parser/ty.rs b/compiler/rustc_parse/src/parser/ty.rs index dd1cc75c7ff..66019ffbc0a 100644 --- a/compiler/rustc_parse/src/parser/ty.rs +++ b/compiler/rustc_parse/src/parser/ty.rs @@ -607,9 +607,6 @@ impl<'a> Parser<'a> { let decl = self.parse_fn_decl(|_| false, AllowPlus::No, recover_return_sign)?; let whole_span = lo.to(self.prev_token.span); if let ast::Const::Yes(span) = constness { - // If we ever start to allow `const fn()`, then update - // feature gating for `#![feature(const_extern_fn)]` to - // cover it. self.dcx().emit_err(FnPointerCannotBeConst { span: whole_span, qualifier: span }); } if let Some(ast::CoroutineKind::Async { span, .. }) = coroutine_kind { diff --git a/compiler/rustc_passes/src/errors.rs b/compiler/rustc_passes/src/errors.rs index a985ecb019a..01052c60e94 100644 --- a/compiler/rustc_passes/src/errors.rs +++ b/compiler/rustc_passes/src/errors.rs @@ -1012,12 +1012,12 @@ pub(crate) struct FeatureStableTwice { #[derive(Diagnostic)] #[diag(passes_feature_previously_declared, code = E0711)] -pub(crate) struct FeaturePreviouslyDeclared<'a, 'b> { +pub(crate) struct FeaturePreviouslyDeclared<'a> { #[primary_span] pub span: Span, pub feature: Symbol, pub declared: &'a str, - pub prev_declared: &'b str, + pub prev_declared: &'a str, } pub(crate) struct BreakNonLoop<'a> { diff --git a/compiler/rustc_passes/src/loops.rs b/compiler/rustc_passes/src/loops.rs index c11562ae39e..af932bd69ab 100644 --- a/compiler/rustc_passes/src/loops.rs +++ b/compiler/rustc_passes/src/loops.rs @@ -9,7 +9,6 @@ use rustc_middle::hir::nested_filter; use rustc_middle::query::Providers; use rustc_middle::span_bug; use rustc_middle::ty::TyCtxt; -use rustc_session::Session; use rustc_span::hygiene::DesugaringKind; use rustc_span::{BytePos, Span}; use Context::*; @@ -64,8 +63,7 @@ impl fmt::Display for BreakContextKind { } #[derive(Clone)] -struct CheckLoopVisitor<'a, 'tcx> { - sess: &'a Session, +struct CheckLoopVisitor<'tcx> { tcx: TyCtxt<'tcx>, // Keep track of a stack of contexts, so that suggestions // are not made for contexts where it would be incorrect, @@ -76,12 +74,8 @@ struct CheckLoopVisitor<'a, 'tcx> { } fn check_mod_loops(tcx: TyCtxt<'_>, module_def_id: LocalModDefId) { - let mut check = CheckLoopVisitor { - sess: tcx.sess, - tcx, - cx_stack: vec![Normal], - block_breaks: Default::default(), - }; + let mut check = + CheckLoopVisitor { tcx, cx_stack: vec![Normal], block_breaks: Default::default() }; tcx.hir().visit_item_likes_in_module(module_def_id, &mut check); check.report_outside_loop_error(); } @@ -90,7 +84,7 @@ pub(crate) fn provide(providers: &mut Providers) { *providers = Providers { check_mod_loops, ..*providers }; } -impl<'a, 'hir> Visitor<'hir> for CheckLoopVisitor<'a, 'hir> { +impl<'hir> Visitor<'hir> for CheckLoopVisitor<'hir> { type NestedFilter = nested_filter::OnlyBodies; fn nested_visit_map(&mut self) -> Self::Map { @@ -129,7 +123,7 @@ impl<'a, 'hir> Visitor<'hir> for CheckLoopVisitor<'a, 'hir> { hir::ExprKind::If(cond, then, else_opt) => { self.visit_expr(cond); - let get_block = |ck_loop: &CheckLoopVisitor<'a, 'hir>, + let get_block = |ck_loop: &CheckLoopVisitor<'hir>, expr: &hir::Expr<'hir>| -> Option<&hir::Block<'hir>> { if let hir::ExprKind::Block(b, None) = expr.kind @@ -213,7 +207,7 @@ impl<'a, 'hir> Visitor<'hir> for CheckLoopVisitor<'a, 'hir> { Ok(loop_id) => Some(loop_id), Err(hir::LoopIdError::OutsideLoopScope) => None, Err(hir::LoopIdError::UnlabeledCfInWhileCondition) => { - self.sess.dcx().emit_err(UnlabeledCfInWhileCondition { + self.tcx.dcx().emit_err(UnlabeledCfInWhileCondition { span: e.span, cf_type: "break", }); @@ -248,7 +242,7 @@ impl<'a, 'hir> Visitor<'hir> for CheckLoopVisitor<'a, 'hir> { .label .map_or_else(String::new, |l| format!(" {}", l.ident)) ); - self.sess.dcx().emit_err(BreakNonLoop { + self.tcx.dcx().emit_err(BreakNonLoop { span: e.span, head, kind: kind.name(), @@ -280,14 +274,14 @@ impl<'a, 'hir> Visitor<'hir> for CheckLoopVisitor<'a, 'hir> { match destination.target_id { Ok(loop_id) => { if let Node::Block(block) = self.tcx.hir_node(loop_id) { - self.sess.dcx().emit_err(ContinueLabeledBlock { + self.tcx.dcx().emit_err(ContinueLabeledBlock { span: e.span, block_span: block.span, }); } } Err(hir::LoopIdError::UnlabeledCfInWhileCondition) => { - self.sess.dcx().emit_err(UnlabeledCfInWhileCondition { + self.tcx.dcx().emit_err(UnlabeledCfInWhileCondition { span: e.span, cf_type: "continue", }); @@ -306,10 +300,10 @@ impl<'a, 'hir> Visitor<'hir> for CheckLoopVisitor<'a, 'hir> { } } -impl<'a, 'hir> CheckLoopVisitor<'a, 'hir> { +impl<'hir> CheckLoopVisitor<'hir> { fn with_context(&mut self, cx: Context, f: F) where - F: FnOnce(&mut CheckLoopVisitor<'a, 'hir>), + F: FnOnce(&mut CheckLoopVisitor<'hir>), { self.cx_stack.push(cx); f(self); @@ -326,7 +320,7 @@ impl<'a, 'hir> CheckLoopVisitor<'a, 'hir> { match self.cx_stack[cx_pos] { LabeledBlock | Loop(_) => {} Closure(closure_span) => { - self.sess.dcx().emit_err(BreakInsideClosure { + self.tcx.dcx().emit_err(BreakInsideClosure { span, closure_span, name: &br_cx_kind.to_string(), @@ -343,7 +337,7 @@ impl<'a, 'hir> CheckLoopVisitor<'a, 'hir> { hir::CoroutineSource::Closure => "closure", hir::CoroutineSource::Fn => "function", }; - self.sess.dcx().emit_err(BreakInsideCoroutine { + self.tcx.dcx().emit_err(BreakInsideCoroutine { span, coroutine_span, name: &br_cx_kind.to_string(), @@ -366,7 +360,7 @@ impl<'a, 'hir> CheckLoopVisitor<'a, 'hir> { self.require_break_cx(br_cx_kind, span, break_span, cx_pos - 1); } Normal | AnonConst | Fn | UnlabeledBlock(_) | UnlabeledIfBlock(_) | ConstBlock => { - self.sess.dcx().emit_err(OutsideLoop { + self.tcx.dcx().emit_err(OutsideLoop { spans: vec![span], name: &br_cx_kind.to_string(), is_break: br_cx_kind == BreakContextKind::Break, @@ -386,7 +380,7 @@ impl<'a, 'hir> CheckLoopVisitor<'a, 'hir> { && self.cx_stack.last() == Some(&LabeledBlock) && label.label.is_none() { - self.sess.dcx().emit_err(UnlabeledInLabeledBlock { span, cf_type }); + self.tcx.dcx().emit_err(UnlabeledInLabeledBlock { span, cf_type }); return true; } false @@ -394,7 +388,7 @@ impl<'a, 'hir> CheckLoopVisitor<'a, 'hir> { fn report_outside_loop_error(&self) { for (s, block) in &self.block_breaks { - self.sess.dcx().emit_err(OutsideLoop { + self.tcx.dcx().emit_err(OutsideLoop { spans: block.spans.clone(), name: &block.name, is_break: true, diff --git a/compiler/rustc_privacy/src/lib.rs b/compiler/rustc_privacy/src/lib.rs index 572f71d7c77..c7078e1a27a 100644 --- a/compiler/rustc_privacy/src/lib.rs +++ b/compiler/rustc_privacy/src/lib.rs @@ -852,12 +852,12 @@ impl<'tcx> DefIdVisitor<'tcx> for ReachEverythingInTheInterfaceVisitor<'_, 'tcx> //////////////////////////////////////////////////////////////////////////////// /// Visitor, used for EffectiveVisibilities table checking //////////////////////////////////////////////////////////////////////////////// -pub struct TestReachabilityVisitor<'tcx, 'a> { +pub struct TestReachabilityVisitor<'a, 'tcx> { tcx: TyCtxt<'tcx>, effective_visibilities: &'a EffectiveVisibilities, } -impl<'tcx, 'a> TestReachabilityVisitor<'tcx, 'a> { +impl<'a, 'tcx> TestReachabilityVisitor<'a, 'tcx> { fn effective_visibility_diagnostic(&mut self, def_id: LocalDefId) { if self.tcx.has_attr(def_id, sym::rustc_effective_visibility) { let mut error_msg = String::new(); @@ -878,7 +878,7 @@ impl<'tcx, 'a> TestReachabilityVisitor<'tcx, 'a> { } } -impl<'tcx, 'a> Visitor<'tcx> for TestReachabilityVisitor<'tcx, 'a> { +impl<'a, 'tcx> Visitor<'tcx> for TestReachabilityVisitor<'a, 'tcx> { fn visit_item(&mut self, item: &'tcx hir::Item<'tcx>) { self.effective_visibility_diagnostic(item.owner_id.def_id); @@ -1425,12 +1425,12 @@ impl<'tcx> DefIdVisitor<'tcx> for SearchInterfaceForPrivateItemsVisitor<'tcx> { } } -struct PrivateItemsInPublicInterfacesChecker<'tcx, 'a> { +struct PrivateItemsInPublicInterfacesChecker<'a, 'tcx> { tcx: TyCtxt<'tcx>, effective_visibilities: &'a EffectiveVisibilities, } -impl<'tcx> PrivateItemsInPublicInterfacesChecker<'tcx, '_> { +impl<'tcx> PrivateItemsInPublicInterfacesChecker<'_, 'tcx> { fn check( &self, def_id: LocalDefId, diff --git a/compiler/rustc_query_impl/src/profiling_support.rs b/compiler/rustc_query_impl/src/profiling_support.rs index 599316d0cad..536044298f0 100644 --- a/compiler/rustc_query_impl/src/profiling_support.rs +++ b/compiler/rustc_query_impl/src/profiling_support.rs @@ -19,18 +19,18 @@ impl QueryKeyStringCache { } } -struct QueryKeyStringBuilder<'p, 'tcx> { - profiler: &'p SelfProfiler, +struct QueryKeyStringBuilder<'a, 'tcx> { + profiler: &'a SelfProfiler, tcx: TyCtxt<'tcx>, - string_cache: &'p mut QueryKeyStringCache, + string_cache: &'a mut QueryKeyStringCache, } -impl<'p, 'tcx> QueryKeyStringBuilder<'p, 'tcx> { +impl<'a, 'tcx> QueryKeyStringBuilder<'a, 'tcx> { fn new( - profiler: &'p SelfProfiler, + profiler: &'a SelfProfiler, tcx: TyCtxt<'tcx>, - string_cache: &'p mut QueryKeyStringCache, - ) -> QueryKeyStringBuilder<'p, 'tcx> { + string_cache: &'a mut QueryKeyStringCache, + ) -> QueryKeyStringBuilder<'a, 'tcx> { QueryKeyStringBuilder { profiler, tcx, string_cache } } diff --git a/compiler/rustc_session/messages.ftl b/compiler/rustc_session/messages.ftl index a4fbab8477b..1816d1278fe 100644 --- a/compiler/rustc_session/messages.ftl +++ b/compiler/rustc_session/messages.ftl @@ -107,6 +107,16 @@ session_sanitizer_not_supported = {$us} sanitizer is not supported for this targ session_sanitizers_not_supported = {$us} sanitizers are not supported for this target session_skipping_const_checks = skipping const checks + +session_soft_float_deprecated = + `-Csoft-float` is unsound and deprecated; use a corresponding *eabi target instead + .note = it will be removed or ignored in a future version of Rust +session_soft_float_deprecated_issue = see issue #129893 for more information + +session_soft_float_ignored = + `-Csoft-float` is ignored on this target; it only has an effect on *eabihf targets + .note = this may become a hard error in a future version of Rust + session_split_debuginfo_unstable_platform = `-Csplit-debuginfo={$debuginfo}` is unstable on this platform session_split_lto_unit_requires_lto = `-Zsplit-lto-unit` requires `-Clto`, `-Clto=thin`, or `-Clinker-plugin-lto` diff --git a/compiler/rustc_session/src/errors.rs b/compiler/rustc_session/src/errors.rs index 462e2a97c33..dbb74d1e244 100644 --- a/compiler/rustc_session/src/errors.rs +++ b/compiler/rustc_session/src/errors.rs @@ -490,3 +490,14 @@ pub(crate) struct FunctionReturnThunkExternRequiresNonLargeCodeModel; pub(crate) struct FailedToCreateProfiler { pub(crate) err: String, } + +#[derive(Diagnostic)] +#[diag(session_soft_float_ignored)] +#[note] +pub(crate) struct SoftFloatIgnored; + +#[derive(Diagnostic)] +#[diag(session_soft_float_deprecated)] +#[note] +#[note(session_soft_float_deprecated_issue)] +pub(crate) struct SoftFloatDeprecated; diff --git a/compiler/rustc_session/src/options.rs b/compiler/rustc_session/src/options.rs index e487a2501e3..62d3482a7f1 100644 --- a/compiler/rustc_session/src/options.rs +++ b/compiler/rustc_session/src/options.rs @@ -1515,6 +1515,7 @@ options! { // - src/doc/rustc/src/codegen-options/index.md // tidy-alphabetical-start + #[rustc_lint_opt_deny_field_access("documented to do nothing")] ar: String = (String::new(), parse_string, [UNTRACKED], "this option is deprecated and does nothing"), #[rustc_lint_opt_deny_field_access("use `Session::code_model` instead of this field")] @@ -1547,6 +1548,7 @@ options! { "force use of unwind tables"), incremental: Option = (None, parse_opt_string, [UNTRACKED], "enable incremental compilation"), + #[rustc_lint_opt_deny_field_access("documented to do nothing")] inline_threshold: Option = (None, parse_opt_number, [TRACKED], "this option is deprecated and does nothing \ (consider using `-Cllvm-args=--inline-threshold=...`)"), @@ -1583,6 +1585,7 @@ options! { "give an empty list of passes to the pass manager"), no_redzone: Option = (None, parse_opt_bool, [TRACKED], "disable the use of the redzone"), + #[rustc_lint_opt_deny_field_access("documented to do nothing")] no_stack_check: bool = (false, parse_no_flag, [UNTRACKED], "this option is deprecated and does nothing"), no_vectorize_loops: bool = (false, parse_no_flag, [TRACKED], @@ -1619,7 +1622,7 @@ options! { save_temps: bool = (false, parse_bool, [UNTRACKED], "save all temporary output files during compilation (default: no)"), soft_float: bool = (false, parse_bool, [TRACKED], - "use soft float ABI (*eabihf targets only) (default: no)"), + "deprecated option: use soft float ABI (*eabihf targets only) (default: no)"), #[rustc_lint_opt_deny_field_access("use `Session::split_debuginfo` instead of this field")] split_debuginfo: Option = (None, parse_split_debuginfo, [TRACKED], "how to handle split-debuginfo, a platform-specific option"), diff --git a/compiler/rustc_session/src/session.rs b/compiler/rustc_session/src/session.rs index 387ae1b78c4..2d90177ccea 100644 --- a/compiler/rustc_session/src/session.rs +++ b/compiler/rustc_session/src/session.rs @@ -1348,6 +1348,16 @@ fn validate_commandline_args_with_session_available(sess: &Session) { } } } + + if sess.opts.cg.soft_float { + if sess.target.arch == "arm" && sess.target.abi == "eabihf" { + sess.dcx().emit_warn(errors::SoftFloatDeprecated); + } else { + // All `use_softfp` does is the equivalent of `-mfloat-abi` in GCC/clang, which only exists on ARM targets. + // We document this flag to only affect `*eabihf` targets, so let's show a warning for all other targets. + sess.dcx().emit_warn(errors::SoftFloatIgnored); + } + } } /// Holds data on the current incremental compilation session, if there is one. diff --git a/compiler/rustc_target/src/spec/targets/armv8r_none_eabihf.rs b/compiler/rustc_target/src/spec/targets/armv8r_none_eabihf.rs index 042a9a14071..762084291a6 100644 --- a/compiler/rustc_target/src/spec/targets/armv8r_none_eabihf.rs +++ b/compiler/rustc_target/src/spec/targets/armv8r_none_eabihf.rs @@ -21,16 +21,16 @@ pub(crate) fn target() -> Target { linker: Some("rust-lld".into()), relocation_model: RelocModel::Static, panic_strategy: PanicStrategy::Abort, - // The Cortex-R52 has two variants with respect to floating-point support: - // 1. fp-armv8, SP-only, with 16 DP (32 SP) registers - // 2. neon-fp-armv8, SP+DP, with 32 DP registers - // Use the lesser of these two options as the default, as it will produce code - // compatible with either variant. + // Armv8-R requires a minimum set of floating-point features equivalent to: + // fp-armv8, SP-only, with 16 DP (32 SP) registers + // LLVM defines Armv8-R to include these features automatically. + // + // The Cortex-R52 supports these default features and optionally includes: + // neon-fp-armv8, SP+DP, with 32 DP registers // // Reference: // Arm Cortex-R52 Processor Technical Reference Manual // - Chapter 15 Advanced SIMD and floating-point support - features: "+fp-armv8,-fp64,-d32".into(), max_atomic_width: Some(64), emit_debug_gdb_scripts: false, // GCC defaults to 8 for arm-none here. 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 38d06f53fa6..b8ac83e8f96 100644 --- a/compiler/rustc_trait_selection/src/error_reporting/infer/region.rs +++ b/compiler/rustc_trait_selection/src/error_reporting/infer/region.rs @@ -842,14 +842,14 @@ impl<'a, 'tcx> TypeErrCtxt<'a, 'tcx> { lifetime: Region<'tcx>, add_lt_suggs: &mut Vec<(Span, String)>, ) -> String { - struct LifetimeReplaceVisitor<'tcx, 'a> { + struct LifetimeReplaceVisitor<'a, 'tcx> { tcx: TyCtxt<'tcx>, needle: hir::LifetimeName, new_lt: &'a str, add_lt_suggs: &'a mut Vec<(Span, String)>, } - impl<'hir, 'tcx> hir::intravisit::Visitor<'hir> for LifetimeReplaceVisitor<'tcx, '_> { + impl<'hir, 'tcx> hir::intravisit::Visitor<'hir> for LifetimeReplaceVisitor<'_, 'tcx> { fn visit_lifetime(&mut self, lt: &'hir hir::Lifetime) { if lt.res == self.needle { self.add_lt_suggs.push(lt.suggestion(self.new_lt)); diff --git a/compiler/rustc_trait_selection/src/error_reporting/traits/mod.rs b/compiler/rustc_trait_selection/src/error_reporting/traits/mod.rs index 9aa6d1f3d46..752ef729113 100644 --- a/compiler/rustc_trait_selection/src/error_reporting/traits/mod.rs +++ b/compiler/rustc_trait_selection/src/error_reporting/traits/mod.rs @@ -344,7 +344,8 @@ pub(crate) fn to_pretty_impl_header(tcx: TyCtxt<'_>, impl_def_id: DefId) -> Opti write!( w, - " {} for {}", + " {}{} for {}", + tcx.impl_polarity(impl_def_id).as_str(), trait_ref.print_only_trait_path(), tcx.type_of(impl_def_id).instantiate_identity() ) diff --git a/compiler/rustc_trait_selection/src/error_reporting/traits/suggestions.rs b/compiler/rustc_trait_selection/src/error_reporting/traits/suggestions.rs index b13aede509a..e2796c76412 100644 --- a/compiler/rustc_trait_selection/src/error_reporting/traits/suggestions.rs +++ b/compiler/rustc_trait_selection/src/error_reporting/traits/suggestions.rs @@ -61,9 +61,9 @@ pub enum CoroutineInteriorOrUpvar { // This type provides a uniform interface to retrieve data on coroutines, whether it originated from // the local crate being compiled or from a foreign crate. #[derive(Debug)] -struct CoroutineData<'tcx, 'a>(&'a TypeckResults<'tcx>); +struct CoroutineData<'a, 'tcx>(&'a TypeckResults<'tcx>); -impl<'tcx, 'a> CoroutineData<'tcx, 'a> { +impl<'a, 'tcx> CoroutineData<'a, 'tcx> { /// Try to get information about variables captured by the coroutine that matches a type we are /// looking for with `ty_matches` function. We uses it to find upvar which causes a failure to /// meet an obligation diff --git a/compiler/rustc_trait_selection/src/traits/query/normalize.rs b/compiler/rustc_trait_selection/src/traits/query/normalize.rs index f1b524d1325..525fba69a87 100644 --- a/compiler/rustc_trait_selection/src/traits/query/normalize.rs +++ b/compiler/rustc_trait_selection/src/traits/query/normalize.rs @@ -25,7 +25,7 @@ use crate::traits::{ }; #[extension(pub trait QueryNormalizeExt<'tcx>)] -impl<'cx, 'tcx> At<'cx, 'tcx> { +impl<'a, 'tcx> At<'a, 'tcx> { /// Normalize `value` in the context of the inference context, /// yielding a resulting type, or an error if `value` cannot be /// normalized. If you don't care about regions, you should prefer @@ -160,9 +160,9 @@ impl<'tcx> TypeVisitor> for MaxEscapingBoundVarVisitor { } } -struct QueryNormalizer<'cx, 'tcx> { - infcx: &'cx InferCtxt<'tcx>, - cause: &'cx ObligationCause<'tcx>, +struct QueryNormalizer<'a, 'tcx> { + infcx: &'a InferCtxt<'tcx>, + cause: &'a ObligationCause<'tcx>, param_env: ty::ParamEnv<'tcx>, obligations: Vec>, cache: SsoHashMap, Ty<'tcx>>, @@ -170,7 +170,7 @@ struct QueryNormalizer<'cx, 'tcx> { universes: Vec>, } -impl<'cx, 'tcx> FallibleTypeFolder> for QueryNormalizer<'cx, 'tcx> { +impl<'a, 'tcx> FallibleTypeFolder> for QueryNormalizer<'a, 'tcx> { type Error = NoSolution; fn cx(&self) -> TyCtxt<'tcx> { diff --git a/compiler/rustc_trait_selection/src/traits/util.rs b/compiler/rustc_trait_selection/src/traits/util.rs index 0fb13799e67..99445d03965 100644 --- a/compiler/rustc_trait_selection/src/traits/util.rs +++ b/compiler/rustc_trait_selection/src/traits/util.rs @@ -332,8 +332,8 @@ pub fn with_replaced_escaping_bound_vars< } } -pub struct BoundVarReplacer<'me, 'tcx> { - infcx: &'me InferCtxt<'tcx>, +pub struct BoundVarReplacer<'a, 'tcx> { + infcx: &'a InferCtxt<'tcx>, // These three maps track the bound variable that were replaced by placeholders. It might be // nice to remove these since we already have the `kind` in the placeholder; we really just need // the `var` (but we *could* bring that into scope if we were to track them as we pass them). @@ -345,15 +345,15 @@ pub struct BoundVarReplacer<'me, 'tcx> { current_index: ty::DebruijnIndex, // The `UniverseIndex` of the binding levels above us. These are optional, since we are lazy: // we don't actually create a universe until we see a bound var we have to replace. - universe_indices: &'me mut Vec>, + universe_indices: &'a mut Vec>, } -impl<'me, 'tcx> BoundVarReplacer<'me, 'tcx> { +impl<'a, 'tcx> BoundVarReplacer<'a, 'tcx> { /// Returns `Some` if we *were* able to replace bound vars. If there are any bound vars that /// use a binding level above `universe_indices.len()`, we fail. pub fn replace_bound_vars>>( - infcx: &'me InferCtxt<'tcx>, - universe_indices: &'me mut Vec>, + infcx: &'a InferCtxt<'tcx>, + universe_indices: &'a mut Vec>, value: T, ) -> ( T, @@ -479,22 +479,22 @@ impl<'tcx> TypeFolder> for BoundVarReplacer<'_, 'tcx> { } /// The inverse of [`BoundVarReplacer`]: replaces placeholders with the bound vars from which they came. -pub struct PlaceholderReplacer<'me, 'tcx> { - infcx: &'me InferCtxt<'tcx>, +pub struct PlaceholderReplacer<'a, 'tcx> { + infcx: &'a InferCtxt<'tcx>, mapped_regions: FxIndexMap, mapped_types: FxIndexMap, mapped_consts: BTreeMap, - universe_indices: &'me [Option], + universe_indices: &'a [Option], current_index: ty::DebruijnIndex, } -impl<'me, 'tcx> PlaceholderReplacer<'me, 'tcx> { +impl<'a, 'tcx> PlaceholderReplacer<'a, 'tcx> { pub fn replace_placeholders>>( - infcx: &'me InferCtxt<'tcx>, + infcx: &'a InferCtxt<'tcx>, mapped_regions: FxIndexMap, mapped_types: FxIndexMap, mapped_consts: BTreeMap, - universe_indices: &'me [Option], + universe_indices: &'a [Option], value: T, ) -> T { let mut replacer = PlaceholderReplacer { diff --git a/compiler/rustc_transmute/src/layout/tree.rs b/compiler/rustc_transmute/src/layout/tree.rs index c3fd771b797..b5ce465a173 100644 --- a/compiler/rustc_transmute/src/layout/tree.rs +++ b/compiler/rustc_transmute/src/layout/tree.rs @@ -175,7 +175,7 @@ pub(crate) mod rustc { use rustc_middle::ty::{self, AdtDef, AdtKind, List, ScalarInt, Ty, TyCtxt, TypeVisitableExt}; use rustc_span::ErrorGuaranteed; use rustc_target::abi::{ - FieldIdx, FieldsShape, Layout, Size, TyAndLayout, VariantIdx, Variants, + FieldIdx, FieldsShape, Layout, Size, TagEncoding, TyAndLayout, VariantIdx, Variants, }; use super::Tree; @@ -319,11 +319,17 @@ pub(crate) mod rustc { assert!(def.is_enum()); // Computes the variant of a given index. - let layout_of_variant = |index| { + let layout_of_variant = |index, encoding: Option>| { let tag = cx.tcx.tag_for_variant((cx.tcx.erase_regions(ty), index)); let variant_def = Def::Variant(def.variant(index)); let variant_layout = ty_variant(cx, (ty, layout), index); - Self::from_variant(variant_def, tag, (ty, variant_layout), layout.size, cx) + Self::from_variant( + variant_def, + tag.map(|tag| (tag, index, encoding.unwrap())), + (ty, variant_layout), + layout.size, + cx, + ) }; // We consider three kinds of enums, each demanding a different @@ -345,9 +351,9 @@ pub(crate) mod rustc { Variants::Single { index } => { // `Variants::Single` on enums with variants denotes that // the enum delegates its layout to the variant at `index`. - layout_of_variant(*index) + layout_of_variant(*index, None) } - Variants::Multiple { tag_field, .. } => { + Variants::Multiple { tag, tag_encoding, tag_field, .. } => { // `Variants::Multiple` denotes an enum with multiple // variants. The layout of such an enum is the disjunction // of the layouts of its tagged variants. @@ -359,7 +365,7 @@ pub(crate) mod rustc { let variants = def.discriminants(cx.tcx()).try_fold( Self::uninhabited(), |variants, (idx, ref discriminant)| { - let variant = layout_of_variant(idx)?; + let variant = layout_of_variant(idx, Some(tag_encoding.clone()))?; Result::::Ok(variants.or(variant)) }, )?; @@ -380,7 +386,7 @@ pub(crate) mod rustc { /// `0`. fn from_variant( def: Def<'tcx>, - tag: Option, + tag: Option<(ScalarInt, VariantIdx, TagEncoding)>, (ty, layout): (Ty<'tcx>, Layout<'tcx>), total_size: Size, cx: LayoutCx<'tcx, TyCtxt<'tcx>>, @@ -400,9 +406,18 @@ pub(crate) mod rustc { let mut struct_tree = Self::def(def); // If a `tag` is provided, place it at the start of the layout. - if let Some(tag) = tag { - size += tag.size(); - struct_tree = struct_tree.then(Self::from_tag(tag, cx.tcx)); + if let Some((tag, index, encoding)) = &tag { + match encoding { + TagEncoding::Direct => { + size += tag.size(); + } + TagEncoding::Niche { niche_variants, .. } => { + if !niche_variants.contains(index) { + size += tag.size(); + } + } + } + struct_tree = struct_tree.then(Self::from_tag(*tag, cx.tcx)); } // Append the fields, in memory order, to the layout. diff --git a/compiler/rustc_ty_utils/src/layout_sanity_check.rs b/compiler/rustc_ty_utils/src/layout_sanity_check.rs index 2223aca28d1..8378237fe2f 100644 --- a/compiler/rustc_ty_utils/src/layout_sanity_check.rs +++ b/compiler/rustc_ty_utils/src/layout_sanity_check.rs @@ -28,7 +28,7 @@ pub(super) fn sanity_check_layout<'tcx>( } /// Yields non-ZST fields of the type - fn non_zst_fields<'tcx, 'a>( + fn non_zst_fields<'a, 'tcx>( cx: &'a LayoutCx<'tcx, TyCtxt<'tcx>>, layout: &'a TyAndLayout<'tcx>, ) -> impl Iterator)> + 'a { diff --git a/compiler/rustc_type_ir/src/predicate.rs b/compiler/rustc_type_ir/src/predicate.rs index b30346ffc53..e4bf1e1379c 100644 --- a/compiler/rustc_type_ir/src/predicate.rs +++ b/compiler/rustc_type_ir/src/predicate.rs @@ -196,6 +196,17 @@ impl fmt::Display for ImplPolarity { } } +impl ImplPolarity { + /// The polarity marker in front of the impl trait ref if applicable. + pub fn as_str(self) -> &'static str { + match self { + Self::Positive => "", + Self::Negative => "!", + Self::Reservation => "", + } + } +} + /// Polarity for a trait predicate. May either be negative or positive. /// Distinguished from [`ImplPolarity`] since we never compute goals with /// "reservation" level. diff --git a/config.example.toml b/config.example.toml index 2b5e9ae117d..c66d65e639a 100644 --- a/config.example.toml +++ b/config.example.toml @@ -942,3 +942,6 @@ # Copy the linker, DLLs, and various libraries from MinGW into the Rust toolchain. # Only applies when the host or target is pc-windows-gnu. #include-mingw-linker = true + +# Whether to vendor dependencies for the dist tarball. +#vendor = if "is a tarball source" || "is a git repository" { true } else { false } diff --git a/library/alloc/src/boxed.rs b/library/alloc/src/boxed.rs index 4b1d493113c..5978908e8f5 100644 --- a/library/alloc/src/boxed.rs +++ b/library/alloc/src/boxed.rs @@ -1060,6 +1060,59 @@ impl Box { pub unsafe fn from_raw(raw: *mut T) -> Self { unsafe { Self::from_raw_in(raw, Global) } } + + /// Constructs a box from a `NonNull` pointer. + /// + /// After calling this function, the `NonNull` pointer is owned by + /// the resulting `Box`. Specifically, the `Box` destructor will call + /// the destructor of `T` and free the allocated memory. For this + /// to be safe, the memory must have been allocated in accordance + /// with the [memory layout] used by `Box` . + /// + /// # Safety + /// + /// This function is unsafe because improper use may lead to + /// memory problems. For example, a double-free may occur if the + /// function is called twice on the same `NonNull` pointer. + /// + /// The safety conditions are described in the [memory layout] section. + /// + /// # Examples + /// + /// Recreate a `Box` which was previously converted to a `NonNull` + /// pointer using [`Box::into_non_null`]: + /// ``` + /// #![feature(box_vec_non_null)] + /// + /// let x = Box::new(5); + /// let non_null = Box::into_non_null(x); + /// let x = unsafe { Box::from_non_null(non_null) }; + /// ``` + /// Manually create a `Box` from scratch by using the global allocator: + /// ``` + /// #![feature(box_vec_non_null)] + /// + /// use std::alloc::{alloc, Layout}; + /// use std::ptr::NonNull; + /// + /// unsafe { + /// let non_null = NonNull::new(alloc(Layout::new::()).cast::()) + /// .expect("allocation failed"); + /// // In general .write is required to avoid attempting to destruct + /// // the (uninitialized) previous contents of `non_null`. + /// non_null.write(5); + /// let x = Box::from_non_null(non_null); + /// } + /// ``` + /// + /// [memory layout]: self#memory-layout + /// [`Layout`]: crate::Layout + #[unstable(feature = "box_vec_non_null", reason = "new API", issue = "130364")] + #[inline] + #[must_use = "call `drop(Box::from_non_null(ptr))` if you intend to drop the `Box`"] + pub unsafe fn from_non_null(ptr: NonNull) -> Self { + unsafe { Self::from_raw(ptr.as_ptr()) } + } } impl Box { @@ -1117,6 +1170,61 @@ impl Box { Box(unsafe { Unique::new_unchecked(raw) }, alloc) } + /// Constructs a box from a `NonNull` pointer in the given allocator. + /// + /// After calling this function, the `NonNull` pointer is owned by + /// the resulting `Box`. Specifically, the `Box` destructor will call + /// the destructor of `T` and free the allocated memory. For this + /// to be safe, the memory must have been allocated in accordance + /// with the [memory layout] used by `Box` . + /// + /// # Safety + /// + /// This function is unsafe because improper use may lead to + /// memory problems. For example, a double-free may occur if the + /// function is called twice on the same raw pointer. + /// + /// + /// # Examples + /// + /// Recreate a `Box` which was previously converted to a `NonNull` pointer + /// using [`Box::into_non_null_with_allocator`]: + /// ``` + /// #![feature(allocator_api, box_vec_non_null)] + /// + /// use std::alloc::System; + /// + /// let x = Box::new_in(5, System); + /// let (non_null, alloc) = Box::into_non_null_with_allocator(x); + /// let x = unsafe { Box::from_non_null_in(non_null, alloc) }; + /// ``` + /// Manually create a `Box` from scratch by using the system allocator: + /// ``` + /// #![feature(allocator_api, box_vec_non_null, slice_ptr_get)] + /// + /// use std::alloc::{Allocator, Layout, System}; + /// + /// unsafe { + /// let non_null = System.allocate(Layout::new::())?.cast::(); + /// // In general .write is required to avoid attempting to destruct + /// // the (uninitialized) previous contents of `non_null`. + /// non_null.write(5); + /// let x = Box::from_non_null_in(non_null, System); + /// } + /// # Ok::<(), std::alloc::AllocError>(()) + /// ``` + /// + /// [memory layout]: self#memory-layout + /// [`Layout`]: crate::Layout + #[unstable(feature = "allocator_api", issue = "32838")] + // #[unstable(feature = "box_vec_non_null", reason = "new API", issue = "130364")] + #[rustc_const_unstable(feature = "const_box", issue = "92521")] + #[inline] + pub const unsafe fn from_non_null_in(raw: NonNull, alloc: A) -> Self { + // SAFETY: guaranteed by the caller. + unsafe { Box::from_raw_in(raw.as_ptr(), alloc) } + } + /// Consumes the `Box`, returning a wrapped raw pointer. /// /// The pointer will be properly aligned and non-null. @@ -1172,6 +1280,66 @@ impl Box { unsafe { addr_of_mut!(*&mut *Self::into_raw_with_allocator(b).0) } } + /// Consumes the `Box`, returning a wrapped `NonNull` pointer. + /// + /// The pointer will be properly aligned. + /// + /// After calling this function, the caller is responsible for the + /// memory previously managed by the `Box`. In particular, the + /// caller should properly destroy `T` and release the memory, taking + /// into account the [memory layout] used by `Box`. The easiest way to + /// do this is to convert the `NonNull` pointer back into a `Box` with the + /// [`Box::from_non_null`] function, allowing the `Box` destructor to + /// perform the cleanup. + /// + /// Note: this is an associated function, which means that you have + /// to call it as `Box::into_non_null(b)` instead of `b.into_non_null()`. + /// This is so that there is no conflict with a method on the inner type. + /// + /// # Examples + /// Converting the `NonNull` pointer back into a `Box` with [`Box::from_non_null`] + /// for automatic cleanup: + /// ``` + /// #![feature(box_vec_non_null)] + /// + /// let x = Box::new(String::from("Hello")); + /// let non_null = Box::into_non_null(x); + /// let x = unsafe { Box::from_non_null(non_null) }; + /// ``` + /// Manual cleanup by explicitly running the destructor and deallocating + /// the memory: + /// ``` + /// #![feature(box_vec_non_null)] + /// + /// use std::alloc::{dealloc, Layout}; + /// + /// let x = Box::new(String::from("Hello")); + /// let non_null = Box::into_non_null(x); + /// unsafe { + /// non_null.drop_in_place(); + /// dealloc(non_null.as_ptr().cast::(), Layout::new::()); + /// } + /// ``` + /// Note: This is equivalent to the following: + /// ``` + /// #![feature(box_vec_non_null)] + /// + /// let x = Box::new(String::from("Hello")); + /// let non_null = Box::into_non_null(x); + /// unsafe { + /// drop(Box::from_non_null(non_null)); + /// } + /// ``` + /// + /// [memory layout]: self#memory-layout + #[must_use = "losing the pointer will leak memory"] + #[unstable(feature = "box_vec_non_null", reason = "new API", issue = "130364")] + #[inline] + pub fn into_non_null(b: Self) -> NonNull { + // SAFETY: `Box` is guaranteed to be non-null. + unsafe { NonNull::new_unchecked(Self::into_raw(b)) } + } + /// Consumes the `Box`, returning a wrapped raw pointer and the allocator. /// /// The pointer will be properly aligned and non-null. @@ -1233,6 +1401,61 @@ impl Box { (ptr, alloc) } + /// Consumes the `Box`, returning a wrapped `NonNull` pointer and the allocator. + /// + /// The pointer will be properly aligned. + /// + /// After calling this function, the caller is responsible for the + /// memory previously managed by the `Box`. In particular, the + /// caller should properly destroy `T` and release the memory, taking + /// into account the [memory layout] used by `Box`. The easiest way to + /// do this is to convert the `NonNull` pointer back into a `Box` with the + /// [`Box::from_non_null_in`] function, allowing the `Box` destructor to + /// perform the cleanup. + /// + /// Note: this is an associated function, which means that you have + /// to call it as `Box::into_non_null_with_allocator(b)` instead of + /// `b.into_non_null_with_allocator()`. This is so that there is no + /// conflict with a method on the inner type. + /// + /// # Examples + /// Converting the `NonNull` pointer back into a `Box` with + /// [`Box::from_non_null_in`] for automatic cleanup: + /// ``` + /// #![feature(allocator_api, box_vec_non_null)] + /// + /// use std::alloc::System; + /// + /// let x = Box::new_in(String::from("Hello"), System); + /// let (non_null, alloc) = Box::into_non_null_with_allocator(x); + /// let x = unsafe { Box::from_non_null_in(non_null, alloc) }; + /// ``` + /// Manual cleanup by explicitly running the destructor and deallocating + /// the memory: + /// ``` + /// #![feature(allocator_api, box_vec_non_null)] + /// + /// use std::alloc::{Allocator, Layout, System}; + /// + /// let x = Box::new_in(String::from("Hello"), System); + /// let (non_null, alloc) = Box::into_non_null_with_allocator(x); + /// unsafe { + /// non_null.drop_in_place(); + /// alloc.deallocate(non_null.cast::(), Layout::new::()); + /// } + /// ``` + /// + /// [memory layout]: self#memory-layout + #[must_use = "losing the pointer will leak memory"] + #[unstable(feature = "allocator_api", issue = "32838")] + // #[unstable(feature = "box_vec_non_null", reason = "new API", issue = "130364")] + #[inline] + pub fn into_non_null_with_allocator(b: Self) -> (NonNull, A) { + let (ptr, alloc) = Box::into_raw_with_allocator(b); + // SAFETY: `Box` is guaranteed to be non-null. + unsafe { (NonNull::new_unchecked(ptr), alloc) } + } + #[unstable( feature = "ptr_internals", issue = "none", diff --git a/library/alloc/src/lib.rs b/library/alloc/src/lib.rs index 7aaa4e73df7..f98c0cca1db 100644 --- a/library/alloc/src/lib.rs +++ b/library/alloc/src/lib.rs @@ -114,7 +114,6 @@ #![feature(const_maybe_uninit_write)] #![feature(const_option)] #![feature(const_pin)] -#![feature(const_refs_to_cell)] #![feature(const_size_of_val)] #![feature(core_intrinsics)] #![feature(deprecated_suggestion)] @@ -164,13 +163,14 @@ // // Language features: // tidy-alphabetical-start +#![cfg_attr(bootstrap, feature(const_mut_refs))] +#![cfg_attr(bootstrap, feature(const_refs_to_cell))] #![cfg_attr(not(test), feature(coroutine_trait))] #![cfg_attr(test, feature(panic_update_hook))] #![cfg_attr(test, feature(test))] #![feature(allocator_internals)] #![feature(allow_internal_unstable)] #![feature(cfg_sanitize)] -#![feature(const_mut_refs)] #![feature(const_precise_live_drops)] #![feature(const_ptr_write)] #![feature(const_try)] diff --git a/library/alloc/src/string.rs b/library/alloc/src/string.rs index 05617669ed2..6daab5bc73a 100644 --- a/library/alloc/src/string.rs +++ b/library/alloc/src/string.rs @@ -660,6 +660,56 @@ impl String { Cow::Owned(res) } + /// Converts a [`Vec`] to a `String`, substituting invalid UTF-8 + /// sequences with replacement characters. + /// + /// See [`from_utf8_lossy`] for more details. + /// + /// [`from_utf8_lossy`]: String::from_utf8_lossy + /// + /// Note that this function does not guarantee reuse of the original `Vec` + /// allocation. + /// + /// # Examples + /// + /// Basic usage: + /// + /// ``` + /// #![feature(string_from_utf8_lossy_owned)] + /// // some bytes, in a vector + /// let sparkle_heart = vec![240, 159, 146, 150]; + /// + /// let sparkle_heart = String::from_utf8_lossy_owned(sparkle_heart); + /// + /// assert_eq!(String::from("💖"), sparkle_heart); + /// ``` + /// + /// Incorrect bytes: + /// + /// ``` + /// #![feature(string_from_utf8_lossy_owned)] + /// // some invalid bytes + /// let input: Vec = b"Hello \xF0\x90\x80World".into(); + /// let output = String::from_utf8_lossy_owned(input); + /// + /// assert_eq!(String::from("Hello �World"), output); + /// ``` + #[must_use] + #[cfg(not(no_global_oom_handling))] + #[unstable(feature = "string_from_utf8_lossy_owned", issue = "129436")] + pub fn from_utf8_lossy_owned(v: Vec) -> String { + if let Cow::Owned(string) = String::from_utf8_lossy(&v) { + string + } else { + // SAFETY: `String::from_utf8_lossy`'s contract ensures that if + // it returns a `Cow::Borrowed`, it is a valid UTF-8 string. + // Otherwise, it returns a new allocation of an owned `String`, with + // replacement characters for invalid sequences, which is returned + // above. + unsafe { String::from_utf8_unchecked(v) } + } + } + /// Decode a UTF-16–encoded vector `v` into a `String`, returning [`Err`] /// if `v` contains any invalid data. /// @@ -2010,6 +2060,30 @@ impl FromUtf8Error { &self.bytes[..] } + /// Converts the bytes into a `String` lossily, substituting invalid UTF-8 + /// sequences with replacement characters. + /// + /// See [`String::from_utf8_lossy`] for more details on replacement of + /// invalid sequences, and [`String::from_utf8_lossy_owned`] for the + /// `String` function which corresponds to this function. + /// + /// # Examples + /// + /// ``` + /// #![feature(string_from_utf8_lossy_owned)] + /// // some invalid bytes + /// let input: Vec = b"Hello \xF0\x90\x80World".into(); + /// let output = String::from_utf8(input).unwrap_or_else(|e| e.into_utf8_lossy()); + /// + /// assert_eq!(String::from("Hello �World"), output); + /// ``` + #[must_use] + #[cfg(not(no_global_oom_handling))] + #[unstable(feature = "string_from_utf8_lossy_owned", issue = "129436")] + pub fn into_utf8_lossy(self) -> String { + String::from_utf8_lossy_owned(self.bytes) + } + /// Returns the bytes that were attempted to convert to a `String`. /// /// This method is carefully constructed to avoid allocation. It will diff --git a/library/alloc/src/vec/in_place_collect.rs b/library/alloc/src/vec/in_place_collect.rs index cda63da0904..23dbc3b63f9 100644 --- a/library/alloc/src/vec/in_place_collect.rs +++ b/library/alloc/src/vec/in_place_collect.rs @@ -328,7 +328,7 @@ where mem::forget(dst_guard); - let vec = unsafe { Vec::from_nonnull(dst_buf, len, dst_cap) }; + let vec = unsafe { Vec::from_parts(dst_buf, len, dst_cap) }; vec } diff --git a/library/alloc/src/vec/mod.rs b/library/alloc/src/vec/mod.rs index ff084edba8d..2afb5dd0d1a 100644 --- a/library/alloc/src/vec/mod.rs +++ b/library/alloc/src/vec/mod.rs @@ -603,15 +603,116 @@ impl Vec { unsafe { Self::from_raw_parts_in(ptr, length, capacity, Global) } } - /// A convenience method for hoisting the non-null precondition out of [`Vec::from_raw_parts`]. + #[doc(alias = "from_non_null_parts")] + /// Creates a `Vec` directly from a `NonNull` pointer, a length, and a capacity. /// /// # Safety /// - /// See [`Vec::from_raw_parts`]. + /// This is highly unsafe, due to the number of invariants that aren't + /// checked: + /// + /// * `ptr` must have been allocated using the global allocator, such as via + /// the [`alloc::alloc`] function. + /// * `T` needs to have the same alignment as what `ptr` was allocated with. + /// (`T` having a less strict alignment is not sufficient, the alignment really + /// needs to be equal to satisfy the [`dealloc`] requirement that memory must be + /// allocated and deallocated with the same layout.) + /// * The size of `T` times the `capacity` (ie. the allocated size in bytes) needs + /// to be the same size as the pointer was allocated with. (Because similar to + /// alignment, [`dealloc`] must be called with the same layout `size`.) + /// * `length` needs to be less than or equal to `capacity`. + /// * The first `length` values must be properly initialized values of type `T`. + /// * `capacity` needs to be the capacity that the pointer was allocated with. + /// * The allocated size in bytes must be no larger than `isize::MAX`. + /// See the safety documentation of [`pointer::offset`]. + /// + /// These requirements are always upheld by any `ptr` that has been allocated + /// via `Vec`. Other allocation sources are allowed if the invariants are + /// upheld. + /// + /// Violating these may cause problems like corrupting the allocator's + /// internal data structures. For example it is normally **not** safe + /// to build a `Vec` from a pointer to a C `char` array with length + /// `size_t`, doing so is only safe if the array was initially allocated by + /// a `Vec` or `String`. + /// It's also not safe to build one from a `Vec` and its length, because + /// the allocator cares about the alignment, and these two types have different + /// alignments. The buffer was allocated with alignment 2 (for `u16`), but after + /// turning it into a `Vec` it'll be deallocated with alignment 1. To avoid + /// these issues, it is often preferable to do casting/transmuting using + /// [`NonNull::slice_from_raw_parts`] instead. + /// + /// The ownership of `ptr` is effectively transferred to the + /// `Vec` which may then deallocate, reallocate or change the + /// contents of memory pointed to by the pointer at will. Ensure + /// that nothing else uses the pointer after calling this + /// function. + /// + /// [`String`]: crate::string::String + /// [`alloc::alloc`]: crate::alloc::alloc + /// [`dealloc`]: crate::alloc::GlobalAlloc::dealloc + /// + /// # Examples + /// + /// ``` + /// #![feature(box_vec_non_null)] + /// + /// use std::ptr::NonNull; + /// use std::mem; + /// + /// let v = vec![1, 2, 3]; + /// + // FIXME Update this when vec_into_raw_parts is stabilized + /// // Prevent running `v`'s destructor so we are in complete control + /// // of the allocation. + /// let mut v = mem::ManuallyDrop::new(v); + /// + /// // Pull out the various important pieces of information about `v` + /// let p = unsafe { NonNull::new_unchecked(v.as_mut_ptr()) }; + /// let len = v.len(); + /// let cap = v.capacity(); + /// + /// unsafe { + /// // Overwrite memory with 4, 5, 6 + /// for i in 0..len { + /// p.add(i).write(4 + i); + /// } + /// + /// // Put everything back together into a Vec + /// let rebuilt = Vec::from_parts(p, len, cap); + /// assert_eq!(rebuilt, [4, 5, 6]); + /// } + /// ``` + /// + /// Using memory that was allocated elsewhere: + /// + /// ```rust + /// #![feature(box_vec_non_null)] + /// + /// use std::alloc::{alloc, Layout}; + /// use std::ptr::NonNull; + /// + /// fn main() { + /// let layout = Layout::array::(16).expect("overflow cannot happen"); + /// + /// let vec = unsafe { + /// let Some(mem) = NonNull::new(alloc(layout).cast::()) else { + /// return; + /// }; + /// + /// mem.write(1_000_000); + /// + /// Vec::from_parts(mem, 1, 16) + /// }; + /// + /// assert_eq!(vec, &[1_000_000]); + /// assert_eq!(vec.capacity(), 16); + /// } + /// ``` #[inline] - #[cfg(not(no_global_oom_handling))] // required by tests/run-make/alloc-no-oom-handling - pub(crate) unsafe fn from_nonnull(ptr: NonNull, length: usize, capacity: usize) -> Self { - unsafe { Self::from_nonnull_in(ptr, length, capacity, Global) } + #[unstable(feature = "box_vec_non_null", reason = "new API", issue = "130364")] + pub unsafe fn from_parts(ptr: NonNull, length: usize, capacity: usize) -> Self { + unsafe { Self::from_parts_in(ptr, length, capacity, Global) } } } @@ -830,19 +931,119 @@ impl Vec { unsafe { Vec { buf: RawVec::from_raw_parts_in(ptr, capacity, alloc), len: length } } } - /// A convenience method for hoisting the non-null precondition out of [`Vec::from_raw_parts_in`]. + #[doc(alias = "from_non_null_parts_in")] + /// Creates a `Vec` directly from a `NonNull` pointer, a length, a capacity, + /// and an allocator. /// /// # Safety /// - /// See [`Vec::from_raw_parts_in`]. + /// This is highly unsafe, due to the number of invariants that aren't + /// checked: + /// + /// * `ptr` must be [*currently allocated*] via the given allocator `alloc`. + /// * `T` needs to have the same alignment as what `ptr` was allocated with. + /// (`T` having a less strict alignment is not sufficient, the alignment really + /// needs to be equal to satisfy the [`dealloc`] requirement that memory must be + /// allocated and deallocated with the same layout.) + /// * The size of `T` times the `capacity` (ie. the allocated size in bytes) needs + /// to be the same size as the pointer was allocated with. (Because similar to + /// alignment, [`dealloc`] must be called with the same layout `size`.) + /// * `length` needs to be less than or equal to `capacity`. + /// * The first `length` values must be properly initialized values of type `T`. + /// * `capacity` needs to [*fit*] the layout size that the pointer was allocated with. + /// * The allocated size in bytes must be no larger than `isize::MAX`. + /// See the safety documentation of [`pointer::offset`]. + /// + /// These requirements are always upheld by any `ptr` that has been allocated + /// via `Vec`. Other allocation sources are allowed if the invariants are + /// upheld. + /// + /// Violating these may cause problems like corrupting the allocator's + /// internal data structures. For example it is **not** safe + /// to build a `Vec` from a pointer to a C `char` array with length `size_t`. + /// It's also not safe to build one from a `Vec` and its length, because + /// the allocator cares about the alignment, and these two types have different + /// alignments. The buffer was allocated with alignment 2 (for `u16`), but after + /// turning it into a `Vec` it'll be deallocated with alignment 1. + /// + /// The ownership of `ptr` is effectively transferred to the + /// `Vec` which may then deallocate, reallocate or change the + /// contents of memory pointed to by the pointer at will. Ensure + /// that nothing else uses the pointer after calling this + /// function. + /// + /// [`String`]: crate::string::String + /// [`dealloc`]: crate::alloc::GlobalAlloc::dealloc + /// [*currently allocated*]: crate::alloc::Allocator#currently-allocated-memory + /// [*fit*]: crate::alloc::Allocator#memory-fitting + /// + /// # Examples + /// + /// ``` + /// #![feature(allocator_api, box_vec_non_null)] + /// + /// use std::alloc::System; + /// + /// use std::ptr::NonNull; + /// use std::mem; + /// + /// let mut v = Vec::with_capacity_in(3, System); + /// v.push(1); + /// v.push(2); + /// v.push(3); + /// + // FIXME Update this when vec_into_raw_parts is stabilized + /// // Prevent running `v`'s destructor so we are in complete control + /// // of the allocation. + /// let mut v = mem::ManuallyDrop::new(v); + /// + /// // Pull out the various important pieces of information about `v` + /// let p = unsafe { NonNull::new_unchecked(v.as_mut_ptr()) }; + /// let len = v.len(); + /// let cap = v.capacity(); + /// let alloc = v.allocator(); + /// + /// unsafe { + /// // Overwrite memory with 4, 5, 6 + /// for i in 0..len { + /// p.add(i).write(4 + i); + /// } + /// + /// // Put everything back together into a Vec + /// let rebuilt = Vec::from_parts_in(p, len, cap, alloc.clone()); + /// assert_eq!(rebuilt, [4, 5, 6]); + /// } + /// ``` + /// + /// Using memory that was allocated elsewhere: + /// + /// ```rust + /// #![feature(allocator_api, box_vec_non_null)] + /// + /// use std::alloc::{AllocError, Allocator, Global, Layout}; + /// + /// fn main() { + /// let layout = Layout::array::(16).expect("overflow cannot happen"); + /// + /// let vec = unsafe { + /// let mem = match Global.allocate(layout) { + /// Ok(mem) => mem.cast::(), + /// Err(AllocError) => return, + /// }; + /// + /// mem.write(1_000_000); + /// + /// Vec::from_parts_in(mem, 1, 16, Global) + /// }; + /// + /// assert_eq!(vec, &[1_000_000]); + /// assert_eq!(vec.capacity(), 16); + /// } + /// ``` #[inline] - #[cfg(not(no_global_oom_handling))] // required by tests/run-make/alloc-no-oom-handling - pub(crate) unsafe fn from_nonnull_in( - ptr: NonNull, - length: usize, - capacity: usize, - alloc: A, - ) -> Self { + #[unstable(feature = "allocator_api", reason = "new API", issue = "32838")] + // #[unstable(feature = "box_vec_non_null", issue = "130364")] + pub unsafe fn from_parts_in(ptr: NonNull, length: usize, capacity: usize, alloc: A) -> Self { unsafe { Vec { buf: RawVec::from_nonnull_in(ptr, capacity, alloc), len: length } } } @@ -885,6 +1086,49 @@ impl Vec { (me.as_mut_ptr(), me.len(), me.capacity()) } + #[doc(alias = "into_non_null_parts")] + /// Decomposes a `Vec` into its raw components: `(NonNull pointer, length, capacity)`. + /// + /// Returns the `NonNull` pointer to the underlying data, the length of + /// the vector (in elements), and the allocated capacity of the + /// data (in elements). These are the same arguments in the same + /// order as the arguments to [`from_parts`]. + /// + /// After calling this function, the caller is responsible for the + /// memory previously managed by the `Vec`. The only way to do + /// this is to convert the `NonNull` pointer, length, and capacity back + /// into a `Vec` with the [`from_parts`] function, allowing + /// the destructor to perform the cleanup. + /// + /// [`from_parts`]: Vec::from_parts + /// + /// # Examples + /// + /// ``` + /// #![feature(vec_into_raw_parts, box_vec_non_null)] + /// + /// let v: Vec = vec![-1, 0, 1]; + /// + /// let (ptr, len, cap) = v.into_parts(); + /// + /// let rebuilt = unsafe { + /// // We can now make changes to the components, such as + /// // transmuting the raw pointer to a compatible type. + /// let ptr = ptr.cast::(); + /// + /// Vec::from_parts(ptr, len, cap) + /// }; + /// assert_eq!(rebuilt, [4294967295, 0, 1]); + /// ``` + #[must_use = "losing the pointer will leak memory"] + #[unstable(feature = "box_vec_non_null", reason = "new API", issue = "130364")] + // #[unstable(feature = "vec_into_raw_parts", reason = "new API", issue = "65816")] + pub fn into_parts(self) -> (NonNull, usize, usize) { + let (ptr, len, capacity) = self.into_raw_parts(); + // SAFETY: A `Vec` always has a non-null pointer. + (unsafe { NonNull::new_unchecked(ptr) }, len, capacity) + } + /// Decomposes a `Vec` into its raw components: `(pointer, length, capacity, allocator)`. /// /// Returns the raw pointer to the underlying data, the length of the vector (in elements), @@ -934,6 +1178,54 @@ impl Vec { (ptr, len, capacity, alloc) } + #[doc(alias = "into_non_null_parts_with_alloc")] + /// Decomposes a `Vec` into its raw components: `(NonNull pointer, length, capacity, allocator)`. + /// + /// Returns the `NonNull` pointer to the underlying data, the length of the vector (in elements), + /// the allocated capacity of the data (in elements), and the allocator. These are the same + /// arguments in the same order as the arguments to [`from_parts_in`]. + /// + /// After calling this function, the caller is responsible for the + /// memory previously managed by the `Vec`. The only way to do + /// this is to convert the `NonNull` pointer, length, and capacity back + /// into a `Vec` with the [`from_parts_in`] function, allowing + /// the destructor to perform the cleanup. + /// + /// [`from_parts_in`]: Vec::from_parts_in + /// + /// # Examples + /// + /// ``` + /// #![feature(allocator_api, vec_into_raw_parts, box_vec_non_null)] + /// + /// use std::alloc::System; + /// + /// let mut v: Vec = Vec::new_in(System); + /// v.push(-1); + /// v.push(0); + /// v.push(1); + /// + /// let (ptr, len, cap, alloc) = v.into_parts_with_alloc(); + /// + /// let rebuilt = unsafe { + /// // We can now make changes to the components, such as + /// // transmuting the raw pointer to a compatible type. + /// let ptr = ptr.cast::(); + /// + /// Vec::from_parts_in(ptr, len, cap, alloc) + /// }; + /// assert_eq!(rebuilt, [4294967295, 0, 1]); + /// ``` + #[must_use = "losing the pointer will leak memory"] + #[unstable(feature = "allocator_api", issue = "32838")] + // #[unstable(feature = "box_vec_non_null", reason = "new API", issue = "130364")] + // #[unstable(feature = "vec_into_raw_parts", reason = "new API", issue = "65816")] + pub fn into_parts_with_alloc(self) -> (NonNull, usize, usize, A) { + let (ptr, len, capacity, alloc) = self.into_raw_parts_with_alloc(); + // SAFETY: A `Vec` always has a non-null pointer. + (unsafe { NonNull::new_unchecked(ptr) }, len, capacity, alloc) + } + /// Returns the total number of elements the vector can hold without /// reallocating. /// diff --git a/library/alloc/src/vec/spec_from_iter.rs b/library/alloc/src/vec/spec_from_iter.rs index 6646ae7bccb..e1f0b639bdf 100644 --- a/library/alloc/src/vec/spec_from_iter.rs +++ b/library/alloc/src/vec/spec_from_iter.rs @@ -51,7 +51,7 @@ impl SpecFromIter> for Vec { if has_advanced { ptr::copy(it.ptr.as_ptr(), it.buf.as_ptr(), it.len()); } - return Vec::from_nonnull(it.buf, it.len(), it.cap); + return Vec::from_parts(it.buf, it.len(), it.cap); } } diff --git a/library/alloc/tests/lib.rs b/library/alloc/tests/lib.rs index c5c6a122cfe..ffc9a233b66 100644 --- a/library/alloc/tests/lib.rs +++ b/library/alloc/tests/lib.rs @@ -6,7 +6,7 @@ #![feature(cow_is_borrowed)] #![feature(const_cow_is_borrowed)] #![feature(const_heap)] -#![feature(const_mut_refs)] +#![cfg_attr(bootstrap, feature(const_mut_refs))] #![feature(const_slice_from_raw_parts_mut)] #![feature(const_ptr_write)] #![feature(const_try)] diff --git a/library/core/src/intrinsics/simd.rs b/library/core/src/intrinsics/simd.rs index 59828198099..5ddca9c4dce 100644 --- a/library/core/src/intrinsics/simd.rs +++ b/library/core/src/intrinsics/simd.rs @@ -232,7 +232,7 @@ extern "rust-intrinsic" { /// /// `T` must be a vector. /// - /// `U` must be a **const** array or vector of `u32`s. This means it must either refer to a named + /// `U` must be a **const** vector of `u32`s. This means it must either refer to a named /// const or be given as an inline const expression (`const { ... }`). /// /// `V` must be a vector with the same element type as `T` and the same length as `U`. diff --git a/library/core/src/iter/adapters/peekable.rs b/library/core/src/iter/adapters/peekable.rs index a11b73cbe8e..cc12cd9c356 100644 --- a/library/core/src/iter/adapters/peekable.rs +++ b/library/core/src/iter/adapters/peekable.rs @@ -269,7 +269,7 @@ impl Peekable { /// let mut iter = (0..5).peekable(); /// // The first item of the iterator is 0; consume it. /// assert_eq!(iter.next_if(|&x| x == 0), Some(0)); - /// // The next item returned is now 1, so `consume` will return `false`. + /// // The next item returned is now 1, so `next_if` will return `None`. /// assert_eq!(iter.next_if(|&x| x == 0), None); /// // `next_if` saves the value of the next item if it was not equal to `expected`. /// assert_eq!(iter.next(), Some(1)); @@ -304,7 +304,7 @@ impl Peekable { /// let mut iter = (0..5).peekable(); /// // The first item of the iterator is 0; consume it. /// assert_eq!(iter.next_if_eq(&0), Some(0)); - /// // The next item returned is now 1, so `consume` will return `false`. + /// // The next item returned is now 1, so `next_if` will return `None`. /// assert_eq!(iter.next_if_eq(&0), None); /// // `next_if_eq` saves the value of the next item if it was not equal to `expected`. /// assert_eq!(iter.next(), Some(1)); diff --git a/library/core/src/lib.rs b/library/core/src/lib.rs index 5b5d5d1a961..058dcf34532 100644 --- a/library/core/src/lib.rs +++ b/library/core/src/lib.rs @@ -191,6 +191,8 @@ // // Language features: // tidy-alphabetical-start +#![cfg_attr(bootstrap, feature(const_mut_refs))] +#![cfg_attr(bootstrap, feature(const_refs_to_cell))] #![feature(abi_unadjusted)] #![feature(adt_const_params)] #![feature(allow_internal_unsafe)] @@ -201,9 +203,7 @@ #![feature(cfg_target_has_atomic_equal_alignment)] #![feature(cfg_ub_checks)] #![feature(const_for)] -#![feature(const_mut_refs)] #![feature(const_precise_live_drops)] -#![feature(const_refs_to_cell)] #![feature(decl_macro)] #![feature(deprecated_suggestion)] #![feature(doc_cfg)] diff --git a/library/core/src/option.rs b/library/core/src/option.rs index da2cb3a2b78..265f056dc87 100644 --- a/library/core/src/option.rs +++ b/library/core/src/option.rs @@ -1067,7 +1067,7 @@ impl Option { #[inline] #[track_caller] #[stable(feature = "option_result_unwrap_unchecked", since = "1.58.0")] - #[rustc_const_unstable(feature = "const_option_ext", issue = "91930")] + #[rustc_const_unstable(feature = "const_option", issue = "67441")] pub const unsafe fn unwrap_unchecked(self) -> T { match self { Some(val) => val, diff --git a/library/core/src/ptr/mut_ptr.rs b/library/core/src/ptr/mut_ptr.rs index ddb9195d2e7..5fa3b9bf61f 100644 --- a/library/core/src/ptr/mut_ptr.rs +++ b/library/core/src/ptr/mut_ptr.rs @@ -1569,7 +1569,7 @@ impl *mut T { /// /// ``` /// #![feature(const_pointer_is_aligned)] - /// #![feature(const_mut_refs)] + /// # #![cfg_attr(bootstrap, feature(const_mut_refs))] /// /// // On some platforms, the alignment of primitives is less than their size. /// #[repr(align(4))] @@ -1695,7 +1695,7 @@ impl *mut T { /// ``` /// #![feature(pointer_is_aligned_to)] /// #![feature(const_pointer_is_aligned)] - /// #![feature(const_mut_refs)] + /// # #![cfg_attr(bootstrap, feature(const_mut_refs))] /// /// // On some platforms, the alignment of i32 is less than 4. /// #[repr(align(4))] diff --git a/library/core/src/slice/mod.rs b/library/core/src/slice/mod.rs index 8b661d1202c..b1948ce69c7 100644 --- a/library/core/src/slice/mod.rs +++ b/library/core/src/slice/mod.rs @@ -846,7 +846,7 @@ impl [T] { /// [`as_mut_ptr`]: slice::as_mut_ptr #[stable(feature = "slice_ptr_range", since = "1.48.0")] #[rustc_const_stable(feature = "const_ptr_offset", since = "1.61.0")] - #[rustc_allow_const_fn_unstable(const_mut_refs)] + #[cfg_attr(bootstrap, rustc_allow_const_fn_unstable(const_mut_refs, const_refs_to_cell))] #[inline] #[must_use] pub const fn as_mut_ptr_range(&mut self) -> Range<*mut T> { diff --git a/library/core/tests/lib.rs b/library/core/tests/lib.rs index dbceb8abafc..948ea9bc098 100644 --- a/library/core/tests/lib.rs +++ b/library/core/tests/lib.rs @@ -1,4 +1,5 @@ // tidy-alphabetical-start +#![cfg_attr(bootstrap, feature(const_mut_refs))] #![cfg_attr(target_has_atomic = "128", feature(integer_atomics))] #![cfg_attr(test, feature(cfg_match))] #![feature(alloc_layout_extra)] @@ -26,7 +27,6 @@ #![feature(const_ipv6)] #![feature(const_likely)] #![feature(const_maybe_uninit_as_mut_ptr)] -#![feature(const_mut_refs)] #![feature(const_nonnull_new)] #![feature(const_option)] #![feature(const_option_ext)] diff --git a/library/panic_unwind/src/gcc.rs b/library/panic_unwind/src/gcc.rs index 589d3c1b4d2..d8c1dcaaefe 100644 --- a/library/panic_unwind/src/gcc.rs +++ b/library/panic_unwind/src/gcc.rs @@ -61,7 +61,7 @@ struct Exception { pub unsafe fn panic(data: Box) -> u32 { let exception = Box::new(Exception { _uwe: uw::_Unwind_Exception { - exception_class: rust_exception_class(), + exception_class: RUST_EXCEPTION_CLASS, exception_cleanup: Some(exception_cleanup), private: [core::ptr::null(); uw::unwinder_private_data_size], }, @@ -84,7 +84,7 @@ pub unsafe fn panic(data: Box) -> u32 { pub unsafe fn cleanup(ptr: *mut u8) -> Box { let exception = ptr as *mut uw::_Unwind_Exception; - if (*exception).exception_class != rust_exception_class() { + if (*exception).exception_class != RUST_EXCEPTION_CLASS { uw::_Unwind_DeleteException(exception); super::__rust_foreign_exception(); } @@ -107,7 +107,4 @@ pub unsafe fn cleanup(ptr: *mut u8) -> Box { // Rust's exception class identifier. This is used by personality routines to // determine whether the exception was thrown by their own runtime. -fn rust_exception_class() -> uw::_Unwind_Exception_Class { - // M O Z \0 R U S T -- vendor, language - 0x4d4f5a_00_52555354 -} +const RUST_EXCEPTION_CLASS: uw::_Unwind_Exception_Class = u64::from_be_bytes(*b"MOZ\0RUST"); diff --git a/library/portable-simd/crates/core_simd/src/swizzle.rs b/library/portable-simd/crates/core_simd/src/swizzle.rs index 2f4f777b20e..d62642fb906 100644 --- a/library/portable-simd/crates/core_simd/src/swizzle.rs +++ b/library/portable-simd/crates/core_simd/src/swizzle.rs @@ -85,7 +85,7 @@ pub trait Swizzle { LaneCount: SupportedLaneCount, LaneCount: SupportedLaneCount, { - // Safety: `vector` is a vector, and the index is a const array of u32. + // Safety: `vector` is a vector, and the index is a const vector of u32. unsafe { core::intrinsics::simd::simd_shuffle( vector, @@ -103,7 +103,11 @@ pub trait Swizzle { output[i] = index as u32; i += 1; } - output + + // The index list needs to be returned as a vector. + #[repr(simd)] + struct SimdShuffleIdx([u32; LEN]); + SimdShuffleIdx(output) }, ) } @@ -121,7 +125,7 @@ pub trait Swizzle { LaneCount: SupportedLaneCount, LaneCount: SupportedLaneCount, { - // Safety: `first` and `second` are vectors, and the index is a const array of u32. + // Safety: `first` and `second` are vectors, and the index is a const vector of u32. unsafe { core::intrinsics::simd::simd_shuffle( first, @@ -139,7 +143,11 @@ pub trait Swizzle { output[i] = index as u32; i += 1; } - output + + // The index list needs to be returned as a vector. + #[repr(simd)] + struct SimdShuffleIdx([u32; LEN]); + SimdShuffleIdx(output) }, ) } diff --git a/library/std/src/collections/hash/map.rs b/library/std/src/collections/hash/map.rs index 822fa5791e3..7d21d37f40d 100644 --- a/library/std/src/collections/hash/map.rs +++ b/library/std/src/collections/hash/map.rs @@ -2754,7 +2754,6 @@ impl<'a, K, V> Entry<'a, K, V> { /// # Examples /// /// ``` - /// #![feature(entry_insert)] /// use std::collections::HashMap; /// /// let mut map: HashMap<&str, String> = HashMap::new(); @@ -2763,7 +2762,7 @@ impl<'a, K, V> Entry<'a, K, V> { /// assert_eq!(entry.key(), &"poneyland"); /// ``` #[inline] - #[unstable(feature = "entry_insert", issue = "65225")] + #[stable(feature = "entry_insert", since = "CURRENT_RUSTC_VERSION")] pub fn insert_entry(self, value: V) -> OccupiedEntry<'a, K, V> { match self { Occupied(mut entry) => { @@ -3097,7 +3096,6 @@ impl<'a, K: 'a, V: 'a> VacantEntry<'a, K, V> { /// # Examples /// /// ``` - /// #![feature(entry_insert)] /// use std::collections::HashMap; /// use std::collections::hash_map::Entry; /// @@ -3109,7 +3107,7 @@ impl<'a, K: 'a, V: 'a> VacantEntry<'a, K, V> { /// assert_eq!(map["poneyland"], 37); /// ``` #[inline] - #[unstable(feature = "entry_insert", issue = "65225")] + #[stable(feature = "entry_insert", since = "CURRENT_RUSTC_VERSION")] pub fn insert_entry(self, value: V) -> OccupiedEntry<'a, K, V> { let base = self.base.insert_entry(value); OccupiedEntry { base } diff --git a/library/std/src/io/buffered/bufreader.rs b/library/std/src/io/buffered/bufreader.rs index 035afbb8368..7dcca2707ba 100644 --- a/library/std/src/io/buffered/bufreader.rs +++ b/library/std/src/io/buffered/bufreader.rs @@ -99,7 +99,10 @@ impl BufReader { impl BufReader { /// Attempt to look ahead `n` bytes. /// - /// `n` must be less than `capacity`. + /// `n` must be less than or equal to `capacity`. + /// + /// the returned slice may be less than `n` bytes long if + /// end of file is reached. /// /// ## Examples /// @@ -117,6 +120,7 @@ impl BufReader { /// let mut s = String::new(); /// rdr.read_to_string(&mut s).unwrap(); /// assert_eq!(&s, "hello"); + /// assert_eq!(rdr.peek(1).unwrap().len(), 0); /// ``` #[unstable(feature = "bufreader_peek", issue = "128405")] pub fn peek(&mut self, n: usize) -> io::Result<&[u8]> { @@ -125,7 +129,11 @@ impl BufReader { if self.buf.pos() > 0 { self.buf.backshift(); } - self.buf.read_more(&mut self.inner)?; + let new = self.buf.read_more(&mut self.inner)?; + if new == 0 { + // end of file, no more bytes to read + return Ok(&self.buf.buffer()[..]); + } debug_assert_eq!(self.buf.pos(), 0); } Ok(&self.buf.buffer()[..n]) diff --git a/library/std/src/io/buffered/bufreader/buffer.rs b/library/std/src/io/buffered/bufreader/buffer.rs index ccd67fafb45..1bf84d8bef3 100644 --- a/library/std/src/io/buffered/bufreader/buffer.rs +++ b/library/std/src/io/buffered/bufreader/buffer.rs @@ -98,7 +98,7 @@ impl Buffer { } /// Read more bytes into the buffer without discarding any of its contents - pub fn read_more(&mut self, mut reader: impl Read) -> io::Result<()> { + pub fn read_more(&mut self, mut reader: impl Read) -> io::Result { let mut buf = BorrowedBuf::from(&mut self.buf[self.pos..]); let old_init = self.initialized - self.pos; unsafe { @@ -107,7 +107,7 @@ impl Buffer { reader.read_buf(buf.unfilled())?; self.filled += buf.len(); self.initialized += buf.init_len() - old_init; - Ok(()) + Ok(buf.len()) } /// Remove bytes that have already been read from the buffer. diff --git a/library/std/src/lib.rs b/library/std/src/lib.rs index 60969af3e85..bc5369ddc3d 100644 --- a/library/std/src/lib.rs +++ b/library/std/src/lib.rs @@ -272,6 +272,7 @@ // // Language features: // tidy-alphabetical-start +#![cfg_attr(bootstrap, feature(const_mut_refs))] #![feature(alloc_error_handler)] #![feature(allocator_internals)] #![feature(allow_internal_unsafe)] @@ -281,7 +282,6 @@ #![feature(cfg_target_thread_local)] #![feature(cfi_encoding)] #![feature(concat_idents)] -#![feature(const_mut_refs)] #![feature(decl_macro)] #![feature(deprecated_suggestion)] #![feature(doc_cfg)] diff --git a/src/bootstrap/defaults/config.library.toml b/src/bootstrap/defaults/config.library.toml index 087544397f5..5447565a4b0 100644 --- a/src/bootstrap/defaults/config.library.toml +++ b/src/bootstrap/defaults/config.library.toml @@ -13,4 +13,5 @@ lto = "off" [llvm] # Will download LLVM from CI if available on your platform. -download-ci-llvm = "if-unchanged" +# If you intend to modify `src/llvm-project`, use `"if-unchanged"` or `false` instead. +download-ci-llvm = true diff --git a/src/bootstrap/defaults/config.tools.toml b/src/bootstrap/defaults/config.tools.toml index 75ad37ce335..efb56996bcd 100644 --- a/src/bootstrap/defaults/config.tools.toml +++ b/src/bootstrap/defaults/config.tools.toml @@ -17,4 +17,5 @@ compiler-docs = true [llvm] # Will download LLVM from CI if available on your platform. -download-ci-llvm = "if-unchanged" +# If you intend to modify `src/llvm-project`, use `"if-unchanged"` or `false` instead. +download-ci-llvm = true diff --git a/src/bootstrap/src/core/build_steps/compile.rs b/src/bootstrap/src/core/build_steps/compile.rs index bb07d478f71..e1ab1e7599e 100644 --- a/src/bootstrap/src/core/build_steps/compile.rs +++ b/src/bootstrap/src/core/build_steps/compile.rs @@ -1760,6 +1760,49 @@ impl Step for Assemble { return target_compiler; } + // We prepend this bin directory to the user PATH when linking Rust binaries. To + // avoid shadowing the system LLD we rename the LLD we provide to `rust-lld`. + let libdir = builder.sysroot_libdir(target_compiler, target_compiler.host); + let libdir_bin = libdir.parent().unwrap().join("bin"); + t!(fs::create_dir_all(&libdir_bin)); + + if builder.config.llvm_enabled(target_compiler.host) { + let llvm::LlvmResult { llvm_config, .. } = + builder.ensure(llvm::Llvm { target: target_compiler.host }); + if !builder.config.dry_run() && builder.config.llvm_tools_enabled { + let llvm_bin_dir = + command(llvm_config).arg("--bindir").run_capture_stdout(builder).stdout(); + let llvm_bin_dir = Path::new(llvm_bin_dir.trim()); + + // Since we've already built the LLVM tools, install them to the sysroot. + // This is the equivalent of installing the `llvm-tools-preview` component via + // rustup, and lets developers use a locally built toolchain to + // build projects that expect llvm tools to be present in the sysroot + // (e.g. the `bootimage` crate). + for tool in LLVM_TOOLS { + let tool_exe = exe(tool, target_compiler.host); + let src_path = llvm_bin_dir.join(&tool_exe); + // When using `download-ci-llvm`, some of the tools + // may not exist, so skip trying to copy them. + if src_path.exists() { + builder.copy_link(&src_path, &libdir_bin.join(&tool_exe)); + } + } + } + } + + let maybe_install_llvm_bitcode_linker = |compiler| { + if builder.config.llvm_bitcode_linker_enabled { + let src_path = builder.ensure(crate::core::build_steps::tool::LlvmBitcodeLinker { + compiler, + target: target_compiler.host, + extra_features: vec![], + }); + let tool_exe = exe("llvm-bitcode-linker", target_compiler.host); + builder.copy_link(&src_path, &libdir_bin.join(tool_exe)); + } + }; + // If we're downloading a compiler from CI, we can use the same compiler for all stages other than 0. if builder.download_rustc() { builder.ensure(Std::new(target_compiler, target_compiler.host)); @@ -1772,6 +1815,9 @@ impl Step for Assemble { if target_compiler.stage == builder.top_stage { builder.info(&format!("Creating a sysroot for stage{stage} compiler (use `rustup toolchain link 'name' build/host/stage{stage}`)", stage=target_compiler.stage)); } + + maybe_install_llvm_bitcode_linker(target_compiler); + return target_compiler; } @@ -1880,11 +1926,6 @@ impl Step for Assemble { copy_codegen_backends_to_sysroot(builder, build_compiler, target_compiler); - // We prepend this bin directory to the user PATH when linking Rust binaries. To - // avoid shadowing the system LLD we rename the LLD we provide to `rust-lld`. - let libdir = builder.sysroot_libdir(target_compiler, target_compiler.host); - let libdir_bin = libdir.parent().unwrap().join("bin"); - t!(fs::create_dir_all(&libdir_bin)); if let Some(lld_install) = lld_install { let src_exe = exe("lld", target_compiler.host); let dst_exe = exe("rust-lld", target_compiler.host); @@ -1920,40 +1961,7 @@ impl Step for Assemble { ); } - if builder.config.llvm_enabled(target_compiler.host) { - let llvm::LlvmResult { llvm_config, .. } = - builder.ensure(llvm::Llvm { target: target_compiler.host }); - if !builder.config.dry_run() && builder.config.llvm_tools_enabled { - let llvm_bin_dir = - command(llvm_config).arg("--bindir").run_capture_stdout(builder).stdout(); - let llvm_bin_dir = Path::new(llvm_bin_dir.trim()); - - // Since we've already built the LLVM tools, install them to the sysroot. - // This is the equivalent of installing the `llvm-tools-preview` component via - // rustup, and lets developers use a locally built toolchain to - // build projects that expect llvm tools to be present in the sysroot - // (e.g. the `bootimage` crate). - for tool in LLVM_TOOLS { - let tool_exe = exe(tool, target_compiler.host); - let src_path = llvm_bin_dir.join(&tool_exe); - // When using `download-ci-llvm`, some of the tools - // may not exist, so skip trying to copy them. - if src_path.exists() { - builder.copy_link(&src_path, &libdir_bin.join(&tool_exe)); - } - } - } - } - - if builder.config.llvm_bitcode_linker_enabled { - let src_path = builder.ensure(crate::core::build_steps::tool::LlvmBitcodeLinker { - compiler: build_compiler, - target: target_compiler.host, - extra_features: vec![], - }); - let tool_exe = exe("llvm-bitcode-linker", target_compiler.host); - builder.copy_link(&src_path, &libdir_bin.join(tool_exe)); - } + maybe_install_llvm_bitcode_linker(build_compiler); // Ensure that `libLLVM.so` ends up in the newly build compiler directory, // so that it can be found when the newly built `rustc` is run. diff --git a/src/bootstrap/src/core/build_steps/dist.rs b/src/bootstrap/src/core/build_steps/dist.rs index b0bd18792be..294a56b3e97 100644 --- a/src/bootstrap/src/core/build_steps/dist.rs +++ b/src/bootstrap/src/core/build_steps/dist.rs @@ -1011,11 +1011,7 @@ impl Step for PlainSourceTarball { write_git_info(builder.rust_info().info(), plain_dst_src); write_git_info(builder.cargo_info.info(), &plain_dst_src.join("./src/tools/cargo")); - // If we're building from git or tarball sources, we need to vendor - // a complete distribution. - if builder.rust_info().is_managed_git_subrepository() - || builder.rust_info().is_from_tarball() - { + if builder.config.dist_vendor { builder.require_and_update_all_submodules(); // Vendor all Cargo dependencies diff --git a/src/bootstrap/src/core/config/config.rs b/src/bootstrap/src/core/config/config.rs index 9271e809853..555a6a7f8bd 100644 --- a/src/bootstrap/src/core/config/config.rs +++ b/src/bootstrap/src/core/config/config.rs @@ -308,6 +308,7 @@ pub struct Config { pub dist_compression_formats: Option>, pub dist_compression_profile: String, pub dist_include_mingw_linker: bool, + pub dist_vendor: bool, // libstd features pub backtrace: bool, // support for RUST_BACKTRACE @@ -933,6 +934,7 @@ define_config! { compression_formats: Option> = "compression-formats", compression_profile: Option = "compression-profile", include_mingw_linker: Option = "include-mingw-linker", + vendor: Option = "vendor", } } @@ -2028,13 +2030,19 @@ impl Config { compression_formats, compression_profile, include_mingw_linker, + vendor, } = dist; config.dist_sign_folder = sign_folder.map(PathBuf::from); config.dist_upload_addr = upload_addr; config.dist_compression_formats = compression_formats; set(&mut config.dist_compression_profile, compression_profile); set(&mut config.rust_dist_src, src_tarball); - set(&mut config.dist_include_mingw_linker, include_mingw_linker) + set(&mut config.dist_include_mingw_linker, include_mingw_linker); + config.dist_vendor = vendor.unwrap_or_else(|| { + // If we're building from git or tarball sources, enable it by default. + config.rust_info.is_managed_git_subrepository() + || config.rust_info.is_from_tarball() + }); } if let Some(r) = rustfmt { @@ -2739,6 +2747,8 @@ impl Config { return false; } + // Fetching the LLVM submodule is unnecessary for self-tests. + #[cfg(not(feature = "bootstrap-self-test"))] self.update_submodule("src/llvm-project"); // Check for untracked changes in `src/llvm-project`. diff --git a/src/bootstrap/src/lib.rs b/src/bootstrap/src/lib.rs index b339905cce1..df2acd8b76b 100644 --- a/src/bootstrap/src/lib.rs +++ b/src/bootstrap/src/lib.rs @@ -349,10 +349,14 @@ impl Build { }; let Some(initial_libdir) = find_initial_libdir() else { panic!( - "couldn't determine `initial_libdir` \ - from target dir {initial_target_dir:?} \ - and sysroot {initial_sysroot:?}" - ) + "couldn't determine `initial_libdir`: +- config.initial_rustc: {rustc:?} +- initial_target_libdir_str: {initial_target_libdir_str:?} +- initial_target_dir: {initial_target_dir:?} +- initial_sysroot: {initial_sysroot:?} +", + rustc = config.initial_rustc, + ); }; let version = std::fs::read_to_string(src.join("src").join("version")) diff --git a/src/bootstrap/src/utils/change_tracker.rs b/src/bootstrap/src/utils/change_tracker.rs index 99bcc6e0787..379cd568647 100644 --- a/src/bootstrap/src/utils/change_tracker.rs +++ b/src/bootstrap/src/utils/change_tracker.rs @@ -255,4 +255,14 @@ pub const CONFIG_CHANGE_HISTORY: &[ChangeInfo] = &[ severity: ChangeSeverity::Warning, summary: "`download-ci-llvm = true` now checks if CI llvm is available and has become the default for the compiler profile", }, + ChangeInfo { + change_id: 130202, + severity: ChangeSeverity::Info, + summary: "'tools' and 'library' profiles switched `download-ci-llvm` option from `if-unchanged` to `true`.", + }, + ChangeInfo { + change_id: 130110, + severity: ChangeSeverity::Info, + summary: "New option `dist.vendor` added to control whether bootstrap should vendor dependencies for dist tarball.", + }, ]; 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 new file mode 100644 index 00000000000..44328b078ad --- /dev/null +++ b/src/ci/docker/host-x86_64/x86_64-gnu-llvm-19/Dockerfile @@ -0,0 +1,62 @@ +FROM ubuntu:24.10 + +ARG DEBIAN_FRONTEND=noninteractive + +RUN apt-get update && apt-get install -y --no-install-recommends \ + g++ \ + gcc-multilib \ + make \ + ninja-build \ + file \ + curl \ + ca-certificates \ + python3 \ + git \ + cmake \ + sudo \ + gdb \ + llvm-19-tools \ + llvm-19-dev \ + libedit-dev \ + libssl-dev \ + pkg-config \ + zlib1g-dev \ + xz-utils \ + nodejs \ + mingw-w64 \ + # libgccjit dependencies + flex \ + libmpfr-dev \ + libgmp-dev \ + libmpc3 \ + libmpc-dev \ + && rm -rf /var/lib/apt/lists/* + +# Install powershell (universal package) so we can test x.ps1 on Linux +# FIXME: need a "universal" version that supports libicu74, but for now it still works to ignore that dep. +RUN curl -sL "https://github.com/PowerShell/PowerShell/releases/download/v7.3.1/powershell_7.3.1-1.deb_amd64.deb" > powershell.deb && \ + dpkg --ignore-depends=libicu72 -i powershell.deb && \ + rm -f powershell.deb + +COPY scripts/sccache.sh /scripts/ +RUN sh /scripts/sccache.sh + +# We are disabling CI LLVM since this builder is intentionally using a host +# LLVM, rather than the typical src/llvm-project LLVM. +ENV NO_DOWNLOAD_CI_LLVM 1 +ENV EXTERNAL_LLVM 1 + +# Using llvm-link-shared due to libffi issues -- see #34486 +ENV RUST_CONFIGURE_ARGS \ + --build=x86_64-unknown-linux-gnu \ + --llvm-root=/usr/lib/llvm-19 \ + --enable-llvm-link-shared \ + --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/ + +RUN /scripts/build-gccjit.sh /scripts + +COPY scripts/x86_64-gnu-llvm.sh /tmp/script.sh +ENV SCRIPT /tmp/script.sh diff --git a/src/ci/github-actions/jobs.yml b/src/ci/github-actions/jobs.yml index 41d3b311749..f65083eec47 100644 --- a/src/ci/github-actions/jobs.yml +++ b/src/ci/github-actions/jobs.yml @@ -24,6 +24,10 @@ runners: os: macos-14 <<: *base-job + - &job-windows + os: windows-2022 + <<: *base-job + - &job-windows-8c os: windows-2022-8core-32gb <<: *base-job @@ -247,6 +251,11 @@ auto: - image: x86_64-gnu-distcheck <<: *job-linux-8c + - image: x86_64-gnu-llvm-19 + env: + RUST_BACKTRACE: 1 + <<: *job-linux-8c + - image: x86_64-gnu-llvm-18 env: RUST_BACKTRACE: 1 @@ -383,7 +392,7 @@ auto: python x.py miri --stage 2 library/alloc --test-args notest && python x.py miri --stage 2 library/std --test-args notest RUST_CONFIGURE_ARGS: --build=x86_64-pc-windows-msvc --enable-lld - <<: *job-windows-8c + <<: *job-windows # 32/64-bit MinGW builds. # diff --git a/src/doc/unstable-book/src/language-features/trait-upcasting.md b/src/doc/unstable-book/src/language-features/trait-upcasting.md index 3697ae38f9d..a5f99cc86f2 100644 --- a/src/doc/unstable-book/src/language-features/trait-upcasting.md +++ b/src/doc/unstable-book/src/language-features/trait-upcasting.md @@ -12,7 +12,6 @@ so long as `Bar: Foo`. ```rust,edition2018 #![feature(trait_upcasting)] -#![allow(incomplete_features)] trait Foo {} diff --git a/src/librustdoc/html/render/search_index.rs b/src/librustdoc/html/render/search_index.rs index b84c22ac746..86b719c46e8 100644 --- a/src/librustdoc/html/render/search_index.rs +++ b/src/librustdoc/html/render/search_index.rs @@ -847,7 +847,7 @@ enum SimplifiedParam { /// /// This function also works recursively. #[instrument(level = "trace", skip(tcx, res, rgen, cache))] -fn simplify_fn_type<'tcx, 'a>( +fn simplify_fn_type<'a, 'tcx>( self_: Option<&'a Type>, generics: &Generics, arg: &'a Type, @@ -1192,7 +1192,7 @@ fn simplify_fn_type<'tcx, 'a>( } } -fn simplify_fn_constraint<'tcx, 'a>( +fn simplify_fn_constraint<'a, 'tcx>( self_: Option<&'a Type>, generics: &Generics, constraint: &'a clean::AssocItemConstraint, diff --git a/src/tools/cargo b/src/tools/cargo index c1fa840a85e..a9a418d1a22 160000 --- a/src/tools/cargo +++ b/src/tools/cargo @@ -1 +1 @@ -Subproject commit c1fa840a85eca53818895901a53fae34247448b2 +Subproject commit a9a418d1a22f29e7dfd034e3b93f15657e608a29 diff --git a/src/tools/clippy/clippy_config/src/msrvs.rs b/src/tools/clippy/clippy_config/src/msrvs.rs index e17458b3310..a2b4b6e256f 100644 --- a/src/tools/clippy/clippy_config/src/msrvs.rs +++ b/src/tools/clippy/clippy_config/src/msrvs.rs @@ -17,6 +17,7 @@ macro_rules! msrv_aliases { // names may refer to stabilized feature flags or library items msrv_aliases! { + 1,83,0 { CONST_EXTERN_FN } 1,83,0 { CONST_FLOAT_BITS_CONV } 1,81,0 { LINT_REASONS_STABILIZATION } 1,80,0 { BOX_INTO_ITER} @@ -27,7 +28,7 @@ msrv_aliases! { 1,68,0 { PATH_MAIN_SEPARATOR_STR } 1,65,0 { LET_ELSE, POINTER_CAST_CONSTNESS } 1,63,0 { CLONE_INTO } - 1,62,0 { BOOL_THEN_SOME, DEFAULT_ENUM_ATTRIBUTE, CONST_EXTERN_FN } + 1,62,0 { BOOL_THEN_SOME, DEFAULT_ENUM_ATTRIBUTE, CONST_EXTERN_C_FN } 1,59,0 { THREAD_LOCAL_CONST_INIT } 1,58,0 { FORMAT_ARGS_CAPTURE, PATTERN_TRAIT_CHAR_ARRAY, CONST_RAW_PTR_DEREF } 1,56,0 { CONST_FN_UNION } diff --git a/src/tools/clippy/clippy_lints/src/missing_const_for_fn.rs b/src/tools/clippy/clippy_lints/src/missing_const_for_fn.rs index 052d738b2e7..859afe1b963 100644 --- a/src/tools/clippy/clippy_lints/src/missing_const_for_fn.rs +++ b/src/tools/clippy/clippy_lints/src/missing_const_for_fn.rs @@ -119,9 +119,7 @@ impl<'tcx> LateLintPass<'tcx> for MissingConstForFn { .iter() .any(|param| matches!(param.kind, GenericParamKind::Const { .. })); - if already_const(header) - || has_const_generic_params - || !could_be_const_with_abi(cx, &self.msrv, header.abi) + if already_const(header) || has_const_generic_params || !could_be_const_with_abi(&self.msrv, header.abi) { return; } @@ -183,13 +181,13 @@ fn already_const(header: hir::FnHeader) -> bool { header.constness == Constness::Const } -fn could_be_const_with_abi(cx: &LateContext<'_>, msrv: &Msrv, abi: Abi) -> bool { +fn could_be_const_with_abi(msrv: &Msrv, abi: Abi) -> bool { match abi { Abi::Rust => true, // `const extern "C"` was stabilized after 1.62.0 - Abi::C { unwind: false } => msrv.meets(msrvs::CONST_EXTERN_FN), + Abi::C { unwind: false } => msrv.meets(msrvs::CONST_EXTERN_C_FN), // Rest ABIs are still unstable and need the `const_extern_fn` feature enabled. - _ => cx.tcx.features().const_extern_fn, + _ => msrv.meets(msrvs::CONST_EXTERN_FN), } } diff --git a/src/tools/clippy/tests/ui/arithmetic_side_effects.rs b/src/tools/clippy/tests/ui/arithmetic_side_effects.rs index 9d06e14e88c..0838d064a5f 100644 --- a/src/tools/clippy/tests/ui/arithmetic_side_effects.rs +++ b/src/tools/clippy/tests/ui/arithmetic_side_effects.rs @@ -1,5 +1,8 @@ //@aux-build:proc_macro_derive.rs +#![feature(f128)] +#![feature(f16)] + #![allow( clippy::assign_op_pattern, clippy::erasing_op, @@ -10,9 +13,6 @@ arithmetic_overflow, unconditional_panic )] -#![feature(const_mut_refs)] -#![feature(f128)] -#![feature(f16)] #![warn(clippy::arithmetic_side_effects)] extern crate proc_macro_derive; diff --git a/src/tools/clippy/tests/ui/expect_tool_lint_rfc_2383.stderr b/src/tools/clippy/tests/ui/expect_tool_lint_rfc_2383.stderr index f70d3408aa4..028e22ca724 100644 --- a/src/tools/clippy/tests/ui/expect_tool_lint_rfc_2383.stderr +++ b/src/tools/clippy/tests/ui/expect_tool_lint_rfc_2383.stderr @@ -13,6 +13,14 @@ error: this lint expectation is unfulfilled LL | #[expect(invalid_nan_comparisons)] | ^^^^^^^^^^^^^^^^^^^^^^^ +error: this lint expectation is unfulfilled + --> tests/ui/expect_tool_lint_rfc_2383.rs:36:18 + | +LL | #[expect(invalid_nan_comparisons)] + | ^^^^^^^^^^^^^^^^^^^^^^^ + | + = note: duplicate diagnostic emitted due to `-Z deduplicate-diagnostics=no` + error: this lint expectation is unfulfilled --> tests/ui/expect_tool_lint_rfc_2383.rs:107:14 | @@ -37,5 +45,5 @@ error: this lint expectation is unfulfilled LL | #[expect(clippy::overly_complex_bool_expr)] | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ -error: aborting due to 6 previous errors +error: aborting due to 7 previous errors diff --git a/src/tools/clippy/tests/ui/missing_const_for_fn/cant_be_const.rs b/src/tools/clippy/tests/ui/missing_const_for_fn/cant_be_const.rs index 2c6e1e92da0..ca323dcf173 100644 --- a/src/tools/clippy/tests/ui/missing_const_for_fn/cant_be_const.rs +++ b/src/tools/clippy/tests/ui/missing_const_for_fn/cant_be_const.rs @@ -186,12 +186,6 @@ mod msrv { extern "C" fn c() {} } -mod with_extern { - extern "C-unwind" fn c_unwind() {} - extern "system" fn system() {} - extern "system-unwind" fn system_unwind() {} -} - mod with_ty_alias { type Foo = impl std::fmt::Debug; diff --git a/src/tools/clippy/tests/ui/missing_const_for_fn/could_be_const.fixed b/src/tools/clippy/tests/ui/missing_const_for_fn/could_be_const.fixed index f54503ada97..41b424a8e5d 100644 --- a/src/tools/clippy/tests/ui/missing_const_for_fn/could_be_const.fixed +++ b/src/tools/clippy/tests/ui/missing_const_for_fn/could_be_const.fixed @@ -1,6 +1,6 @@ #![warn(clippy::missing_const_for_fn)] #![allow(incomplete_features, clippy::let_and_return, clippy::missing_transmute_annotations)] -#![feature(const_mut_refs)] +#![allow(unsupported_calling_conventions)] #![feature(const_trait_impl)] use std::mem::transmute; @@ -204,3 +204,16 @@ mod with_ty_alias { // in this test. const fn alias_ty_is_projection(bar: <() as FooTrait>::Foo) {} } + +mod extern_fn { + const extern "C-unwind" fn c_unwind() {} + //~^ ERROR: this could be a `const fn` + const extern "system" fn system() {} + //~^ ERROR: this could be a `const fn` + const extern "system-unwind" fn system_unwind() {} + //~^ ERROR: this could be a `const fn` + pub const extern "stdcall" fn std_call() {} + //~^ ERROR: this could be a `const fn` + pub const extern "stdcall-unwind" fn std_call_unwind() {} + //~^ ERROR: this could be a `const fn` +} diff --git a/src/tools/clippy/tests/ui/missing_const_for_fn/could_be_const.rs b/src/tools/clippy/tests/ui/missing_const_for_fn/could_be_const.rs index 2c229068e4d..27593575a01 100644 --- a/src/tools/clippy/tests/ui/missing_const_for_fn/could_be_const.rs +++ b/src/tools/clippy/tests/ui/missing_const_for_fn/could_be_const.rs @@ -1,6 +1,6 @@ #![warn(clippy::missing_const_for_fn)] #![allow(incomplete_features, clippy::let_and_return, clippy::missing_transmute_annotations)] -#![feature(const_mut_refs)] +#![allow(unsupported_calling_conventions)] #![feature(const_trait_impl)] use std::mem::transmute; @@ -204,3 +204,16 @@ mod with_ty_alias { // in this test. fn alias_ty_is_projection(bar: <() as FooTrait>::Foo) {} } + +mod extern_fn { + extern "C-unwind" fn c_unwind() {} + //~^ ERROR: this could be a `const fn` + extern "system" fn system() {} + //~^ ERROR: this could be a `const fn` + extern "system-unwind" fn system_unwind() {} + //~^ ERROR: this could be a `const fn` + pub extern "stdcall" fn std_call() {} + //~^ ERROR: this could be a `const fn` + pub extern "stdcall-unwind" fn std_call_unwind() {} + //~^ ERROR: this could be a `const fn` +} diff --git a/src/tools/clippy/tests/ui/missing_const_for_fn/could_be_const.stderr b/src/tools/clippy/tests/ui/missing_const_for_fn/could_be_const.stderr index fb4db703103..12d97b17119 100644 --- a/src/tools/clippy/tests/ui/missing_const_for_fn/could_be_const.stderr +++ b/src/tools/clippy/tests/ui/missing_const_for_fn/could_be_const.stderr @@ -283,5 +283,60 @@ help: make the function `const` LL | const fn alias_ty_is_projection(bar: <() as FooTrait>::Foo) {} | +++++ -error: aborting due to 21 previous errors +error: this could be a `const fn` + --> tests/ui/missing_const_for_fn/could_be_const.rs:209:5 + | +LL | extern "C-unwind" fn c_unwind() {} + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | +help: make the function `const` + | +LL | const extern "C-unwind" fn c_unwind() {} + | +++++ + +error: this could be a `const fn` + --> tests/ui/missing_const_for_fn/could_be_const.rs:211:5 + | +LL | extern "system" fn system() {} + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | +help: make the function `const` + | +LL | const extern "system" fn system() {} + | +++++ + +error: this could be a `const fn` + --> tests/ui/missing_const_for_fn/could_be_const.rs:213:5 + | +LL | extern "system-unwind" fn system_unwind() {} + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | +help: make the function `const` + | +LL | const extern "system-unwind" fn system_unwind() {} + | +++++ + +error: this could be a `const fn` + --> tests/ui/missing_const_for_fn/could_be_const.rs:215:5 + | +LL | pub extern "stdcall" fn std_call() {} + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | +help: make the function `const` + | +LL | pub const extern "stdcall" fn std_call() {} + | +++++ + +error: this could be a `const fn` + --> tests/ui/missing_const_for_fn/could_be_const.rs:217:5 + | +LL | pub extern "stdcall-unwind" fn std_call_unwind() {} + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | +help: make the function `const` + | +LL | pub const extern "stdcall-unwind" fn std_call_unwind() {} + | +++++ + +error: aborting due to 26 previous errors diff --git a/src/tools/clippy/tests/ui/missing_const_for_fn/could_be_const_with_const_extern_fn.fixed b/src/tools/clippy/tests/ui/missing_const_for_fn/could_be_const_with_const_extern_fn.fixed deleted file mode 100644 index c103db536ab..00000000000 --- a/src/tools/clippy/tests/ui/missing_const_for_fn/could_be_const_with_const_extern_fn.fixed +++ /dev/null @@ -1,14 +0,0 @@ -#![warn(clippy::missing_const_for_fn)] -#![allow(unsupported_calling_conventions)] -#![feature(const_extern_fn)] - -const extern "C-unwind" fn c_unwind() {} -//~^ ERROR: this could be a `const fn` -const extern "system" fn system() {} -//~^ ERROR: this could be a `const fn` -const extern "system-unwind" fn system_unwind() {} -//~^ ERROR: this could be a `const fn` -pub const extern "stdcall" fn std_call() {} -//~^ ERROR: this could be a `const fn` -pub const extern "stdcall-unwind" fn std_call_unwind() {} -//~^ ERROR: this could be a `const fn` diff --git a/src/tools/clippy/tests/ui/missing_const_for_fn/could_be_const_with_const_extern_fn.rs b/src/tools/clippy/tests/ui/missing_const_for_fn/could_be_const_with_const_extern_fn.rs deleted file mode 100644 index 0f7020ae559..00000000000 --- a/src/tools/clippy/tests/ui/missing_const_for_fn/could_be_const_with_const_extern_fn.rs +++ /dev/null @@ -1,14 +0,0 @@ -#![warn(clippy::missing_const_for_fn)] -#![allow(unsupported_calling_conventions)] -#![feature(const_extern_fn)] - -extern "C-unwind" fn c_unwind() {} -//~^ ERROR: this could be a `const fn` -extern "system" fn system() {} -//~^ ERROR: this could be a `const fn` -extern "system-unwind" fn system_unwind() {} -//~^ ERROR: this could be a `const fn` -pub extern "stdcall" fn std_call() {} -//~^ ERROR: this could be a `const fn` -pub extern "stdcall-unwind" fn std_call_unwind() {} -//~^ ERROR: this could be a `const fn` diff --git a/src/tools/clippy/tests/ui/missing_const_for_fn/could_be_const_with_const_extern_fn.stderr b/src/tools/clippy/tests/ui/missing_const_for_fn/could_be_const_with_const_extern_fn.stderr deleted file mode 100644 index 036094a367b..00000000000 --- a/src/tools/clippy/tests/ui/missing_const_for_fn/could_be_const_with_const_extern_fn.stderr +++ /dev/null @@ -1,59 +0,0 @@ -error: this could be a `const fn` - --> tests/ui/missing_const_for_fn/could_be_const_with_const_extern_fn.rs:5:1 - | -LL | extern "C-unwind" fn c_unwind() {} - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ - | - = note: `-D clippy::missing-const-for-fn` implied by `-D warnings` - = help: to override `-D warnings` add `#[allow(clippy::missing_const_for_fn)]` -help: make the function `const` - | -LL | const extern "C-unwind" fn c_unwind() {} - | +++++ - -error: this could be a `const fn` - --> tests/ui/missing_const_for_fn/could_be_const_with_const_extern_fn.rs:7:1 - | -LL | extern "system" fn system() {} - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ - | -help: make the function `const` - | -LL | const extern "system" fn system() {} - | +++++ - -error: this could be a `const fn` - --> tests/ui/missing_const_for_fn/could_be_const_with_const_extern_fn.rs:9:1 - | -LL | extern "system-unwind" fn system_unwind() {} - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ - | -help: make the function `const` - | -LL | const extern "system-unwind" fn system_unwind() {} - | +++++ - -error: this could be a `const fn` - --> tests/ui/missing_const_for_fn/could_be_const_with_const_extern_fn.rs:11:1 - | -LL | pub extern "stdcall" fn std_call() {} - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ - | -help: make the function `const` - | -LL | pub const extern "stdcall" fn std_call() {} - | +++++ - -error: this could be a `const fn` - --> tests/ui/missing_const_for_fn/could_be_const_with_const_extern_fn.rs:13:1 - | -LL | pub extern "stdcall-unwind" fn std_call_unwind() {} - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ - | -help: make the function `const` - | -LL | pub const extern "stdcall-unwind" fn std_call_unwind() {} - | +++++ - -error: aborting due to 5 previous errors - diff --git a/src/tools/miri/src/concurrency/data_race.rs b/src/tools/miri/src/concurrency/data_race.rs index b604fd868a0..f686b331ad6 100644 --- a/src/tools/miri/src/concurrency/data_race.rs +++ b/src/tools/miri/src/concurrency/data_race.rs @@ -47,6 +47,7 @@ use std::{ }; use rustc_ast::Mutability; +use rustc_data_structures::fx::FxHashMap; use rustc_data_structures::fx::FxHashSet; use rustc_index::{Idx, IndexVec}; use rustc_middle::{mir, ty::Ty}; @@ -1047,32 +1048,31 @@ impl VClockAlloc { ) -> InterpResult<'tcx> { let current_span = machine.current_span(); let global = machine.data_race.as_ref().unwrap(); - if global.race_detecting() { - let (index, mut thread_clocks) = global.active_thread_state_mut(&machine.threads); - let mut alloc_ranges = self.alloc_ranges.borrow_mut(); - for (mem_clocks_range, mem_clocks) in - alloc_ranges.iter_mut(access_range.start, access_range.size) - { - if let Err(DataRace) = - mem_clocks.read_race_detect(&mut thread_clocks, index, read_type, current_span) - { - drop(thread_clocks); - // Report data-race. - return Self::report_data_race( - global, - &machine.threads, - mem_clocks, - AccessType::NaRead(read_type), - access_range.size, - interpret::Pointer::new(alloc_id, Size::from_bytes(mem_clocks_range.start)), - ty, - ); - } - } - Ok(()) - } else { - Ok(()) + if !global.race_detecting() { + return Ok(()); } + let (index, mut thread_clocks) = global.active_thread_state_mut(&machine.threads); + let mut alloc_ranges = self.alloc_ranges.borrow_mut(); + for (mem_clocks_range, mem_clocks) in + alloc_ranges.iter_mut(access_range.start, access_range.size) + { + if let Err(DataRace) = + mem_clocks.read_race_detect(&mut thread_clocks, index, read_type, current_span) + { + drop(thread_clocks); + // Report data-race. + return Self::report_data_race( + global, + &machine.threads, + mem_clocks, + AccessType::NaRead(read_type), + access_range.size, + interpret::Pointer::new(alloc_id, Size::from_bytes(mem_clocks_range.start)), + ty, + ); + } + } + Ok(()) } /// Detect data-races for an unsynchronized write operation. It will not perform @@ -1090,33 +1090,129 @@ impl VClockAlloc { ) -> InterpResult<'tcx> { let current_span = machine.current_span(); let global = machine.data_race.as_mut().unwrap(); - if global.race_detecting() { - let (index, mut thread_clocks) = global.active_thread_state_mut(&machine.threads); - for (mem_clocks_range, mem_clocks) in - self.alloc_ranges.get_mut().iter_mut(access_range.start, access_range.size) + if !global.race_detecting() { + return Ok(()); + } + let (index, mut thread_clocks) = global.active_thread_state_mut(&machine.threads); + for (mem_clocks_range, mem_clocks) in + self.alloc_ranges.get_mut().iter_mut(access_range.start, access_range.size) + { + if let Err(DataRace) = + mem_clocks.write_race_detect(&mut thread_clocks, index, write_type, current_span) { - if let Err(DataRace) = mem_clocks.write_race_detect( - &mut thread_clocks, - index, - write_type, - current_span, - ) { - drop(thread_clocks); - // Report data-race - return Self::report_data_race( - global, - &machine.threads, - mem_clocks, - AccessType::NaWrite(write_type), - access_range.size, - interpret::Pointer::new(alloc_id, Size::from_bytes(mem_clocks_range.start)), - ty, - ); - } + drop(thread_clocks); + // Report data-race + return Self::report_data_race( + global, + &machine.threads, + mem_clocks, + AccessType::NaWrite(write_type), + access_range.size, + interpret::Pointer::new(alloc_id, Size::from_bytes(mem_clocks_range.start)), + ty, + ); } - Ok(()) + } + Ok(()) + } +} + +/// Vector clock state for a stack frame (tracking the local variables +/// that do not have an allocation yet). +#[derive(Debug, Default)] +pub struct FrameState { + local_clocks: RefCell>, +} + +/// Stripped-down version of [`MemoryCellClocks`] for the clocks we need to keep track +/// of in a local that does not yet have addressable memory -- and hence can only +/// be accessed from the thread its stack frame belongs to, and cannot be access atomically. +#[derive(Debug)] +struct LocalClocks { + write: VTimestamp, + write_type: NaWriteType, + read: VTimestamp, +} + +impl Default for LocalClocks { + fn default() -> Self { + Self { write: VTimestamp::ZERO, write_type: NaWriteType::Allocate, read: VTimestamp::ZERO } + } +} + +impl FrameState { + pub fn local_write(&self, local: mir::Local, storage_live: bool, machine: &MiriMachine<'_>) { + let current_span = machine.current_span(); + let global = machine.data_race.as_ref().unwrap(); + if !global.race_detecting() { + return; + } + let (index, mut thread_clocks) = global.active_thread_state_mut(&machine.threads); + // This should do the same things as `MemoryCellClocks::write_race_detect`. + if !current_span.is_dummy() { + thread_clocks.clock.index_mut(index).span = current_span; + } + let mut clocks = self.local_clocks.borrow_mut(); + if storage_live { + let new_clocks = LocalClocks { + write: thread_clocks.clock[index], + write_type: NaWriteType::Allocate, + read: VTimestamp::ZERO, + }; + // There might already be an entry in the map for this, if the local was previously + // live already. + clocks.insert(local, new_clocks); } else { - Ok(()) + // This can fail to exist if `race_detecting` was false when the allocation + // occurred, in which case we can backdate this to the beginning of time. + let clocks = clocks.entry(local).or_insert_with(Default::default); + clocks.write = thread_clocks.clock[index]; + clocks.write_type = NaWriteType::Write; + } + } + + pub fn local_read(&self, local: mir::Local, machine: &MiriMachine<'_>) { + let current_span = machine.current_span(); + let global = machine.data_race.as_ref().unwrap(); + if !global.race_detecting() { + return; + } + let (index, mut thread_clocks) = global.active_thread_state_mut(&machine.threads); + // This should do the same things as `MemoryCellClocks::read_race_detect`. + if !current_span.is_dummy() { + thread_clocks.clock.index_mut(index).span = current_span; + } + thread_clocks.clock.index_mut(index).set_read_type(NaReadType::Read); + // This can fail to exist if `race_detecting` was false when the allocation + // occurred, in which case we can backdate this to the beginning of time. + let mut clocks = self.local_clocks.borrow_mut(); + let clocks = clocks.entry(local).or_insert_with(Default::default); + clocks.read = thread_clocks.clock[index]; + } + + pub fn local_moved_to_memory( + &self, + local: mir::Local, + alloc: &mut VClockAlloc, + machine: &MiriMachine<'_>, + ) { + let global = machine.data_race.as_ref().unwrap(); + if !global.race_detecting() { + return; + } + let (index, _thread_clocks) = global.active_thread_state_mut(&machine.threads); + // Get the time the last write actually happened. This can fail to exist if + // `race_detecting` was false when the write occurred, in that case we can backdate this + // to the beginning of time. + let local_clocks = self.local_clocks.borrow_mut().remove(&local).unwrap_or_default(); + for (_mem_clocks_range, mem_clocks) in alloc.alloc_ranges.get_mut().iter_mut_all() { + // The initialization write for this already happened, just at the wrong timestamp. + // Check that the thread index matches what we expect. + assert_eq!(mem_clocks.write.0, index); + // Convert the local's clocks into memory clocks. + mem_clocks.write = (index, local_clocks.write); + mem_clocks.write_type = local_clocks.write_type; + mem_clocks.read = VClock::new_with_index(index, local_clocks.read); } } } @@ -1305,69 +1401,67 @@ trait EvalContextPrivExt<'tcx>: MiriInterpCxExt<'tcx> { ) -> InterpResult<'tcx> { let this = self.eval_context_ref(); assert!(access.is_atomic()); - if let Some(data_race) = &this.machine.data_race { - if data_race.race_detecting() { - let size = place.layout.size; - let (alloc_id, base_offset, _prov) = this.ptr_get_alloc_id(place.ptr(), 0)?; - // Load and log the atomic operation. - // Note that atomic loads are possible even from read-only allocations, so `get_alloc_extra_mut` is not an option. - let alloc_meta = this.get_alloc_extra(alloc_id)?.data_race.as_ref().unwrap(); - trace!( - "Atomic op({}) with ordering {:?} on {:?} (size={})", - access.description(None, None), - &atomic, - place.ptr(), - size.bytes() - ); + let Some(data_race) = &this.machine.data_race else { return Ok(()) }; + if !data_race.race_detecting() { + return Ok(()); + } + let size = place.layout.size; + let (alloc_id, base_offset, _prov) = this.ptr_get_alloc_id(place.ptr(), 0)?; + // Load and log the atomic operation. + // Note that atomic loads are possible even from read-only allocations, so `get_alloc_extra_mut` is not an option. + let alloc_meta = this.get_alloc_extra(alloc_id)?.data_race.as_ref().unwrap(); + trace!( + "Atomic op({}) with ordering {:?} on {:?} (size={})", + access.description(None, None), + &atomic, + place.ptr(), + size.bytes() + ); - let current_span = this.machine.current_span(); - // Perform the atomic operation. - data_race.maybe_perform_sync_operation( - &this.machine.threads, - current_span, - |index, mut thread_clocks| { - for (mem_clocks_range, mem_clocks) in - alloc_meta.alloc_ranges.borrow_mut().iter_mut(base_offset, size) - { - if let Err(DataRace) = op(mem_clocks, &mut thread_clocks, index, atomic) - { - mem::drop(thread_clocks); - return VClockAlloc::report_data_race( - data_race, - &this.machine.threads, - mem_clocks, - access, - place.layout.size, - interpret::Pointer::new( - alloc_id, - Size::from_bytes(mem_clocks_range.start), - ), - None, - ) - .map(|_| true); - } - } - - // This conservatively assumes all operations have release semantics - Ok(true) - }, - )?; - - // Log changes to atomic memory. - if tracing::enabled!(tracing::Level::TRACE) { - for (_offset, mem_clocks) in - alloc_meta.alloc_ranges.borrow().iter(base_offset, size) - { - trace!( - "Updated atomic memory({:?}, size={}) to {:#?}", - place.ptr(), - size.bytes(), - mem_clocks.atomic_ops - ); + let current_span = this.machine.current_span(); + // Perform the atomic operation. + data_race.maybe_perform_sync_operation( + &this.machine.threads, + current_span, + |index, mut thread_clocks| { + for (mem_clocks_range, mem_clocks) in + alloc_meta.alloc_ranges.borrow_mut().iter_mut(base_offset, size) + { + if let Err(DataRace) = op(mem_clocks, &mut thread_clocks, index, atomic) { + mem::drop(thread_clocks); + return VClockAlloc::report_data_race( + data_race, + &this.machine.threads, + mem_clocks, + access, + place.layout.size, + interpret::Pointer::new( + alloc_id, + Size::from_bytes(mem_clocks_range.start), + ), + None, + ) + .map(|_| true); } } + + // This conservatively assumes all operations have release semantics + Ok(true) + }, + )?; + + // Log changes to atomic memory. + if tracing::enabled!(tracing::Level::TRACE) { + for (_offset, mem_clocks) in alloc_meta.alloc_ranges.borrow().iter(base_offset, size) { + trace!( + "Updated atomic memory({:?}, size={}) to {:#?}", + place.ptr(), + size.bytes(), + mem_clocks.atomic_ops + ); } } + Ok(()) } } diff --git a/src/tools/miri/src/concurrency/thread.rs b/src/tools/miri/src/concurrency/thread.rs index 306245a843b..4efe2beb155 100644 --- a/src/tools/miri/src/concurrency/thread.rs +++ b/src/tools/miri/src/concurrency/thread.rs @@ -530,7 +530,9 @@ impl<'tcx> ThreadManager<'tcx> { } /// Mutably borrow the stack of the active thread. - fn active_thread_stack_mut(&mut self) -> &mut Vec>> { + pub fn active_thread_stack_mut( + &mut self, + ) -> &mut Vec>> { &mut self.threads[self.active_thread].stack } pub fn all_stacks( @@ -898,7 +900,7 @@ pub trait EvalContextExt<'tcx>: crate::MiriInterpCxExt<'tcx> { // This allocation will be deallocated when the thread dies, so it is not in read-only memory. alloc.mutability = Mutability::Mut; // Create a fresh allocation with this content. - let ptr = this.allocate_raw_ptr(alloc, MiriMemoryKind::Tls.into())?; + let ptr = this.insert_allocation(alloc, MiriMemoryKind::Tls.into())?; this.machine.threads.set_thread_local_alloc(def_id, ptr); Ok(ptr) } diff --git a/src/tools/miri/src/concurrency/vector_clock.rs b/src/tools/miri/src/concurrency/vector_clock.rs index c3496bc1a0c..0968e10bbee 100644 --- a/src/tools/miri/src/concurrency/vector_clock.rs +++ b/src/tools/miri/src/concurrency/vector_clock.rs @@ -130,6 +130,9 @@ impl Ord for VTimestamp { /// also this means that there is only one unique valid length /// for each set of vector clock values and hence the PartialEq /// and Eq derivations are correct. +/// +/// This means we cannot represent a clock where the last entry is a timestamp-0 read that occurs +/// because of a retag. That's fine, all it does is risk wrong diagnostics in a extreme corner case. #[derive(PartialEq, Eq, Default, Debug)] pub struct VClock(SmallVec<[VTimestamp; SMALL_VECTOR]>); @@ -137,6 +140,9 @@ impl VClock { /// Create a new vector-clock containing all zeros except /// for a value at the given index pub(super) fn new_with_index(index: VectorIdx, timestamp: VTimestamp) -> VClock { + if timestamp.time() == 0 { + return VClock::default(); + } let len = index.index() + 1; let mut vec = smallvec::smallvec![VTimestamp::ZERO; len]; vec[index.index()] = timestamp; diff --git a/src/tools/miri/src/intrinsics/mod.rs b/src/tools/miri/src/intrinsics/mod.rs index 0ab1b9dfb61..7acc99a8af0 100644 --- a/src/tools/miri/src/intrinsics/mod.rs +++ b/src/tools/miri/src/intrinsics/mod.rs @@ -3,11 +3,8 @@ mod atomic; mod simd; -use std::iter; - use rand::Rng; use rustc_apfloat::{Float, Round}; -use rustc_middle::ty::layout::LayoutOf; use rustc_middle::{ mir, ty::{self, FloatTy}, @@ -119,19 +116,9 @@ pub trait EvalContextExt<'tcx>: crate::MiriInterpCxExt<'tcx> { this.copy_op(dest, &place)?; } - "write_bytes" | "volatile_set_memory" => { + "volatile_set_memory" => { let [ptr, val_byte, count] = check_arg_count(args)?; - let ty = ptr.layout.ty.builtin_deref(true).unwrap(); - let ty_layout = this.layout_of(ty)?; - let val_byte = this.read_scalar(val_byte)?.to_u8()?; - let ptr = this.read_pointer(ptr)?; - let count = this.read_target_usize(count)?; - // `checked_mul` enforces a too small bound (the correct one would probably be target_isize_max), - // but no actual allocation can be big enough for the difference to be noticeable. - let byte_count = ty_layout.size.checked_mul(count, this).ok_or_else(|| { - err_ub_format!("overflow computing total size of `{intrinsic_name}`") - })?; - this.write_bytes_ptr(ptr, iter::repeat(val_byte).take(byte_count.bytes_usize()))?; + this.write_bytes_intrinsic(ptr, val_byte, count, "volatile_set_memory")?; } // Memory model / provenance manipulation diff --git a/src/tools/miri/src/intrinsics/simd.rs b/src/tools/miri/src/intrinsics/simd.rs index aa91b89d0ec..e22306ca82f 100644 --- a/src/tools/miri/src/intrinsics/simd.rs +++ b/src/tools/miri/src/intrinsics/simd.rs @@ -664,15 +664,9 @@ pub trait EvalContextExt<'tcx>: crate::MiriInterpCxExt<'tcx> { let [left, right, index] = check_arg_count(args)?; let (left, left_len) = this.project_to_simd(left)?; let (right, right_len) = this.project_to_simd(right)?; + let (index, index_len) = this.project_to_simd(index)?; let (dest, dest_len) = this.project_to_simd(dest)?; - // `index` is an array or a SIMD type - let (index, index_len) = match index.layout.ty.kind() { - // FIXME: remove this once `index` must always be a SIMD vector. - ty::Array(..) => (index.clone(), index.len(this)?), - _ => this.project_to_simd(index)?, - }; - assert_eq!(left_len, right_len); assert_eq!(index_len, dest_len); diff --git a/src/tools/miri/src/machine.rs b/src/tools/miri/src/machine.rs index 76b4366476d..df55902decd 100644 --- a/src/tools/miri/src/machine.rs +++ b/src/tools/miri/src/machine.rs @@ -81,24 +81,42 @@ pub struct FrameExtra<'tcx> { /// an additional bit of "salt" into the cache key. This salt is fixed per-frame /// so that within a call, a const will have a stable address. salt: usize, + + /// Data race detector per-frame data. + pub data_race: Option, } impl<'tcx> std::fmt::Debug for FrameExtra<'tcx> { fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { // Omitting `timing`, it does not support `Debug`. - let FrameExtra { borrow_tracker, catch_unwind, timing: _, is_user_relevant: _, salt: _ } = - self; + let FrameExtra { + borrow_tracker, + catch_unwind, + timing: _, + is_user_relevant, + salt, + data_race, + } = self; f.debug_struct("FrameData") .field("borrow_tracker", borrow_tracker) .field("catch_unwind", catch_unwind) + .field("is_user_relevant", is_user_relevant) + .field("salt", salt) + .field("data_race", data_race) .finish() } } impl VisitProvenance for FrameExtra<'_> { fn visit_provenance(&self, visit: &mut VisitWith<'_>) { - let FrameExtra { catch_unwind, borrow_tracker, timing: _, is_user_relevant: _, salt: _ } = - self; + let FrameExtra { + catch_unwind, + borrow_tracker, + timing: _, + is_user_relevant: _, + salt: _, + data_race: _, + } = self; catch_unwind.visit_provenance(visit); borrow_tracker.visit_provenance(visit); @@ -1446,6 +1464,7 @@ impl<'tcx> Machine<'tcx> for MiriMachine<'tcx> { timing, is_user_relevant: ecx.machine.is_user_relevant(&frame), salt: ecx.machine.rng.borrow_mut().gen::() % ADDRS_PER_ANON_GLOBAL, + data_race: ecx.machine.data_race.as_ref().map(|_| data_race::FrameState::default()), }; Ok(frame.with_extra(extra)) @@ -1551,7 +1570,25 @@ impl<'tcx> Machine<'tcx> for MiriMachine<'tcx> { res } - fn after_local_allocated( + fn after_local_read(ecx: &InterpCx<'tcx, Self>, local: mir::Local) -> InterpResult<'tcx> { + if let Some(data_race) = &ecx.frame().extra.data_race { + data_race.local_read(local, &ecx.machine); + } + Ok(()) + } + + fn after_local_write( + ecx: &mut InterpCx<'tcx, Self>, + local: mir::Local, + storage_live: bool, + ) -> InterpResult<'tcx> { + if let Some(data_race) = &ecx.frame().extra.data_race { + data_race.local_write(local, storage_live, &ecx.machine); + } + Ok(()) + } + + fn after_local_moved_to_memory( ecx: &mut InterpCx<'tcx, Self>, local: mir::Local, mplace: &MPlaceTy<'tcx>, @@ -1559,9 +1596,17 @@ impl<'tcx> Machine<'tcx> for MiriMachine<'tcx> { let Some(Provenance::Concrete { alloc_id, .. }) = mplace.ptr().provenance else { panic!("after_local_allocated should only be called on fresh allocations"); }; + // Record the span where this was allocated: the declaration of the local. let local_decl = &ecx.frame().body().local_decls[local]; let span = local_decl.source_info.span; ecx.machine.allocation_spans.borrow_mut().insert(alloc_id, (span, None)); + // The data race system has to fix the clocks used for this write. + let (alloc_info, machine) = ecx.get_alloc_extra_mut(alloc_id)?; + if let Some(data_race) = + &machine.threads.active_thread_stack().last().unwrap().extra.data_race + { + data_race.local_moved_to_memory(local, alloc_info.data_race.as_mut().unwrap(), machine); + } Ok(()) } diff --git a/src/tools/miri/src/shims/foreign_items.rs b/src/tools/miri/src/shims/foreign_items.rs index 88ab012f978..67dc1476175 100644 --- a/src/tools/miri/src/shims/foreign_items.rs +++ b/src/tools/miri/src/shims/foreign_items.rs @@ -196,7 +196,7 @@ trait EvalContextExtPriv<'tcx>: crate::MiriInterpCxExt<'tcx> { if size == 0 { throw_ub_format!("creating allocation with size 0"); } - if i128::from(size) > this.tcx.data_layout.pointer_size.signed_int_max() { + if size > this.max_size_of_val().bytes() { throw_ub_format!("creating an allocation larger than half the address space"); } if let Err(e) = Align::from_bytes(align) { @@ -441,19 +441,34 @@ trait EvalContextExtPriv<'tcx>: crate::MiriInterpCxExt<'tcx> { "malloc" => { let [size] = this.check_shim(abi, Abi::C { unwind: false }, link_name, args)?; let size = this.read_target_usize(size)?; - let res = this.malloc(size, /*zero_init:*/ false)?; - this.write_pointer(res, dest)?; + if size <= this.max_size_of_val().bytes() { + let res = this.malloc(size, /*zero_init:*/ false)?; + this.write_pointer(res, dest)?; + } else { + // If this does not fit in an isize, return null and, on Unix, set errno. + if this.target_os_is_unix() { + let einval = this.eval_libc("ENOMEM"); + this.set_last_error(einval)?; + } + this.write_null(dest)?; + } } "calloc" => { - let [items, len] = + let [items, elem_size] = this.check_shim(abi, Abi::C { unwind: false }, link_name, args)?; let items = this.read_target_usize(items)?; - let len = this.read_target_usize(len)?; - let size = items - .checked_mul(len) - .ok_or_else(|| err_ub_format!("overflow during calloc size computation"))?; - let res = this.malloc(size, /*zero_init:*/ true)?; - this.write_pointer(res, dest)?; + let elem_size = this.read_target_usize(elem_size)?; + if let Some(size) = this.compute_size_in_bytes(Size::from_bytes(elem_size), items) { + let res = this.malloc(size.bytes(), /*zero_init:*/ true)?; + this.write_pointer(res, dest)?; + } else { + // On size overflow, return null and, on Unix, set errno. + if this.target_os_is_unix() { + let einval = this.eval_libc("ENOMEM"); + this.set_last_error(einval)?; + } + this.write_null(dest)?; + } } "free" => { let [ptr] = this.check_shim(abi, Abi::C { unwind: false }, link_name, args)?; @@ -465,8 +480,17 @@ trait EvalContextExtPriv<'tcx>: crate::MiriInterpCxExt<'tcx> { this.check_shim(abi, Abi::C { unwind: false }, link_name, args)?; let old_ptr = this.read_pointer(old_ptr)?; let new_size = this.read_target_usize(new_size)?; - let res = this.realloc(old_ptr, new_size)?; - this.write_pointer(res, dest)?; + if new_size <= this.max_size_of_val().bytes() { + let res = this.realloc(old_ptr, new_size)?; + this.write_pointer(res, dest)?; + } else { + // If this does not fit in an isize, return null and, on Unix, set errno. + if this.target_os_is_unix() { + let einval = this.eval_libc("ENOMEM"); + this.set_last_error(einval)?; + } + this.write_null(dest)?; + } } // Rust allocation diff --git a/src/tools/miri/src/shims/unix/foreign_items.rs b/src/tools/miri/src/shims/unix/foreign_items.rs index 273a99b3116..73f933264fd 100644 --- a/src/tools/miri/src/shims/unix/foreign_items.rs +++ b/src/tools/miri/src/shims/unix/foreign_items.rs @@ -363,14 +363,14 @@ pub trait EvalContextExt<'tcx>: crate::MiriInterpCxExt<'tcx> { // // Linux: https://www.unix.com/man-page/linux/3/reallocarray/ // FreeBSD: https://man.freebsd.org/cgi/man.cgi?query=reallocarray - match nmemb.checked_mul(size) { + match this.compute_size_in_bytes(Size::from_bytes(size), nmemb) { None => { let einval = this.eval_libc("ENOMEM"); this.set_last_error(einval)?; this.write_null(dest)?; } Some(len) => { - let res = this.realloc(ptr, len)?; + let res = this.realloc(ptr, len.bytes())?; this.write_pointer(res, dest)?; } } diff --git a/src/tools/miri/tests/fail/data_race/local_variable_alloc_race.rs b/src/tools/miri/tests/fail/data_race/local_variable_alloc_race.rs new file mode 100644 index 00000000000..751a308a399 --- /dev/null +++ b/src/tools/miri/tests/fail/data_race/local_variable_alloc_race.rs @@ -0,0 +1,57 @@ +//@compile-flags: -Zmiri-preemption-rate=0.0 -Zmiri-disable-weak-memory-emulation +#![feature(core_intrinsics)] +#![feature(custom_mir)] + +use std::intrinsics::mir::*; +use std::sync::atomic::Ordering::*; +use std::sync::atomic::*; +use std::thread::JoinHandle; + +static P: AtomicPtr = AtomicPtr::new(core::ptr::null_mut()); + +fn spawn_thread() -> JoinHandle<()> { + std::thread::spawn(|| { + while P.load(Relaxed).is_null() { + std::hint::spin_loop(); + } + unsafe { + // Initialize `*P`. + let ptr = P.load(Relaxed); + *ptr = 127; + //~^ ERROR: Data race detected between (1) creating a new allocation on thread `main` and (2) non-atomic write on thread `unnamed-1` + } + }) +} + +fn finish(t: JoinHandle<()>, val_ptr: *mut u8) { + P.store(val_ptr, Relaxed); + + // Wait for the thread to be done. + t.join().unwrap(); + + // Read initialized value. + assert_eq!(unsafe { *val_ptr }, 127); +} + +#[custom_mir(dialect = "runtime", phase = "optimized")] +fn main() { + mir! { + let t; + let val; + let val_ptr; + let _ret; + { + Call(t = spawn_thread(), ReturnTo(after_spawn), UnwindContinue()) + } + after_spawn = { + // This races with the write in the other thread. + StorageLive(val); + + val_ptr = &raw mut val; + Call(_ret = finish(t, val_ptr), ReturnTo(done), UnwindContinue()) + } + done = { + Return() + } + } +} diff --git a/src/tools/miri/tests/fail/data_race/local_variable_alloc_race.stderr b/src/tools/miri/tests/fail/data_race/local_variable_alloc_race.stderr new file mode 100644 index 00000000000..f46eb078a51 --- /dev/null +++ b/src/tools/miri/tests/fail/data_race/local_variable_alloc_race.stderr @@ -0,0 +1,20 @@ +error: Undefined Behavior: Data race detected between (1) creating a new allocation on thread `main` and (2) non-atomic write on thread `unnamed-ID` at ALLOC. (2) just happened here + --> $DIR/local_variable_alloc_race.rs:LL:CC + | +LL | *ptr = 127; + | ^^^^^^^^^^ Data race detected between (1) creating a new allocation on thread `main` and (2) non-atomic write on thread `unnamed-ID` at ALLOC. (2) just happened here + | +help: and (1) occurred earlier here + --> $DIR/local_variable_alloc_race.rs:LL:CC + | +LL | StorageLive(val); + | ^^^^^^^^^^^^^^^^ + = help: this indicates a bug in the program: it performed an invalid operation, and caused Undefined Behavior + = help: see https://doc.rust-lang.org/nightly/reference/behavior-considered-undefined.html for further information + = note: BACKTRACE (of the first span) on thread `unnamed-ID`: + = note: inside closure at $DIR/local_variable_alloc_race.rs:LL:CC + +note: some details are omitted, run with `MIRIFLAGS=-Zmiri-backtrace=full` for a verbose backtrace + +error: aborting due to 1 previous error + diff --git a/src/tools/miri/tests/fail/data_race/local_variable_read_race.rs b/src/tools/miri/tests/fail/data_race/local_variable_read_race.rs new file mode 100644 index 00000000000..80d2b7b7c12 --- /dev/null +++ b/src/tools/miri/tests/fail/data_race/local_variable_read_race.rs @@ -0,0 +1,38 @@ +//@compile-flags: -Zmiri-preemption-rate=0.0 -Zmiri-disable-weak-memory-emulation +use std::sync::atomic::Ordering::*; +use std::sync::atomic::*; + +static P: AtomicPtr = AtomicPtr::new(core::ptr::null_mut()); + +fn main() { + // Create the local variable, and initialize it. + let mut val: u8 = 0; + + let t1 = std::thread::spawn(|| { + while P.load(Relaxed).is_null() { + std::hint::spin_loop(); + } + unsafe { + // Initialize `*P`. + let ptr = P.load(Relaxed); + *ptr = 127; + //~^ ERROR: Data race detected between (1) non-atomic read on thread `main` and (2) non-atomic write on thread `unnamed-1` + } + }); + + // This read is not ordered with the store above, and thus should be reported as a race. + let _val = val; + + // Actually generate memory for the local variable. + // This is the time its value is actually written to memory. + // If we just "pre-date" the write to the beginning of time (since we don't know + // when it actually happened), we'd miss the UB in this test. + // Also, the UB error should point at the write above, not the addr-of here. + P.store(std::ptr::addr_of_mut!(val), Relaxed); + + // Wait for the thread to be done. + t1.join().unwrap(); + + // Read initialized value. + assert_eq!(val, 127); +} diff --git a/src/tools/miri/tests/fail/data_race/local_variable_read_race.stderr b/src/tools/miri/tests/fail/data_race/local_variable_read_race.stderr new file mode 100644 index 00000000000..d14c2fb47ff --- /dev/null +++ b/src/tools/miri/tests/fail/data_race/local_variable_read_race.stderr @@ -0,0 +1,20 @@ +error: Undefined Behavior: Data race detected between (1) non-atomic read on thread `main` and (2) non-atomic write on thread `unnamed-ID` at ALLOC. (2) just happened here + --> $DIR/local_variable_read_race.rs:LL:CC + | +LL | *ptr = 127; + | ^^^^^^^^^^ Data race detected between (1) non-atomic read on thread `main` and (2) non-atomic write on thread `unnamed-ID` at ALLOC. (2) just happened here + | +help: and (1) occurred earlier here + --> $DIR/local_variable_read_race.rs:LL:CC + | +LL | let _val = val; + | ^^^ + = help: this indicates a bug in the program: it performed an invalid operation, and caused Undefined Behavior + = help: see https://doc.rust-lang.org/nightly/reference/behavior-considered-undefined.html for further information + = note: BACKTRACE (of the first span) on thread `unnamed-ID`: + = note: inside closure at $DIR/local_variable_read_race.rs:LL:CC + +note: some details are omitted, run with `MIRIFLAGS=-Zmiri-backtrace=full` for a verbose backtrace + +error: aborting due to 1 previous error + diff --git a/src/tools/miri/tests/fail/data_race/local_variable_write_race.rs b/src/tools/miri/tests/fail/data_race/local_variable_write_race.rs new file mode 100644 index 00000000000..eabbe4403c6 --- /dev/null +++ b/src/tools/miri/tests/fail/data_race/local_variable_write_race.rs @@ -0,0 +1,37 @@ +//@compile-flags: -Zmiri-preemption-rate=0.0 -Zmiri-disable-weak-memory-emulation +use std::sync::atomic::Ordering::*; +use std::sync::atomic::*; + +static P: AtomicPtr = AtomicPtr::new(core::ptr::null_mut()); + +fn main() { + let t1 = std::thread::spawn(|| { + while P.load(Relaxed).is_null() { + std::hint::spin_loop(); + } + unsafe { + // Initialize `*P`. + let ptr = P.load(Relaxed); + *ptr = 127; + //~^ ERROR: Data race detected between (1) non-atomic write on thread `main` and (2) non-atomic write on thread `unnamed-1` + } + }); + + // Create the local variable, and initialize it. + // This is not ordered with the store above, so it's definitely UB + // for that thread to access this variable. + let mut val: u8 = 0; + + // Actually generate memory for the local variable. + // This is the time its value is actually written to memory. + // If we just "pre-date" the write to the beginning of time (since we don't know + // when it actually happened), we'd miss the UB in this test. + // Also, the UB error should point at the write above, not the addr-of here. + P.store(std::ptr::addr_of_mut!(val), Relaxed); + + // Wait for the thread to be done. + t1.join().unwrap(); + + // Read initialized value. + assert_eq!(val, 127); +} diff --git a/src/tools/miri/tests/fail/data_race/local_variable_write_race.stderr b/src/tools/miri/tests/fail/data_race/local_variable_write_race.stderr new file mode 100644 index 00000000000..d84db955a3d --- /dev/null +++ b/src/tools/miri/tests/fail/data_race/local_variable_write_race.stderr @@ -0,0 +1,20 @@ +error: Undefined Behavior: Data race detected between (1) non-atomic write on thread `main` and (2) non-atomic write on thread `unnamed-ID` at ALLOC. (2) just happened here + --> $DIR/local_variable_write_race.rs:LL:CC + | +LL | *ptr = 127; + | ^^^^^^^^^^ Data race detected between (1) non-atomic write on thread `main` and (2) non-atomic write on thread `unnamed-ID` at ALLOC. (2) just happened here + | +help: and (1) occurred earlier here + --> $DIR/local_variable_write_race.rs:LL:CC + | +LL | let mut val: u8 = 0; + | ^ + = help: this indicates a bug in the program: it performed an invalid operation, and caused Undefined Behavior + = help: see https://doc.rust-lang.org/nightly/reference/behavior-considered-undefined.html for further information + = note: BACKTRACE (of the first span) on thread `unnamed-ID`: + = note: inside closure at $DIR/local_variable_write_race.rs:LL:CC + +note: some details are omitted, run with `MIRIFLAGS=-Zmiri-backtrace=full` for a verbose backtrace + +error: aborting due to 1 previous error + diff --git a/src/tools/miri/tests/pass-dep/libc/libc-mem.rs b/src/tools/miri/tests/pass-dep/libc/libc-mem.rs index aa383a99bc2..c399616b9ae 100644 --- a/src/tools/miri/tests/pass-dep/libc/libc-mem.rs +++ b/src/tools/miri/tests/pass-dep/libc/libc-mem.rs @@ -101,6 +101,10 @@ fn test_malloc() { let slice = slice::from_raw_parts(p3 as *const u8, 20); assert_eq!(&slice, &[0_u8; 20]); + // new size way too big (so this doesn't actually realloc). + let p_too_big = libc::realloc(p3, usize::MAX); + assert!(p_too_big.is_null()); + // old size > new size let p4 = libc::realloc(p3, 10); let slice = slice::from_raw_parts(p4 as *const u8, 10); @@ -119,9 +123,13 @@ fn test_malloc() { unsafe { let p1 = libc::realloc(ptr::null_mut(), 20); assert!(!p1.is_null()); - libc::free(p1); } + + unsafe { + let p_too_big = libc::malloc(usize::MAX); + assert!(p_too_big.is_null()); + } } fn test_calloc() { @@ -143,6 +151,9 @@ fn test_calloc() { let slice = slice::from_raw_parts(p4 as *const u8, 4 * 8); assert_eq!(&slice, &[0_u8; 4 * 8]); libc::free(p4); + + let p_too_big = libc::calloc(usize::MAX / 4, 4); + assert!(p_too_big.is_null()); } } diff --git a/src/tools/miri/tests/pass/concurrency/data_race.rs b/src/tools/miri/tests/pass/concurrency/data_race.rs index d31420380a5..34380dfa504 100644 --- a/src/tools/miri/tests/pass/concurrency/data_race.rs +++ b/src/tools/miri/tests/pass/concurrency/data_race.rs @@ -1,6 +1,6 @@ //@compile-flags: -Zmiri-disable-weak-memory-emulation -Zmiri-preemption-rate=0 -use std::sync::atomic::{fence, AtomicUsize, Ordering}; +use std::sync::atomic::*; use std::thread::spawn; #[derive(Copy, Clone)] @@ -112,9 +112,41 @@ pub fn test_simple_release() { } } +fn test_local_variable_lazy_write() { + static P: AtomicPtr = AtomicPtr::new(core::ptr::null_mut()); + + // Create the local variable, and initialize it. + // This write happens before the thread is spanwed, so there is no data race. + let mut val: u8 = 0; + + let t1 = std::thread::spawn(|| { + while P.load(Ordering::Relaxed).is_null() { + std::hint::spin_loop(); + } + unsafe { + // Initialize `*P`. + let ptr = P.load(Ordering::Relaxed); + *ptr = 127; + } + }); + + // Actually generate memory for the local variable. + // This is the time its value is actually written to memory: + // that's *after* the thread above was spawned! + // This may hence look like a data race wrt the access in the thread above. + P.store(std::ptr::addr_of_mut!(val), Ordering::Relaxed); + + // Wait for the thread to be done. + t1.join().unwrap(); + + // Read initialized value. + assert_eq!(val, 127); +} + pub fn main() { test_fence_sync(); test_multiple_reads(); test_rmw_no_block(); test_simple_release(); + test_local_variable_lazy_write(); } diff --git a/src/tools/miri/tests/pass/intrinsics/portable-simd.rs b/src/tools/miri/tests/pass/intrinsics/portable-simd.rs index daf75fee8fe..4c0d6f52425 100644 --- a/src/tools/miri/tests/pass/intrinsics/portable-simd.rs +++ b/src/tools/miri/tests/pass/intrinsics/portable-simd.rs @@ -619,7 +619,6 @@ fn simd_intrinsics() { i32x4::from_array([10, 2, 10, 10]) ); assert_eq!(simd_shuffle_generic::<_, i32x4, { &[3, 1, 0, 2] }>(a, b), a,); - assert_eq!(simd_shuffle::<_, _, i32x4>(a, b, const { [3u32, 1, 0, 2] }), a,); assert_eq!( simd_shuffle::<_, _, i32x4>(a, b, const { u32x4::from_array([3u32, 1, 0, 2]) }), a, @@ -628,10 +627,6 @@ fn simd_intrinsics() { simd_shuffle_generic::<_, i32x4, { &[7, 5, 4, 6] }>(a, b), i32x4::from_array([4, 2, 1, 10]), ); - assert_eq!( - simd_shuffle::<_, _, i32x4>(a, b, const { [7u32, 5, 4, 6] }), - i32x4::from_array([4, 2, 1, 10]), - ); assert_eq!( simd_shuffle::<_, _, i32x4>(a, b, const { u32x4::from_array([7u32, 5, 4, 6]) }), i32x4::from_array([4, 2, 1, 10]), diff --git a/src/tools/tidy/src/issues.txt b/src/tools/tidy/src/issues.txt index 4627079a647..8197a1bd859 100644 --- a/src/tools/tidy/src/issues.txt +++ b/src/tools/tidy/src/issues.txt @@ -675,8 +675,6 @@ ui/consts/auxiliary/issue-17718-aux.rs ui/consts/auxiliary/issue-63226.rs ui/consts/const-eval/issue-100878.rs ui/consts/const-eval/issue-104390.rs -ui/consts/const-eval/issue-114994-fail.rs -ui/consts/const-eval/issue-114994.rs ui/consts/const-eval/issue-43197.rs ui/consts/const-eval/issue-44578.rs ui/consts/const-eval/issue-47971.rs diff --git a/tests/assembly/small_data_threshold.rs b/tests/assembly/small_data_threshold.rs index b0c0a63ca49..d3ba144600e 100644 --- a/tests/assembly/small_data_threshold.rs +++ b/tests/assembly/small_data_threshold.rs @@ -58,7 +58,7 @@ static mut Z: u64 = 0; // Currently, only MIPS and RISCV successfully put any objects in the small data // sections so the U/V/W/X tests are skipped on Hexagon and M68K -//@ RISCV: .section .sdata, +//@ RISCV: .section .sdata //@ RISCV-NOT: .section //@ RISCV: U: //@ RISCV: .section .sbss @@ -71,7 +71,7 @@ static mut Z: u64 = 0; //@ RISCV-NOT: .section //@ RISCV: X: -//@ MIPS: .section .sdata, +//@ MIPS: .section .sdata //@ MIPS-NOT: .section //@ MIPS: U: //@ MIPS: .section .sbss diff --git a/tests/codegen/clone_as_copy.rs b/tests/codegen/clone_as_copy.rs new file mode 100644 index 00000000000..36a59ae56b7 --- /dev/null +++ b/tests/codegen/clone_as_copy.rs @@ -0,0 +1,40 @@ +//@ revisions: DEBUGINFO NODEBUGINFO +//@ compile-flags: -O -Cno-prepopulate-passes +//@ [DEBUGINFO] compile-flags: -Cdebuginfo=full + +// From https://github.com/rust-lang/rust/issues/128081. +// Ensure that we only generate a memcpy instruction. + +#![crate_type = "lib"] + +#[derive(Clone)] +struct SubCloneAndCopy { + v1: u32, + v2: u32, +} + +#[derive(Clone)] +struct CloneOnly { + v1: u8, + v2: u8, + v3: u8, + v4: u8, + v5: u8, + v6: u8, + v7: u8, + v8: u8, + v9: u8, + v_sub: SubCloneAndCopy, + v_large: [u8; 256], +} + +// CHECK-LABEL: define {{.*}}@clone_only( +#[no_mangle] +pub fn clone_only(v: &CloneOnly) -> CloneOnly { + // CHECK-NOT: call {{.*}}clone + // CHECK-NOT: store i8 + // CHECK-NOT: store i32 + // CHECK: call void @llvm.memcpy + // CHECK-NEXT: ret void + v.clone() +} diff --git a/tests/codegen/enum/unreachable_enum_default_branch.rs b/tests/codegen/enum/unreachable_enum_default_branch.rs index 81a258f2722..76a92496c07 100644 --- a/tests/codegen/enum/unreachable_enum_default_branch.rs +++ b/tests/codegen/enum/unreachable_enum_default_branch.rs @@ -28,11 +28,13 @@ pub fn implicit_match(x: Int) -> bool { // The code is from https://github.com/rust-lang/rust/issues/110097. // We expect it to generate the same optimized code as a full match. // CHECK-LABEL: @if_let( -// CHECK-NEXT: start: +// CHECK: start: +// CHECK-NOT: zext +// CHECK: select // CHECK-NEXT: insertvalue // CHECK-NEXT: insertvalue // CHECK-NEXT: ret #[no_mangle] pub fn if_let(val: Result) -> Result { - if let Ok(x) = val { Ok(x) } else { Err(()) } + if let Ok(x) = val { Ok(x * 2) } else { Err(()) } } diff --git a/tests/codegen/try_question_mark_nop.rs b/tests/codegen/try_question_mark_nop.rs index c23f41f5467..321067d1b90 100644 --- a/tests/codegen/try_question_mark_nop.rs +++ b/tests/codegen/try_question_mark_nop.rs @@ -1,5 +1,7 @@ //@ compile-flags: -O -Z merge-functions=disabled --edition=2021 //@ only-x86_64 +// FIXME: Remove the `min-llvm-version`. +//@ min-llvm-version: 19 #![crate_type = "lib"] #![feature(try_blocks)] @@ -7,11 +9,14 @@ use std::ops::ControlFlow::{self, Break, Continue}; use std::ptr::NonNull; +// FIXME: The `trunc` and `select` instructions can be eliminated. // CHECK-LABEL: @option_nop_match_32 #[no_mangle] pub fn option_nop_match_32(x: Option) -> Option { // CHECK: start: - // CHECK-NEXT: insertvalue { i32, i32 } + // CHECK-NEXT: [[TRUNC:%.*]] = trunc nuw i32 %0 to i1 + // CHECK-NEXT: [[FIRST:%.*]] = select i1 [[TRUNC]], i32 %0 + // CHECK-NEXT: insertvalue { i32, i32 } poison, i32 [[FIRST]] // CHECK-NEXT: insertvalue { i32, i32 } // CHECK-NEXT: ret { i32, i32 } match x { diff --git a/tests/coverage/async.cov-map b/tests/coverage/async.cov-map index 1ba165f1e49..43b497a1d3f 100644 --- a/tests/coverage/async.cov-map +++ b/tests/coverage/async.cov-map @@ -1,103 +1,103 @@ Function name: async::c -Raw bytes (9): 0x[01, 01, 00, 01, 01, 09, 01, 00, 19] +Raw bytes (9): 0x[01, 01, 00, 01, 01, 0c, 01, 00, 19] Number of files: 1 - file 0 => global file 1 Number of expressions: 0 Number of file 0 mappings: 1 -- Code(Counter(0)) at (prev + 9, 1) to (start + 0, 25) +- Code(Counter(0)) at (prev + 12, 1) to (start + 0, 25) Function name: async::c::{closure#0} -Raw bytes (26): 0x[01, 01, 01, 01, 05, 04, 01, 09, 19, 01, 0e, 05, 02, 09, 00, 0a, 02, 02, 09, 00, 0a, 01, 02, 01, 00, 02] +Raw bytes (26): 0x[01, 01, 01, 01, 05, 04, 01, 0c, 19, 01, 0e, 05, 02, 09, 00, 0a, 02, 02, 09, 00, 0a, 01, 02, 01, 00, 02] 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 + 9, 25) to (start + 1, 14) +- Code(Counter(0)) at (prev + 12, 25) to (start + 1, 14) - Code(Counter(1)) at (prev + 2, 9) to (start + 0, 10) - Code(Expression(0, Sub)) at (prev + 2, 9) to (start + 0, 10) = (c0 - c1) - Code(Counter(0)) at (prev + 2, 1) to (start + 0, 2) Function name: async::d -Raw bytes (9): 0x[01, 01, 00, 01, 01, 11, 01, 00, 14] +Raw bytes (9): 0x[01, 01, 00, 01, 01, 14, 01, 00, 14] Number of files: 1 - file 0 => global file 1 Number of expressions: 0 Number of file 0 mappings: 1 -- Code(Counter(0)) at (prev + 17, 1) to (start + 0, 20) +- Code(Counter(0)) at (prev + 20, 1) to (start + 0, 20) Function name: async::d::{closure#0} -Raw bytes (9): 0x[01, 01, 00, 01, 01, 11, 14, 00, 19] +Raw bytes (9): 0x[01, 01, 00, 01, 01, 14, 14, 00, 19] Number of files: 1 - file 0 => global file 1 Number of expressions: 0 Number of file 0 mappings: 1 -- Code(Counter(0)) at (prev + 17, 20) to (start + 0, 25) +- Code(Counter(0)) at (prev + 20, 20) to (start + 0, 25) Function name: async::e (unused) -Raw bytes (9): 0x[01, 01, 00, 01, 00, 13, 01, 00, 14] +Raw bytes (9): 0x[01, 01, 00, 01, 00, 16, 01, 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, 1) to (start + 0, 20) +- Code(Zero) at (prev + 22, 1) to (start + 0, 20) Function name: async::e::{closure#0} (unused) -Raw bytes (9): 0x[01, 01, 00, 01, 00, 13, 14, 00, 19] +Raw bytes (9): 0x[01, 01, 00, 01, 00, 16, 14, 00, 19] Number of files: 1 - file 0 => global file 1 Number of expressions: 0 Number of file 0 mappings: 1 -- Code(Zero) at (prev + 19, 20) to (start + 0, 25) +- Code(Zero) at (prev + 22, 20) to (start + 0, 25) Function name: async::f -Raw bytes (9): 0x[01, 01, 00, 01, 01, 15, 01, 00, 14] +Raw bytes (9): 0x[01, 01, 00, 01, 01, 18, 01, 00, 14] Number of files: 1 - file 0 => global file 1 Number of expressions: 0 Number of file 0 mappings: 1 -- Code(Counter(0)) at (prev + 21, 1) to (start + 0, 20) +- Code(Counter(0)) at (prev + 24, 1) to (start + 0, 20) Function name: async::f::{closure#0} -Raw bytes (9): 0x[01, 01, 00, 01, 01, 15, 14, 00, 19] +Raw bytes (9): 0x[01, 01, 00, 01, 01, 18, 14, 00, 19] Number of files: 1 - file 0 => global file 1 Number of expressions: 0 Number of file 0 mappings: 1 -- Code(Counter(0)) at (prev + 21, 20) to (start + 0, 25) +- Code(Counter(0)) at (prev + 24, 20) to (start + 0, 25) Function name: async::foo (unused) -Raw bytes (9): 0x[01, 01, 00, 01, 00, 17, 01, 00, 1e] +Raw bytes (9): 0x[01, 01, 00, 01, 00, 1a, 01, 00, 1e] Number of files: 1 - file 0 => global file 1 Number of expressions: 0 Number of file 0 mappings: 1 -- Code(Zero) at (prev + 23, 1) to (start + 0, 30) +- Code(Zero) at (prev + 26, 1) to (start + 0, 30) Function name: async::foo::{closure#0} (unused) -Raw bytes (9): 0x[01, 01, 00, 01, 00, 17, 1e, 00, 2d] +Raw bytes (9): 0x[01, 01, 00, 01, 00, 1a, 1e, 00, 2d] Number of files: 1 - file 0 => global file 1 Number of expressions: 0 Number of file 0 mappings: 1 -- Code(Zero) at (prev + 23, 30) to (start + 0, 45) +- Code(Zero) at (prev + 26, 30) to (start + 0, 45) Function name: async::g -Raw bytes (9): 0x[01, 01, 00, 01, 01, 19, 01, 00, 17] +Raw bytes (9): 0x[01, 01, 00, 01, 01, 1c, 01, 00, 17] Number of files: 1 - file 0 => global file 1 Number of expressions: 0 Number of file 0 mappings: 1 -- Code(Counter(0)) at (prev + 25, 1) to (start + 0, 23) +- Code(Counter(0)) at (prev + 28, 1) to (start + 0, 23) Function name: async::g::{closure#0} (unused) -Raw bytes (59): 0x[01, 01, 00, 0b, 00, 19, 17, 01, 0c, 00, 02, 09, 00, 0a, 00, 00, 0e, 00, 17, 00, 00, 1b, 00, 1c, 00, 00, 20, 00, 22, 00, 01, 09, 00, 0a, 00, 00, 0e, 00, 17, 00, 00, 1b, 00, 1c, 00, 00, 20, 00, 22, 00, 01, 0e, 00, 10, 00, 02, 01, 00, 02] +Raw bytes (59): 0x[01, 01, 00, 0b, 00, 1c, 17, 01, 0c, 00, 02, 09, 00, 0a, 00, 00, 0e, 00, 17, 00, 00, 1b, 00, 1c, 00, 00, 20, 00, 22, 00, 01, 09, 00, 0a, 00, 00, 0e, 00, 17, 00, 00, 1b, 00, 1c, 00, 00, 20, 00, 22, 00, 01, 0e, 00, 10, 00, 02, 01, 00, 02] Number of files: 1 - file 0 => global file 1 Number of expressions: 0 Number of file 0 mappings: 11 -- Code(Zero) at (prev + 25, 23) to (start + 1, 12) +- Code(Zero) at (prev + 28, 23) to (start + 1, 12) - Code(Zero) at (prev + 2, 9) to (start + 0, 10) - Code(Zero) at (prev + 0, 14) to (start + 0, 23) - Code(Zero) at (prev + 0, 27) to (start + 0, 28) @@ -110,20 +110,20 @@ Number of file 0 mappings: 11 - Code(Zero) at (prev + 2, 1) to (start + 0, 2) Function name: async::h -Raw bytes (9): 0x[01, 01, 00, 01, 01, 21, 01, 00, 16] +Raw bytes (9): 0x[01, 01, 00, 01, 01, 24, 01, 00, 16] Number of files: 1 - file 0 => global file 1 Number of expressions: 0 Number of file 0 mappings: 1 -- Code(Counter(0)) at (prev + 33, 1) to (start + 0, 22) +- Code(Counter(0)) at (prev + 36, 1) to (start + 0, 22) Function name: async::h::{closure#0} (unused) -Raw bytes (39): 0x[01, 01, 00, 07, 00, 21, 16, 03, 0c, 00, 04, 09, 00, 0a, 00, 00, 0e, 00, 19, 00, 00, 1a, 00, 1b, 00, 00, 20, 00, 22, 00, 01, 0e, 00, 10, 00, 02, 01, 00, 02] +Raw bytes (39): 0x[01, 01, 00, 07, 00, 24, 16, 03, 0c, 00, 04, 09, 00, 0a, 00, 00, 0e, 00, 19, 00, 00, 1a, 00, 1b, 00, 00, 20, 00, 22, 00, 01, 0e, 00, 10, 00, 02, 01, 00, 02] Number of files: 1 - file 0 => global file 1 Number of expressions: 0 Number of file 0 mappings: 7 -- Code(Zero) at (prev + 33, 22) to (start + 3, 12) +- Code(Zero) at (prev + 36, 22) to (start + 3, 12) - Code(Zero) at (prev + 4, 9) to (start + 0, 10) - Code(Zero) at (prev + 0, 14) to (start + 0, 25) - Code(Zero) at (prev + 0, 26) to (start + 0, 27) @@ -132,22 +132,22 @@ Number of file 0 mappings: 7 - Code(Zero) at (prev + 2, 1) to (start + 0, 2) Function name: async::i -Raw bytes (9): 0x[01, 01, 00, 01, 01, 2a, 01, 00, 13] +Raw bytes (9): 0x[01, 01, 00, 01, 01, 2d, 01, 00, 13] Number of files: 1 - file 0 => global file 1 Number of expressions: 0 Number of file 0 mappings: 1 -- Code(Counter(0)) at (prev + 42, 1) to (start + 0, 19) +- Code(Counter(0)) at (prev + 45, 1) to (start + 0, 19) Function name: async::i::{closure#0} -Raw bytes (63): 0x[01, 01, 02, 07, 19, 11, 15, 0b, 01, 2a, 13, 04, 0c, 09, 05, 09, 00, 0a, 01, 00, 0e, 00, 18, 05, 00, 1c, 00, 21, 09, 00, 27, 00, 30, 15, 01, 09, 00, 0a, 0d, 00, 0e, 00, 17, 1d, 00, 1b, 00, 20, 15, 00, 24, 00, 26, 19, 01, 0e, 00, 10, 03, 02, 01, 00, 02] +Raw bytes (63): 0x[01, 01, 02, 07, 19, 11, 15, 0b, 01, 2d, 13, 04, 0c, 09, 05, 09, 00, 0a, 01, 00, 0e, 00, 18, 05, 00, 1c, 00, 21, 09, 00, 27, 00, 30, 15, 01, 09, 00, 0a, 0d, 00, 0e, 00, 17, 1d, 00, 1b, 00, 20, 15, 00, 24, 00, 26, 19, 01, 0e, 00, 10, 03, 02, 01, 00, 02] Number of files: 1 - file 0 => global file 1 Number of expressions: 2 - expression 0 operands: lhs = Expression(1, Add), rhs = Counter(6) - expression 1 operands: lhs = Counter(4), rhs = Counter(5) Number of file 0 mappings: 11 -- Code(Counter(0)) at (prev + 42, 19) to (start + 4, 12) +- Code(Counter(0)) at (prev + 45, 19) to (start + 4, 12) - Code(Counter(2)) at (prev + 5, 9) to (start + 0, 10) - Code(Counter(0)) at (prev + 0, 14) to (start + 0, 24) - Code(Counter(1)) at (prev + 0, 28) to (start + 0, 33) @@ -161,14 +161,14 @@ Number of file 0 mappings: 11 = ((c4 + c5) + c6) Function name: async::j -Raw bytes (58): 0x[01, 01, 02, 07, 0d, 05, 09, 0a, 01, 35, 01, 00, 0d, 01, 0b, 0b, 00, 0c, 05, 01, 09, 00, 0a, 01, 00, 0e, 00, 1b, 05, 00, 1f, 00, 27, 09, 01, 09, 00, 0a, 11, 00, 0e, 00, 1a, 09, 00, 1e, 00, 20, 0d, 01, 0e, 00, 10, 03, 02, 01, 00, 02] +Raw bytes (58): 0x[01, 01, 02, 07, 0d, 05, 09, 0a, 01, 38, 01, 00, 0d, 01, 0b, 0b, 00, 0c, 05, 01, 09, 00, 0a, 01, 00, 0e, 00, 1b, 05, 00, 1f, 00, 27, 09, 01, 09, 00, 0a, 11, 00, 0e, 00, 1a, 09, 00, 1e, 00, 20, 0d, 01, 0e, 00, 10, 03, 02, 01, 00, 02] Number of files: 1 - file 0 => global file 1 Number of expressions: 2 - expression 0 operands: lhs = Expression(1, Add), rhs = Counter(3) - expression 1 operands: lhs = Counter(1), rhs = Counter(2) Number of file 0 mappings: 10 -- Code(Counter(0)) at (prev + 53, 1) to (start + 0, 13) +- Code(Counter(0)) at (prev + 56, 1) to (start + 0, 13) - Code(Counter(0)) at (prev + 11, 11) to (start + 0, 12) - Code(Counter(1)) at (prev + 1, 9) to (start + 0, 10) - Code(Counter(0)) at (prev + 0, 14) to (start + 0, 27) @@ -181,48 +181,48 @@ Number of file 0 mappings: 10 = ((c1 + c2) + c3) Function name: async::j::c -Raw bytes (26): 0x[01, 01, 01, 01, 05, 04, 01, 37, 05, 01, 12, 05, 02, 0d, 00, 0e, 02, 02, 0d, 00, 0e, 01, 02, 05, 00, 06] +Raw bytes (26): 0x[01, 01, 01, 01, 05, 04, 01, 3a, 05, 01, 12, 05, 02, 0d, 00, 0e, 02, 02, 0d, 00, 0e, 01, 02, 05, 00, 06] 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 + 55, 5) to (start + 1, 18) +- Code(Counter(0)) at (prev + 58, 5) to (start + 1, 18) - Code(Counter(1)) at (prev + 2, 13) to (start + 0, 14) - Code(Expression(0, Sub)) at (prev + 2, 13) to (start + 0, 14) = (c0 - c1) - Code(Counter(0)) at (prev + 2, 5) to (start + 0, 6) Function name: async::j::d -Raw bytes (9): 0x[01, 01, 00, 01, 01, 3e, 05, 00, 17] +Raw bytes (9): 0x[01, 01, 00, 01, 01, 41, 05, 00, 17] Number of files: 1 - file 0 => global file 1 Number of expressions: 0 Number of file 0 mappings: 1 -- Code(Counter(0)) at (prev + 62, 5) to (start + 0, 23) +- Code(Counter(0)) at (prev + 65, 5) to (start + 0, 23) Function name: async::j::f -Raw bytes (9): 0x[01, 01, 00, 01, 01, 3f, 05, 00, 17] +Raw bytes (9): 0x[01, 01, 00, 01, 01, 42, 05, 00, 17] Number of files: 1 - file 0 => global file 1 Number of expressions: 0 Number of file 0 mappings: 1 -- Code(Counter(0)) at (prev + 63, 5) to (start + 0, 23) +- Code(Counter(0)) at (prev + 66, 5) to (start + 0, 23) Function name: async::k (unused) -Raw bytes (29): 0x[01, 01, 00, 05, 00, 47, 01, 01, 0c, 00, 02, 0e, 00, 10, 00, 01, 0e, 00, 10, 00, 01, 0e, 00, 10, 00, 02, 01, 00, 02] +Raw bytes (29): 0x[01, 01, 00, 05, 00, 4a, 01, 01, 0c, 00, 02, 0e, 00, 10, 00, 01, 0e, 00, 10, 00, 01, 0e, 00, 10, 00, 02, 01, 00, 02] Number of files: 1 - file 0 => global file 1 Number of expressions: 0 Number of file 0 mappings: 5 -- Code(Zero) at (prev + 71, 1) to (start + 1, 12) +- Code(Zero) at (prev + 74, 1) to (start + 1, 12) - Code(Zero) at (prev + 2, 14) to (start + 0, 16) - Code(Zero) at (prev + 1, 14) to (start + 0, 16) - Code(Zero) at (prev + 1, 14) to (start + 0, 16) - Code(Zero) at (prev + 2, 1) to (start + 0, 2) Function name: async::l -Raw bytes (37): 0x[01, 01, 04, 01, 07, 05, 09, 0f, 02, 09, 05, 05, 01, 4f, 01, 01, 0c, 02, 02, 0e, 00, 10, 05, 01, 0e, 00, 10, 09, 01, 0e, 00, 10, 0b, 02, 01, 00, 02] +Raw bytes (37): 0x[01, 01, 04, 01, 07, 05, 09, 0f, 02, 09, 05, 05, 01, 52, 01, 01, 0c, 02, 02, 0e, 00, 10, 05, 01, 0e, 00, 10, 09, 01, 0e, 00, 10, 0b, 02, 01, 00, 02] Number of files: 1 - file 0 => global file 1 Number of expressions: 4 @@ -231,7 +231,7 @@ Number of expressions: 4 - expression 2 operands: lhs = Expression(3, Add), rhs = Expression(0, Sub) - expression 3 operands: lhs = Counter(2), rhs = Counter(1) Number of file 0 mappings: 5 -- Code(Counter(0)) at (prev + 79, 1) to (start + 1, 12) +- Code(Counter(0)) at (prev + 82, 1) to (start + 1, 12) - Code(Expression(0, Sub)) at (prev + 2, 14) to (start + 0, 16) = (c0 - (c1 + c2)) - Code(Counter(1)) at (prev + 1, 14) to (start + 0, 16) @@ -240,26 +240,26 @@ Number of file 0 mappings: 5 = ((c2 + c1) + (c0 - (c1 + c2))) Function name: async::m -Raw bytes (9): 0x[01, 01, 00, 01, 01, 57, 01, 00, 19] +Raw bytes (9): 0x[01, 01, 00, 01, 01, 5a, 01, 00, 19] Number of files: 1 - file 0 => global file 1 Number of expressions: 0 Number of file 0 mappings: 1 -- Code(Counter(0)) at (prev + 87, 1) to (start + 0, 25) +- Code(Counter(0)) at (prev + 90, 1) to (start + 0, 25) Function name: async::m::{closure#0} (unused) -Raw bytes (9): 0x[01, 01, 00, 01, 00, 57, 19, 00, 22] +Raw bytes (9): 0x[01, 01, 00, 01, 00, 5a, 19, 00, 22] Number of files: 1 - file 0 => global file 1 Number of expressions: 0 Number of file 0 mappings: 1 -- Code(Zero) at (prev + 87, 25) to (start + 0, 34) +- Code(Zero) at (prev + 90, 25) to (start + 0, 34) Function name: async::main -Raw bytes (9): 0x[01, 01, 00, 01, 01, 59, 01, 08, 02] +Raw bytes (9): 0x[01, 01, 00, 01, 01, 5c, 01, 08, 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 + 89, 1) to (start + 8, 2) +- Code(Counter(0)) at (prev + 92, 1) to (start + 8, 2) diff --git a/tests/coverage/async.coverage b/tests/coverage/async.coverage index 995674257c4..429fb112f33 100644 --- a/tests/coverage/async.coverage +++ b/tests/coverage/async.coverage @@ -6,6 +6,9 @@ LL| |//@ edition: 2018 LL| |//@ compile-flags: -Copt-level=1 LL| | + LL| |//@ aux-build: executor.rs + LL| |extern crate executor; + LL| | LL| 1|async fn c(x: u8) -> u8 { LL| 1| if x == 8 { LL| 1| 1 @@ -100,22 +103,4 @@ LL| 1| let _ = m(5); LL| 1| executor::block_on(future.as_mut()); LL| 1|} - LL| | - LL| |mod executor { - LL| | use core::future::Future; - LL| | use core::pin::pin; - LL| | use core::task::{Context, Poll, Waker}; - LL| | - LL| | #[coverage(off)] - LL| | pub fn block_on(mut future: F) -> F::Output { - LL| | let mut future = pin!(future); - LL| | let mut context = Context::from_waker(Waker::noop()); - LL| | - LL| | loop { - LL| | if let Poll::Ready(val) = future.as_mut().poll(&mut context) { - LL| | break val; - LL| | } - LL| | } - LL| | } - LL| |} diff --git a/tests/coverage/async.rs b/tests/coverage/async.rs index 7e6ad761ecd..a7f3c7cec41 100644 --- a/tests/coverage/async.rs +++ b/tests/coverage/async.rs @@ -6,6 +6,9 @@ //@ edition: 2018 //@ compile-flags: -Copt-level=1 +//@ aux-build: executor.rs +extern crate executor; + async fn c(x: u8) -> u8 { if x == 8 { 1 @@ -95,21 +98,3 @@ fn main() { let _ = m(5); executor::block_on(future.as_mut()); } - -mod executor { - use core::future::Future; - use core::pin::pin; - use core::task::{Context, Poll, Waker}; - - #[coverage(off)] - pub fn block_on(mut future: F) -> F::Output { - let mut future = pin!(future); - let mut context = Context::from_waker(Waker::noop()); - - loop { - if let Poll::Ready(val) = future.as_mut().poll(&mut context) { - break val; - } - } - } -} diff --git a/tests/coverage/async2.cov-map b/tests/coverage/async2.cov-map index e39a1d7dd2f..3816401ac63 100644 --- a/tests/coverage/async2.cov-map +++ b/tests/coverage/async2.cov-map @@ -1,53 +1,53 @@ Function name: async2::async_func -Raw bytes (9): 0x[01, 01, 00, 01, 01, 0d, 01, 00, 17] +Raw bytes (9): 0x[01, 01, 00, 01, 01, 10, 01, 00, 17] Number of files: 1 - file 0 => global file 1 Number of expressions: 0 Number of file 0 mappings: 1 -- Code(Counter(0)) at (prev + 13, 1) to (start + 0, 23) +- Code(Counter(0)) at (prev + 16, 1) to (start + 0, 23) Function name: async2::async_func::{closure#0} -Raw bytes (24): 0x[01, 01, 00, 04, 01, 0d, 17, 03, 09, 05, 03, 0a, 02, 06, 00, 02, 06, 00, 07, 01, 01, 01, 00, 02] +Raw bytes (24): 0x[01, 01, 00, 04, 01, 10, 17, 03, 09, 05, 03, 0a, 02, 06, 00, 02, 06, 00, 07, 01, 01, 01, 00, 02] Number of files: 1 - file 0 => global file 1 Number of expressions: 0 Number of file 0 mappings: 4 -- Code(Counter(0)) at (prev + 13, 23) to (start + 3, 9) +- Code(Counter(0)) at (prev + 16, 23) to (start + 3, 9) - Code(Counter(1)) at (prev + 3, 10) to (start + 2, 6) - Code(Zero) at (prev + 2, 6) to (start + 0, 7) - Code(Counter(0)) at (prev + 1, 1) to (start + 0, 2) Function name: async2::async_func_just_println -Raw bytes (9): 0x[01, 01, 00, 01, 01, 15, 01, 00, 24] +Raw bytes (9): 0x[01, 01, 00, 01, 01, 18, 01, 00, 24] Number of files: 1 - file 0 => global file 1 Number of expressions: 0 Number of file 0 mappings: 1 -- Code(Counter(0)) at (prev + 21, 1) to (start + 0, 36) +- Code(Counter(0)) at (prev + 24, 1) to (start + 0, 36) Function name: async2::async_func_just_println::{closure#0} -Raw bytes (9): 0x[01, 01, 00, 01, 01, 15, 24, 02, 02] +Raw bytes (9): 0x[01, 01, 00, 01, 01, 18, 24, 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 + 21, 36) to (start + 2, 2) +- Code(Counter(0)) at (prev + 24, 36) to (start + 2, 2) Function name: async2::main -Raw bytes (9): 0x[01, 01, 00, 01, 01, 19, 01, 07, 02] +Raw bytes (9): 0x[01, 01, 00, 01, 01, 1c, 01, 07, 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 + 25, 1) to (start + 7, 2) +- Code(Counter(0)) at (prev + 28, 1) to (start + 7, 2) Function name: async2::non_async_func -Raw bytes (24): 0x[01, 01, 00, 04, 01, 05, 01, 03, 09, 05, 03, 0a, 02, 06, 00, 02, 06, 00, 07, 01, 01, 01, 00, 02] +Raw bytes (24): 0x[01, 01, 00, 04, 01, 08, 01, 03, 09, 05, 03, 0a, 02, 06, 00, 02, 06, 00, 07, 01, 01, 01, 00, 02] Number of files: 1 - file 0 => global file 1 Number of expressions: 0 Number of file 0 mappings: 4 -- Code(Counter(0)) at (prev + 5, 1) to (start + 3, 9) +- Code(Counter(0)) at (prev + 8, 1) to (start + 3, 9) - Code(Counter(1)) at (prev + 3, 10) to (start + 2, 6) - Code(Zero) at (prev + 2, 6) to (start + 0, 7) - Code(Counter(0)) at (prev + 1, 1) to (start + 0, 2) diff --git a/tests/coverage/async2.coverage b/tests/coverage/async2.coverage index bd5b701491b..ed9bc4c239d 100644 --- a/tests/coverage/async2.coverage +++ b/tests/coverage/async2.coverage @@ -2,6 +2,9 @@ LL| |#![feature(noop_waker)] LL| |//@ edition: 2018 LL| | + LL| |//@ aux-build: executor.rs + LL| |extern crate executor; + LL| | LL| 1|fn non_async_func() { LL| 1| println!("non_async_func was covered"); LL| 1| let b = true; @@ -32,22 +35,4 @@ LL| 1| executor::block_on(async_func()); LL| 1| executor::block_on(async_func_just_println()); LL| 1|} - LL| | - LL| |mod executor { - LL| | use core::future::Future; - LL| | use core::pin::pin; - LL| | use core::task::{Context, Poll, Waker}; - LL| | - LL| | #[coverage(off)] - LL| | pub fn block_on(mut future: F) -> F::Output { - LL| | let mut future = pin!(future); - LL| | let mut context = Context::from_waker(Waker::noop()); - LL| | - LL| | loop { - LL| | if let Poll::Ready(val) = future.as_mut().poll(&mut context) { - LL| | break val; - LL| | } - LL| | } - LL| | } - LL| |} diff --git a/tests/coverage/async2.rs b/tests/coverage/async2.rs index 713c70d277a..f52c848f6f2 100644 --- a/tests/coverage/async2.rs +++ b/tests/coverage/async2.rs @@ -2,6 +2,9 @@ #![feature(noop_waker)] //@ edition: 2018 +//@ aux-build: executor.rs +extern crate executor; + fn non_async_func() { println!("non_async_func was covered"); let b = true; @@ -30,21 +33,3 @@ fn main() { executor::block_on(async_func()); executor::block_on(async_func_just_println()); } - -mod executor { - use core::future::Future; - use core::pin::pin; - use core::task::{Context, Poll, Waker}; - - #[coverage(off)] - pub fn block_on(mut future: F) -> F::Output { - let mut future = pin!(future); - let mut context = Context::from_waker(Waker::noop()); - - loop { - if let Poll::Ready(val) = future.as_mut().poll(&mut context) { - break val; - } - } - } -} diff --git a/tests/coverage/async_block.cov-map b/tests/coverage/async_block.cov-map index e54c15c0436..65f3d821f6e 100644 --- a/tests/coverage/async_block.cov-map +++ b/tests/coverage/async_block.cov-map @@ -1,11 +1,11 @@ Function name: async_block::main -Raw bytes (36): 0x[01, 01, 01, 01, 05, 06, 01, 05, 01, 00, 0b, 05, 01, 09, 00, 0a, 03, 00, 0e, 00, 13, 05, 00, 14, 01, 16, 05, 07, 0a, 02, 06, 01, 03, 01, 00, 02] +Raw bytes (36): 0x[01, 01, 01, 01, 05, 06, 01, 08, 01, 00, 0b, 05, 01, 09, 00, 0a, 03, 00, 0e, 00, 13, 05, 00, 14, 01, 16, 05, 07, 0a, 02, 06, 01, 03, 01, 00, 02] 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: 6 -- Code(Counter(0)) at (prev + 5, 1) to (start + 0, 11) +- Code(Counter(0)) at (prev + 8, 1) to (start + 0, 11) - Code(Counter(1)) at (prev + 1, 9) to (start + 0, 10) - Code(Expression(0, Add)) at (prev + 0, 14) to (start + 0, 19) = (c0 + c1) @@ -14,13 +14,13 @@ Number of file 0 mappings: 6 - Code(Counter(0)) at (prev + 3, 1) to (start + 0, 2) Function name: async_block::main::{closure#0} -Raw bytes (26): 0x[01, 01, 01, 01, 05, 04, 01, 07, 1c, 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, 0a, 1c, 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 + 7, 28) to (start + 1, 23) +- Code(Counter(0)) at (prev + 10, 28) 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/async_block.coverage b/tests/coverage/async_block.coverage index 7fd17bc51c3..d9be8480d80 100644 --- a/tests/coverage/async_block.coverage +++ b/tests/coverage/async_block.coverage @@ -2,6 +2,9 @@ LL| |#![feature(noop_waker)] LL| |//@ edition: 2021 LL| | + LL| |//@ aux-build: executor.rs + LL| |extern crate executor; + LL| | LL| 1|fn main() { LL| 17| for i in 0..16 { ^16 @@ -15,22 +18,4 @@ LL| 16| executor::block_on(future); LL| 16| } LL| 1|} - LL| | - LL| |mod executor { - LL| | use core::future::Future; - LL| | use core::pin::pin; - LL| | use core::task::{Context, Poll, Waker}; - LL| | - LL| | #[coverage(off)] - LL| | pub fn block_on(mut future: F) -> F::Output { - LL| | let mut future = pin!(future); - LL| | let mut context = Context::from_waker(Waker::noop()); - LL| | - LL| | loop { - LL| | if let Poll::Ready(val) = future.as_mut().poll(&mut context) { - LL| | break val; - LL| | } - LL| | } - LL| | } - LL| |} diff --git a/tests/coverage/async_block.rs b/tests/coverage/async_block.rs index a70dd747032..7ae8241aa77 100644 --- a/tests/coverage/async_block.rs +++ b/tests/coverage/async_block.rs @@ -2,6 +2,9 @@ #![feature(noop_waker)] //@ edition: 2021 +//@ aux-build: executor.rs +extern crate executor; + fn main() { for i in 0..16 { let future = async { @@ -14,21 +17,3 @@ fn main() { executor::block_on(future); } } - -mod executor { - use core::future::Future; - use core::pin::pin; - use core::task::{Context, Poll, Waker}; - - #[coverage(off)] - pub fn block_on(mut future: F) -> F::Output { - let mut future = pin!(future); - let mut context = Context::from_waker(Waker::noop()); - - loop { - if let Poll::Ready(val) = future.as_mut().poll(&mut context) { - break val; - } - } - } -} diff --git a/tests/coverage/auxiliary/executor.rs b/tests/coverage/auxiliary/executor.rs new file mode 100644 index 00000000000..fb07c8ce304 --- /dev/null +++ b/tests/coverage/auxiliary/executor.rs @@ -0,0 +1,19 @@ +#![feature(coverage_attribute, noop_waker)] +//@ edition: 2021 + +use core::future::Future; +use core::pin::pin; +use core::task::{Context, Poll, Waker}; + +/// Dummy "executor" that just repeatedly polls a future until it's ready. +#[coverage(off)] +pub fn block_on(mut future: F) -> F::Output { + let mut future = pin!(future); + let mut context = Context::from_waker(Waker::noop()); + + loop { + if let Poll::Ready(val) = future.as_mut().poll(&mut context) { + break val; + } + } +} diff --git a/tests/coverage/await_ready.cov-map b/tests/coverage/await_ready.cov-map index 0c9f2ae29a8..38c2cf7b2d3 100644 --- a/tests/coverage/await_ready.cov-map +++ b/tests/coverage/await_ready.cov-map @@ -1,25 +1,17 @@ Function name: await_ready::await_ready -Raw bytes (9): 0x[01, 01, 00, 01, 01, 0a, 01, 00, 1e] +Raw bytes (9): 0x[01, 01, 00, 01, 01, 0f, 01, 00, 1e] Number of files: 1 - file 0 => global file 1 Number of expressions: 0 Number of file 0 mappings: 1 -- Code(Counter(0)) at (prev + 10, 1) to (start + 0, 30) +- Code(Counter(0)) at (prev + 15, 1) to (start + 0, 30) Function name: await_ready::await_ready::{closure#0} -Raw bytes (14): 0x[01, 01, 00, 02, 01, 0a, 1e, 03, 0f, 05, 04, 01, 00, 02] +Raw bytes (14): 0x[01, 01, 00, 02, 01, 0f, 1e, 03, 0f, 05, 04, 01, 00, 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 + 10, 30) to (start + 3, 15) +- Code(Counter(0)) at (prev + 15, 30) to (start + 3, 15) - Code(Counter(1)) at (prev + 4, 1) to (start + 0, 2) -Function name: await_ready::main -Raw bytes (9): 0x[01, 01, 00, 01, 01, 10, 01, 03, 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 + 16, 1) to (start + 3, 2) - diff --git a/tests/coverage/await_ready.coverage b/tests/coverage/await_ready.coverage index 0075f09426e..7ab03e6d3de 100644 --- a/tests/coverage/await_ready.coverage +++ b/tests/coverage/await_ready.coverage @@ -1,38 +1,25 @@ LL| |#![feature(coverage_attribute)] - LL| |#![feature(custom_inner_attributes)] // for #![rustfmt::skip] LL| |#![feature(noop_waker)] - LL| |#![rustfmt::skip] + LL| |#![coverage(off)] LL| |//@ edition: 2021 LL| | - LL| |#[coverage(off)] - LL| |async fn ready() -> u8 { 1 } + LL| |//@ aux-build: executor.rs + LL| |extern crate executor; LL| | + LL| |async fn ready() -> u8 { + LL| | 1 + LL| |} + LL| | + LL| |#[coverage(on)] + LL| |#[rustfmt::skip] LL| 1|async fn await_ready() -> u8 { LL| 1| // await should be covered even if the function never yields LL| 1| ready() LL| 1| .await LL| 1|} LL| | - LL| 1|fn main() { - LL| 1| let mut future = Box::pin(await_ready()); - LL| 1| executor::block_on(future.as_mut()); - LL| 1|} - LL| | - LL| |mod executor { - LL| | use core::future::Future; - LL| | use core::pin::pin; - LL| | use core::task::{Context, Poll, Waker}; - LL| | - LL| | #[coverage(off)] - LL| | pub fn block_on(mut future: F) -> F::Output { - LL| | let mut future = pin!(future); - LL| | let mut context = Context::from_waker(Waker::noop()); - LL| | - LL| | loop { - LL| | if let Poll::Ready(val) = future.as_mut().poll(&mut context) { - LL| | break val; - LL| | } - LL| | } - LL| | } + LL| |fn main() { + LL| | let mut future = Box::pin(await_ready()); + LL| | executor::block_on(future.as_mut()); LL| |} diff --git a/tests/coverage/await_ready.rs b/tests/coverage/await_ready.rs index 9212a4ba705..27ee99d3989 100644 --- a/tests/coverage/await_ready.rs +++ b/tests/coverage/await_ready.rs @@ -1,12 +1,17 @@ #![feature(coverage_attribute)] -#![feature(custom_inner_attributes)] // for #![rustfmt::skip] #![feature(noop_waker)] -#![rustfmt::skip] +#![coverage(off)] //@ edition: 2021 -#[coverage(off)] -async fn ready() -> u8 { 1 } +//@ aux-build: executor.rs +extern crate executor; +async fn ready() -> u8 { + 1 +} + +#[coverage(on)] +#[rustfmt::skip] async fn await_ready() -> u8 { // await should be covered even if the function never yields ready() @@ -17,21 +22,3 @@ fn main() { let mut future = Box::pin(await_ready()); executor::block_on(future.as_mut()); } - -mod executor { - use core::future::Future; - use core::pin::pin; - use core::task::{Context, Poll, Waker}; - - #[coverage(off)] - pub fn block_on(mut future: F) -> F::Output { - let mut future = pin!(future); - let mut context = Context::from_waker(Waker::noop()); - - loop { - if let Poll::Ready(val) = future.as_mut().poll(&mut context) { - break val; - } - } - } -} diff --git a/tests/coverage/closure_macro_async.cov-map b/tests/coverage/closure_macro_async.cov-map index 1286d663bd4..4d0597f58bf 100644 --- a/tests/coverage/closure_macro_async.cov-map +++ b/tests/coverage/closure_macro_async.cov-map @@ -1,27 +1,27 @@ Function name: closure_macro_async::load_configuration_files -Raw bytes (9): 0x[01, 01, 00, 01, 01, 1f, 01, 02, 02] +Raw bytes (9): 0x[01, 01, 00, 01, 01, 22, 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 + 31, 1) to (start + 2, 2) +- Code(Counter(0)) at (prev + 34, 1) to (start + 2, 2) Function name: closure_macro_async::test -Raw bytes (9): 0x[01, 01, 00, 01, 01, 23, 01, 00, 2b] +Raw bytes (9): 0x[01, 01, 00, 01, 01, 26, 01, 00, 2b] Number of files: 1 - file 0 => global file 1 Number of expressions: 0 Number of file 0 mappings: 1 -- Code(Counter(0)) at (prev + 35, 1) to (start + 0, 43) +- Code(Counter(0)) at (prev + 38, 1) to (start + 0, 43) Function name: closure_macro_async::test::{closure#0} -Raw bytes (36): 0x[01, 01, 01, 01, 05, 06, 01, 23, 2b, 01, 21, 02, 02, 09, 00, 0f, 01, 00, 12, 00, 54, 05, 00, 54, 00, 55, 02, 02, 09, 02, 0b, 01, 03, 01, 00, 02] +Raw bytes (36): 0x[01, 01, 01, 01, 05, 06, 01, 26, 2b, 01, 21, 02, 02, 09, 00, 0f, 01, 00, 12, 00, 54, 05, 00, 54, 00, 55, 02, 02, 09, 02, 0b, 01, 03, 01, 00, 02] 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: 6 -- Code(Counter(0)) at (prev + 35, 43) to (start + 1, 33) +- Code(Counter(0)) at (prev + 38, 43) to (start + 1, 33) - Code(Expression(0, Sub)) at (prev + 2, 9) to (start + 0, 15) = (c0 - c1) - Code(Counter(0)) at (prev + 0, 18) to (start + 0, 84) @@ -31,7 +31,7 @@ Number of file 0 mappings: 6 - Code(Counter(0)) at (prev + 3, 1) to (start + 0, 2) Function name: closure_macro_async::test::{closure#0}::{closure#0} -Raw bytes (35): 0x[01, 01, 03, 01, 05, 05, 0b, 09, 00, 05, 01, 12, 1c, 03, 21, 05, 04, 11, 01, 27, 02, 03, 11, 00, 16, 00, 00, 17, 00, 1e, 07, 02, 09, 00, 0a] +Raw bytes (35): 0x[01, 01, 03, 01, 05, 05, 0b, 09, 00, 05, 01, 15, 1c, 03, 21, 05, 04, 11, 01, 27, 02, 03, 11, 00, 16, 00, 00, 17, 00, 1e, 07, 02, 09, 00, 0a] Number of files: 1 - file 0 => global file 1 Number of expressions: 3 @@ -39,7 +39,7 @@ Number of expressions: 3 - expression 1 operands: lhs = Counter(1), rhs = Expression(2, Add) - expression 2 operands: lhs = Counter(2), rhs = Zero Number of file 0 mappings: 5 -- Code(Counter(0)) at (prev + 18, 28) to (start + 3, 33) +- Code(Counter(0)) at (prev + 21, 28) to (start + 3, 33) - Code(Counter(1)) at (prev + 4, 17) to (start + 1, 39) - Code(Expression(0, Sub)) at (prev + 3, 17) to (start + 0, 22) = (c0 - c1) diff --git a/tests/coverage/closure_macro_async.coverage b/tests/coverage/closure_macro_async.coverage index 0557ce47d68..a8c72efac66 100644 --- a/tests/coverage/closure_macro_async.coverage +++ b/tests/coverage/closure_macro_async.coverage @@ -2,6 +2,9 @@ LL| |#![feature(noop_waker)] LL| |//@ edition: 2018 LL| | + LL| |//@ aux-build: executor.rs + LL| |extern crate executor; + LL| | LL| |macro_rules! bail { LL| | ($msg:literal $(,)?) => { LL| | if $msg.len() > 0 { @@ -46,22 +49,4 @@ LL| |fn main() { LL| | executor::block_on(test()).unwrap(); LL| |} - LL| | - LL| |mod executor { - LL| | use core::future::Future; - LL| | use core::pin::pin; - LL| | use core::task::{Context, Poll, Waker}; - LL| | - LL| | #[coverage(off)] - LL| | pub fn block_on(mut future: F) -> F::Output { - LL| | let mut future = pin!(future); - LL| | let mut context = Context::from_waker(Waker::noop()); - LL| | - LL| | loop { - LL| | if let Poll::Ready(val) = future.as_mut().poll(&mut context) { - LL| | break val; - LL| | } - LL| | } - LL| | } - LL| |} diff --git a/tests/coverage/closure_macro_async.rs b/tests/coverage/closure_macro_async.rs index 735214629b6..defd1b6d632 100644 --- a/tests/coverage/closure_macro_async.rs +++ b/tests/coverage/closure_macro_async.rs @@ -2,6 +2,9 @@ #![feature(noop_waker)] //@ edition: 2018 +//@ aux-build: executor.rs +extern crate executor; + macro_rules! bail { ($msg:literal $(,)?) => { if $msg.len() > 0 { @@ -45,21 +48,3 @@ pub async fn test() -> Result<(), String> { fn main() { executor::block_on(test()).unwrap(); } - -mod executor { - use core::future::Future; - use core::pin::pin; - use core::task::{Context, Poll, Waker}; - - #[coverage(off)] - pub fn block_on(mut future: F) -> F::Output { - let mut future = pin!(future); - let mut context = Context::from_waker(Waker::noop()); - - loop { - if let Poll::Ready(val) = future.as_mut().poll(&mut context) { - break val; - } - } - } -} diff --git a/tests/crashes/123693.rs b/tests/crashes/123693.rs deleted file mode 100644 index c3236322c6e..00000000000 --- a/tests/crashes/123693.rs +++ /dev/null @@ -1,22 +0,0 @@ -//@ known-bug: #123693 - -#![feature(transmutability)] - -mod assert { - use std::mem::{Assume, TransmuteFrom}; - - pub fn is_transmutable() - where - Dst: TransmuteFrom, - { - } -} - -enum Lopsided { - Smol(()), - Lorg(bool), -} - -fn should_pad_variants() { - assert::is_transmutable::(); -} diff --git a/tests/crashes/129262.rs b/tests/crashes/129262.rs new file mode 100644 index 00000000000..c430af35988 --- /dev/null +++ b/tests/crashes/129262.rs @@ -0,0 +1,21 @@ +//@ known-bug: rust-lang/rust#129262 +//@ compile-flags: -Zvalidate-mir --edition=2018 --crate-type=lib -Copt-level=3 + +#![feature(async_closure)] + +fn main() {} + +fn needs_fn_mut(mut x: impl FnMut() -> T) { + x(); +} + +fn hello(x: Ty) { + needs_fn_mut(async || { + x.hello(); + }); +} + +struct Ty; +impl Ty { + fn hello(self) {} +} diff --git a/tests/crashes/129850.rs b/tests/crashes/129850.rs new file mode 100644 index 00000000000..9c04805587a --- /dev/null +++ b/tests/crashes/129850.rs @@ -0,0 +1,9 @@ +//@ known-bug: rust-lang/rust#129850 + +pub trait Foo2 { + fn bar<'a: 'a>(&'a mut self) -> impl Sized + use<'static>; +} + +impl Foo2 for () { + fn bar<'a: 'a>(&'a mut self) -> impl Sized + 'a {} +} diff --git a/tests/crashes/130104.rs b/tests/crashes/130104.rs new file mode 100644 index 00000000000..0ffc21ad360 --- /dev/null +++ b/tests/crashes/130104.rs @@ -0,0 +1,6 @@ +//@ known-bug: rust-lang/rust#130104 + +fn main() { + let non_secure_function = + core::mem::transmute:: _, extern "C-cmse-nonsecure-call" fn() -> _>; +} diff --git a/tests/crashes/130310.rs b/tests/crashes/130310.rs new file mode 100644 index 00000000000..d59dd39983c --- /dev/null +++ b/tests/crashes/130310.rs @@ -0,0 +1,15 @@ +//@ known-bug: rust-lang/rust#130310 + +use std::marker::PhantomData; + +#[repr(C)] +struct A { + a: *const A>, + p: PhantomData, +} + +extern "C" { + fn f(a: *const A<()>); +} + +fn main() {} diff --git a/tests/crashes/130346.rs b/tests/crashes/130346.rs new file mode 100644 index 00000000000..ee25f0fcc5b --- /dev/null +++ b/tests/crashes/130346.rs @@ -0,0 +1,10 @@ +//@ known-bug: rust-lang/rust#130346 + +#![feature(non_lifetime_binders)] +#![allow(unused)] + +trait A: Iterator {} + +fn demo(x: &mut impl for A) { + let _: Option = x.next(); // Removing this line stops the ICE +} diff --git a/tests/crashes/130372-1.rs b/tests/crashes/130372-1.rs new file mode 100644 index 00000000000..5d58c14e7ab --- /dev/null +++ b/tests/crashes/130372-1.rs @@ -0,0 +1,9 @@ +//@ known-bug: rust-lang/rust#130372 + +pub fn variadic_fn(n: usize, mut args: ...) {} + +reuse variadic_fn; + +fn main() { + variadic_fn(); +} diff --git a/tests/crashes/130372-2.rs b/tests/crashes/130372-2.rs new file mode 100644 index 00000000000..46404191e32 --- /dev/null +++ b/tests/crashes/130372-2.rs @@ -0,0 +1,11 @@ +//@ known-bug: rust-lang/rust#130372 + +pub fn test_va_copy(_: u64, mut ap: ...) {} + +pub fn main() { + unsafe { + test_va_copy(); + + call(x); + } +} diff --git a/tests/crashes/130372-3.rs b/tests/crashes/130372-3.rs new file mode 100644 index 00000000000..6e1c57437c8 --- /dev/null +++ b/tests/crashes/130372-3.rs @@ -0,0 +1,7 @@ +//@ known-bug: rust-lang/rust#130372 + +fn bar() -> impl Fn() { + wrap() +} + +fn wrap(...: impl ...) -> impl Fn() {} diff --git a/tests/crashes/130399.rs b/tests/crashes/130399.rs new file mode 100644 index 00000000000..2248c8c0124 --- /dev/null +++ b/tests/crashes/130399.rs @@ -0,0 +1,5 @@ +//@ known-bug: rust-lang/rust#130399 + +fn elided(main: &()) -> impl Sized + use
{} + +fn main() {} diff --git a/tests/incremental/issue-61530.rs b/tests/incremental/issue-61530.rs index b4914dda11a..71ac39d0e03 100644 --- a/tests/incremental/issue-61530.rs +++ b/tests/incremental/issue-61530.rs @@ -9,9 +9,12 @@ extern "rust-intrinsic" { fn simd_shuffle(x: T, y: T, idx: I) -> U; } +#[repr(simd)] +struct SimdShuffleIdx([u32; LEN]); + fn main() { unsafe { - const IDX: [u32; 2] = [0, 0]; + const IDX: SimdShuffleIdx<2> = SimdShuffleIdx([0, 0]); let _: I32x2 = simd_shuffle(I32x2([1, 2]), I32x2([3, 4]), IDX); let _: I32x2 = simd_shuffle(I32x2([1, 2]), I32x2([3, 4]), IDX); } diff --git a/tests/mir-opt/gvn_clone.rs b/tests/mir-opt/gvn_clone.rs new file mode 100644 index 00000000000..08938c0e1b4 --- /dev/null +++ b/tests/mir-opt/gvn_clone.rs @@ -0,0 +1,17 @@ +//@ test-mir-pass: GVN +//@ compile-flags: -Zmir-enable-passes=+InstSimplify-before-inline + +// Check if we have transformed the default clone to copy in the specific pipeline. + +// EMIT_MIR gvn_clone.{impl#0}-clone.GVN.diff + +// CHECK-LABEL: ::clone( +// CHECK-NOT: = AllCopy { {{.*}} }; +// CHECK: _0 = copy (*_1); +// CHECK: return; +#[derive(Clone)] +struct AllCopy { + a: i32, + b: u64, + c: [i8; 3], +} diff --git a/tests/mir-opt/gvn_clone.{impl#0}-clone.GVN.diff b/tests/mir-opt/gvn_clone.{impl#0}-clone.GVN.diff new file mode 100644 index 00000000000..57b0980a0bd --- /dev/null +++ b/tests/mir-opt/gvn_clone.{impl#0}-clone.GVN.diff @@ -0,0 +1,71 @@ +- // MIR for `::clone` before GVN ++ // MIR for `::clone` after GVN + + fn ::clone(_1: &AllCopy) -> AllCopy { + debug self => _1; + let mut _0: AllCopy; + let mut _2: i32; + let mut _3: &i32; + let _4: &i32; + let mut _5: u64; + let mut _6: &u64; + let _7: &u64; + let mut _8: [i8; 3]; + let mut _9: &[i8; 3]; + let _10: &[i8; 3]; + + bb0: { + StorageLive(_2); + StorageLive(_3); +- StorageLive(_4); ++ nop; + _4 = &((*_1).0: i32); + _3 = copy _4; +- _2 = copy (*_3); ++ _2 = copy ((*_1).0: i32); + goto -> bb1; + } + + bb1: { + StorageDead(_3); + StorageLive(_5); + StorageLive(_6); +- StorageLive(_7); ++ nop; + _7 = &((*_1).1: u64); + _6 = copy _7; +- _5 = copy (*_6); ++ _5 = copy ((*_1).1: u64); + goto -> bb2; + } + + bb2: { + StorageDead(_6); + StorageLive(_8); + StorageLive(_9); +- StorageLive(_10); ++ nop; + _10 = &((*_1).2: [i8; 3]); + _9 = copy _10; +- _8 = copy (*_9); ++ _8 = copy ((*_1).2: [i8; 3]); + goto -> bb3; + } + + bb3: { + StorageDead(_9); +- _0 = AllCopy { a: move _2, b: move _5, c: move _8 }; ++ _0 = copy (*_1); + StorageDead(_8); + StorageDead(_5); + StorageDead(_2); +- StorageDead(_10); +- StorageDead(_7); +- StorageDead(_4); ++ nop; ++ nop; ++ nop; + return; + } + } + diff --git a/tests/mir-opt/gvn_copy_aggregate.all_copy.GVN.diff b/tests/mir-opt/gvn_copy_aggregate.all_copy.GVN.diff new file mode 100644 index 00000000000..f6345d5809f --- /dev/null +++ b/tests/mir-opt/gvn_copy_aggregate.all_copy.GVN.diff @@ -0,0 +1,53 @@ +- // MIR for `all_copy` before GVN ++ // MIR for `all_copy` after GVN + + fn all_copy(_1: &AllCopy) -> AllCopy { + debug v => _1; + let mut _0: AllCopy; + let _2: i32; + let mut _5: i32; + let mut _6: u64; + let mut _7: [i8; 3]; + scope 1 { + debug a => _2; + let _3: u64; + scope 2 { + debug b => _3; + let _4: [i8; 3]; + scope 3 { + debug c => _4; + } + } + } + + bb0: { +- StorageLive(_2); ++ nop; + _2 = copy ((*_1).0: i32); +- StorageLive(_3); ++ nop; + _3 = copy ((*_1).1: u64); +- StorageLive(_4); ++ nop; + _4 = copy ((*_1).2: [i8; 3]); + StorageLive(_5); + _5 = copy _2; + StorageLive(_6); + _6 = copy _3; + StorageLive(_7); + _7 = copy _4; +- _0 = AllCopy { a: move _5, b: move _6, c: move _7 }; ++ _0 = copy (*_1); + StorageDead(_7); + StorageDead(_6); + StorageDead(_5); +- StorageDead(_4); +- StorageDead(_3); +- StorageDead(_2); ++ nop; ++ nop; ++ nop; + return; + } + } + diff --git a/tests/mir-opt/gvn_copy_aggregate.all_copy_2.GVN.diff b/tests/mir-opt/gvn_copy_aggregate.all_copy_2.GVN.diff new file mode 100644 index 00000000000..452d8a93320 --- /dev/null +++ b/tests/mir-opt/gvn_copy_aggregate.all_copy_2.GVN.diff @@ -0,0 +1,64 @@ +- // MIR for `all_copy_2` before GVN ++ // MIR for `all_copy_2` after GVN + + fn all_copy_2(_1: &&AllCopy) -> AllCopy { + debug v => _1; + let mut _0: AllCopy; + let _2: i32; + let mut _5: i32; + let mut _6: u64; + let mut _7: [i8; 3]; + let mut _8: &AllCopy; + let mut _9: &AllCopy; + let mut _10: &AllCopy; + scope 1 { + debug a => _2; + let _3: u64; + scope 2 { + debug b => _3; + let _4: [i8; 3]; + scope 3 { + debug c => _4; + } + } + } + + bb0: { +- StorageLive(_2); +- _8 = deref_copy (*_1); ++ nop; ++ _8 = copy (*_1); + _2 = copy ((*_8).0: i32); +- StorageLive(_3); +- _9 = deref_copy (*_1); +- _3 = copy ((*_9).1: u64); +- StorageLive(_4); +- _10 = deref_copy (*_1); +- _4 = copy ((*_10).2: [i8; 3]); ++ nop; ++ _9 = copy _8; ++ _3 = copy ((*_8).1: u64); ++ nop; ++ _10 = copy _8; ++ _4 = copy ((*_8).2: [i8; 3]); + StorageLive(_5); + _5 = copy _2; + StorageLive(_6); + _6 = copy _3; + StorageLive(_7); + _7 = copy _4; +- _0 = AllCopy { a: move _5, b: move _6, c: move _7 }; ++ _0 = copy (*_8); + StorageDead(_7); + StorageDead(_6); + StorageDead(_5); +- StorageDead(_4); +- StorageDead(_3); +- StorageDead(_2); ++ nop; ++ nop; ++ nop; + return; + } + } + diff --git a/tests/mir-opt/gvn_copy_aggregate.all_copy_different_type.GVN.diff b/tests/mir-opt/gvn_copy_aggregate.all_copy_different_type.GVN.diff new file mode 100644 index 00000000000..37652095fa4 --- /dev/null +++ b/tests/mir-opt/gvn_copy_aggregate.all_copy_different_type.GVN.diff @@ -0,0 +1,53 @@ +- // MIR for `all_copy_different_type` before GVN ++ // MIR for `all_copy_different_type` after GVN + + fn all_copy_different_type(_1: &AllCopy) -> AllCopy2 { + debug v => _1; + let mut _0: AllCopy2; + let _2: i32; + let mut _5: i32; + let mut _6: u64; + let mut _7: [i8; 3]; + scope 1 { + debug a => _2; + let _3: u64; + scope 2 { + debug b => _3; + let _4: [i8; 3]; + scope 3 { + debug c => _4; + } + } + } + + bb0: { +- StorageLive(_2); ++ nop; + _2 = copy ((*_1).0: i32); +- StorageLive(_3); ++ nop; + _3 = copy ((*_1).1: u64); +- StorageLive(_4); ++ nop; + _4 = copy ((*_1).2: [i8; 3]); + StorageLive(_5); + _5 = copy _2; + StorageLive(_6); + _6 = copy _3; + StorageLive(_7); + _7 = copy _4; +- _0 = AllCopy2 { a: move _5, b: move _6, c: move _7 }; ++ _0 = AllCopy2 { a: copy _2, b: copy _3, c: copy _4 }; + StorageDead(_7); + StorageDead(_6); + StorageDead(_5); +- StorageDead(_4); +- StorageDead(_3); +- StorageDead(_2); ++ nop; ++ nop; ++ nop; + return; + } + } + diff --git a/tests/mir-opt/gvn_copy_aggregate.all_copy_has_changed.GVN.diff b/tests/mir-opt/gvn_copy_aggregate.all_copy_has_changed.GVN.diff new file mode 100644 index 00000000000..8012c26499c --- /dev/null +++ b/tests/mir-opt/gvn_copy_aggregate.all_copy_has_changed.GVN.diff @@ -0,0 +1,54 @@ +- // MIR for `all_copy_has_changed` before GVN ++ // MIR for `all_copy_has_changed` after GVN + + fn all_copy_has_changed(_1: &mut AllCopy) -> AllCopy { + debug v => _1; + let mut _0: AllCopy; + let _2: i32; + let mut _5: i32; + let mut _6: u64; + let mut _7: [i8; 3]; + scope 1 { + debug a => _2; + let _3: u64; + scope 2 { + debug b => _3; + let _4: [i8; 3]; + scope 3 { + debug c => _4; + } + } + } + + bb0: { +- StorageLive(_2); ++ nop; + _2 = copy ((*_1).0: i32); +- StorageLive(_3); ++ nop; + _3 = copy ((*_1).1: u64); +- StorageLive(_4); ++ nop; + _4 = copy ((*_1).2: [i8; 3]); + ((*_1).0: i32) = const 1_i32; + StorageLive(_5); + _5 = copy _2; + StorageLive(_6); + _6 = copy _3; + StorageLive(_7); + _7 = copy _4; +- _0 = AllCopy { a: move _5, b: move _6, c: move _7 }; ++ _0 = AllCopy { a: copy _2, b: copy _3, c: copy _4 }; + StorageDead(_7); + StorageDead(_6); + StorageDead(_5); +- StorageDead(_4); +- StorageDead(_3); +- StorageDead(_2); ++ nop; ++ nop; ++ nop; + return; + } + } + diff --git a/tests/mir-opt/gvn_copy_aggregate.all_copy_move.GVN.diff b/tests/mir-opt/gvn_copy_aggregate.all_copy_move.GVN.diff new file mode 100644 index 00000000000..911b787a64b --- /dev/null +++ b/tests/mir-opt/gvn_copy_aggregate.all_copy_move.GVN.diff @@ -0,0 +1,53 @@ +- // MIR for `all_copy_move` before GVN ++ // MIR for `all_copy_move` after GVN + + fn all_copy_move(_1: AllCopy) -> AllCopy { + debug v => _1; + let mut _0: AllCopy; + let _2: i32; + let mut _5: i32; + let mut _6: u64; + let mut _7: [i8; 3]; + scope 1 { + debug a => _2; + let _3: u64; + scope 2 { + debug b => _3; + let _4: [i8; 3]; + scope 3 { + debug c => _4; + } + } + } + + bb0: { +- StorageLive(_2); ++ nop; + _2 = copy (_1.0: i32); +- StorageLive(_3); ++ nop; + _3 = copy (_1.1: u64); +- StorageLive(_4); ++ nop; + _4 = copy (_1.2: [i8; 3]); + StorageLive(_5); + _5 = copy _2; + StorageLive(_6); + _6 = copy _3; + StorageLive(_7); + _7 = copy _4; +- _0 = AllCopy { a: move _5, b: move _6, c: move _7 }; ++ _0 = copy _1; + StorageDead(_7); + StorageDead(_6); + StorageDead(_5); +- StorageDead(_4); +- StorageDead(_3); +- StorageDead(_2); ++ nop; ++ nop; ++ nop; + return; + } + } + diff --git a/tests/mir-opt/gvn_copy_aggregate.all_copy_ret_2.GVN.diff b/tests/mir-opt/gvn_copy_aggregate.all_copy_ret_2.GVN.diff new file mode 100644 index 00000000000..5c6e2a6bc67 --- /dev/null +++ b/tests/mir-opt/gvn_copy_aggregate.all_copy_ret_2.GVN.diff @@ -0,0 +1,77 @@ +- // MIR for `all_copy_ret_2` before GVN ++ // MIR for `all_copy_ret_2` after GVN + + fn all_copy_ret_2(_1: &AllCopy) -> (AllCopy, AllCopy) { + debug v => _1; + let mut _0: (AllCopy, AllCopy); + let _2: i32; + let mut _5: AllCopy; + let mut _6: i32; + let mut _7: u64; + let mut _8: [i8; 3]; + let mut _9: AllCopy; + let mut _10: i32; + let mut _11: u64; + let mut _12: [i8; 3]; + scope 1 { + debug a => _2; + let _3: u64; + scope 2 { + debug b => _3; + let _4: [i8; 3]; + scope 3 { + debug c => _4; + } + } + } + + bb0: { +- StorageLive(_2); ++ nop; + _2 = copy ((*_1).0: i32); +- StorageLive(_3); ++ nop; + _3 = copy ((*_1).1: u64); +- StorageLive(_4); ++ nop; + _4 = copy ((*_1).2: [i8; 3]); +- StorageLive(_5); ++ nop; + StorageLive(_6); + _6 = copy _2; + StorageLive(_7); + _7 = copy _3; + StorageLive(_8); + _8 = copy _4; +- _5 = AllCopy { a: move _6, b: move _7, c: move _8 }; ++ _5 = copy (*_1); + StorageDead(_8); + StorageDead(_7); + StorageDead(_6); + StorageLive(_9); + StorageLive(_10); + _10 = copy _2; + StorageLive(_11); + _11 = copy _3; + StorageLive(_12); + _12 = copy _4; +- _9 = AllCopy { a: move _10, b: move _11, c: move _12 }; ++ _9 = copy _5; + StorageDead(_12); + StorageDead(_11); + StorageDead(_10); +- _0 = (move _5, move _9); ++ _0 = (copy _5, copy _5); + StorageDead(_9); +- StorageDead(_5); +- StorageDead(_4); +- StorageDead(_3); +- StorageDead(_2); ++ nop; ++ nop; ++ nop; ++ nop; + return; + } + } + diff --git a/tests/mir-opt/gvn_copy_aggregate.all_copy_use_changed.GVN.diff b/tests/mir-opt/gvn_copy_aggregate.all_copy_use_changed.GVN.diff new file mode 100644 index 00000000000..dc65cccb7bd --- /dev/null +++ b/tests/mir-opt/gvn_copy_aggregate.all_copy_use_changed.GVN.diff @@ -0,0 +1,57 @@ +- // MIR for `all_copy_use_changed` before GVN ++ // MIR for `all_copy_use_changed` after GVN + + fn all_copy_use_changed(_1: &mut AllCopy) -> AllCopy { + debug v => _1; + let mut _0: AllCopy; + let mut _2: i32; + let mut _3: i32; + let mut _6: i32; + let mut _7: u64; + let mut _8: [i8; 3]; + scope 1 { + debug a => _2; + let _4: u64; + scope 2 { + debug b => _4; + let _5: [i8; 3]; + scope 3 { + debug c => _5; + } + } + } + + bb0: { + StorageLive(_2); + _2 = copy ((*_1).0: i32); + ((*_1).0: i32) = const 1_i32; + StorageLive(_3); + _3 = copy ((*_1).0: i32); + _2 = move _3; + StorageDead(_3); +- StorageLive(_4); ++ nop; + _4 = copy ((*_1).1: u64); +- StorageLive(_5); ++ nop; + _5 = copy ((*_1).2: [i8; 3]); + StorageLive(_6); + _6 = copy _2; + StorageLive(_7); + _7 = copy _4; + StorageLive(_8); + _8 = copy _5; +- _0 = AllCopy { a: move _6, b: move _7, c: move _8 }; ++ _0 = AllCopy { a: move _6, b: copy _4, c: copy _5 }; + StorageDead(_8); + StorageDead(_7); + StorageDead(_6); +- StorageDead(_5); +- StorageDead(_4); ++ nop; ++ nop; + StorageDead(_2); + return; + } + } + diff --git a/tests/mir-opt/gvn_copy_aggregate.all_copy_use_changed_2.GVN.diff b/tests/mir-opt/gvn_copy_aggregate.all_copy_use_changed_2.GVN.diff new file mode 100644 index 00000000000..08a4a078adc --- /dev/null +++ b/tests/mir-opt/gvn_copy_aggregate.all_copy_use_changed_2.GVN.diff @@ -0,0 +1,57 @@ +- // MIR for `all_copy_use_changed_2` before GVN ++ // MIR for `all_copy_use_changed_2` after GVN + + fn all_copy_use_changed_2(_1: &mut AllCopy) -> AllCopy { + debug v => _1; + let mut _0: AllCopy; + let mut _2: i32; + let mut _5: i32; + let mut _6: i32; + let mut _7: u64; + let mut _8: [i8; 3]; + scope 1 { + debug a => _2; + let _3: u64; + scope 2 { + debug b => _3; + let _4: [i8; 3]; + scope 3 { + debug c => _4; + } + } + } + + bb0: { + StorageLive(_2); + _2 = copy ((*_1).0: i32); +- StorageLive(_3); ++ nop; + _3 = copy ((*_1).1: u64); +- StorageLive(_4); ++ nop; + _4 = copy ((*_1).2: [i8; 3]); + ((*_1).0: i32) = const 1_i32; + StorageLive(_5); + _5 = copy ((*_1).0: i32); + _2 = move _5; + StorageDead(_5); + StorageLive(_6); + _6 = copy _2; + StorageLive(_7); + _7 = copy _3; + StorageLive(_8); + _8 = copy _4; +- _0 = AllCopy { a: move _6, b: move _7, c: move _8 }; ++ _0 = AllCopy { a: move _6, b: copy _3, c: copy _4 }; + StorageDead(_8); + StorageDead(_7); + StorageDead(_6); +- StorageDead(_4); +- StorageDead(_3); ++ nop; ++ nop; + StorageDead(_2); + return; + } + } + diff --git a/tests/mir-opt/gvn_copy_aggregate.enum_different_variant.GVN.diff b/tests/mir-opt/gvn_copy_aggregate.enum_different_variant.GVN.diff new file mode 100644 index 00000000000..99318d395e2 --- /dev/null +++ b/tests/mir-opt/gvn_copy_aggregate.enum_different_variant.GVN.diff @@ -0,0 +1,162 @@ +- // MIR for `enum_different_variant` before GVN ++ // MIR for `enum_different_variant` after GVN + + fn enum_different_variant(_1: &Enum1) -> Enum1 { + debug v => _1; + let mut _0: Enum1; + let mut _2: isize; + let _3: &AllCopy; + let mut _8: i32; + let mut _9: u64; + let mut _10: [i8; 3]; + let mut _11: AllCopy; + let _12: &AllCopy; + let mut _17: i32; + let mut _18: u64; + let mut _19: [i8; 3]; + let mut _20: AllCopy; + scope 1 { + debug v => _3; + let _4: i32; + scope 2 { + debug a => _4; + let _5: u64; + scope 3 { + debug b => _5; + let _6: [i8; 3]; + scope 4 { + debug c => _6; + let _7: AllCopy; + scope 5 { + debug all_copy => _7; + } + } + } + } + } + scope 6 { + debug v => _12; + let _13: i32; + scope 7 { + debug a => _13; + let _14: u64; + scope 8 { + debug b => _14; + let _15: [i8; 3]; + scope 9 { + debug c => _15; + let _16: AllCopy; + scope 10 { + debug all_copy => _16; + } + } + } + } + } + + bb0: { + _2 = discriminant((*_1)); + switchInt(move _2) -> [0: bb3, 1: bb2, otherwise: bb1]; + } + + bb1: { + unreachable; + } + + bb2: { + StorageLive(_12); + _12 = &(((*_1) as B).0: AllCopy); +- StorageLive(_13); +- _13 = copy ((*_12).0: i32); +- StorageLive(_14); +- _14 = copy ((*_12).1: u64); +- StorageLive(_15); +- _15 = copy ((*_12).2: [i8; 3]); +- StorageLive(_16); ++ nop; ++ _13 = copy ((((*_1) as B).0: AllCopy).0: i32); ++ nop; ++ _14 = copy ((((*_1) as B).0: AllCopy).1: u64); ++ nop; ++ _15 = copy ((((*_1) as B).0: AllCopy).2: [i8; 3]); ++ nop; + StorageLive(_17); + _17 = copy _13; + StorageLive(_18); + _18 = copy _14; + StorageLive(_19); + _19 = copy _15; +- _16 = AllCopy { a: move _17, b: move _18, c: move _19 }; ++ _16 = copy (((*_1) as B).0: AllCopy); + StorageDead(_19); + StorageDead(_18); + StorageDead(_17); + StorageLive(_20); +- _20 = move _16; +- _0 = Enum1::A(move _20); ++ _20 = copy _16; ++ _0 = Enum1::A(copy _16); + StorageDead(_20); +- StorageDead(_16); +- StorageDead(_15); +- StorageDead(_14); +- StorageDead(_13); ++ nop; ++ nop; ++ nop; ++ nop; + StorageDead(_12); + goto -> bb4; + } + + bb3: { + StorageLive(_3); + _3 = &(((*_1) as A).0: AllCopy); +- StorageLive(_4); +- _4 = copy ((*_3).0: i32); +- StorageLive(_5); +- _5 = copy ((*_3).1: u64); +- StorageLive(_6); +- _6 = copy ((*_3).2: [i8; 3]); +- StorageLive(_7); ++ nop; ++ _4 = copy ((((*_1) as A).0: AllCopy).0: i32); ++ nop; ++ _5 = copy ((((*_1) as A).0: AllCopy).1: u64); ++ nop; ++ _6 = copy ((((*_1) as A).0: AllCopy).2: [i8; 3]); ++ nop; + StorageLive(_8); + _8 = copy _4; + StorageLive(_9); + _9 = copy _5; + StorageLive(_10); + _10 = copy _6; +- _7 = AllCopy { a: move _8, b: move _9, c: move _10 }; ++ _7 = copy (((*_1) as A).0: AllCopy); + StorageDead(_10); + StorageDead(_9); + StorageDead(_8); + StorageLive(_11); +- _11 = move _7; +- _0 = Enum1::B(move _11); ++ _11 = copy _7; ++ _0 = Enum1::B(copy _7); + StorageDead(_11); +- StorageDead(_7); +- StorageDead(_6); +- StorageDead(_5); +- StorageDead(_4); ++ nop; ++ nop; ++ nop; ++ nop; + StorageDead(_3); + goto -> bb4; + } + + bb4: { + return; + } + } + diff --git a/tests/mir-opt/gvn_copy_aggregate.enum_identical_variant.GVN.diff b/tests/mir-opt/gvn_copy_aggregate.enum_identical_variant.GVN.diff new file mode 100644 index 00000000000..b740ba6411b --- /dev/null +++ b/tests/mir-opt/gvn_copy_aggregate.enum_identical_variant.GVN.diff @@ -0,0 +1,162 @@ +- // MIR for `enum_identical_variant` before GVN ++ // MIR for `enum_identical_variant` after GVN + + fn enum_identical_variant(_1: &Enum1) -> Enum1 { + debug v => _1; + let mut _0: Enum1; + let mut _2: isize; + let _3: &AllCopy; + let mut _8: i32; + let mut _9: u64; + let mut _10: [i8; 3]; + let mut _11: AllCopy; + let _12: &AllCopy; + let mut _17: i32; + let mut _18: u64; + let mut _19: [i8; 3]; + let mut _20: AllCopy; + scope 1 { + debug v => _3; + let _4: i32; + scope 2 { + debug a => _4; + let _5: u64; + scope 3 { + debug b => _5; + let _6: [i8; 3]; + scope 4 { + debug c => _6; + let _7: AllCopy; + scope 5 { + debug all_copy => _7; + } + } + } + } + } + scope 6 { + debug v => _12; + let _13: i32; + scope 7 { + debug a => _13; + let _14: u64; + scope 8 { + debug b => _14; + let _15: [i8; 3]; + scope 9 { + debug c => _15; + let _16: AllCopy; + scope 10 { + debug all_copy => _16; + } + } + } + } + } + + bb0: { + _2 = discriminant((*_1)); + switchInt(move _2) -> [0: bb3, 1: bb2, otherwise: bb1]; + } + + bb1: { + unreachable; + } + + bb2: { + StorageLive(_12); + _12 = &(((*_1) as B).0: AllCopy); +- StorageLive(_13); +- _13 = copy ((*_12).0: i32); +- StorageLive(_14); +- _14 = copy ((*_12).1: u64); +- StorageLive(_15); +- _15 = copy ((*_12).2: [i8; 3]); +- StorageLive(_16); ++ nop; ++ _13 = copy ((((*_1) as B).0: AllCopy).0: i32); ++ nop; ++ _14 = copy ((((*_1) as B).0: AllCopy).1: u64); ++ nop; ++ _15 = copy ((((*_1) as B).0: AllCopy).2: [i8; 3]); ++ nop; + StorageLive(_17); + _17 = copy _13; + StorageLive(_18); + _18 = copy _14; + StorageLive(_19); + _19 = copy _15; +- _16 = AllCopy { a: move _17, b: move _18, c: move _19 }; ++ _16 = copy (((*_1) as B).0: AllCopy); + StorageDead(_19); + StorageDead(_18); + StorageDead(_17); + StorageLive(_20); +- _20 = move _16; +- _0 = Enum1::B(move _20); ++ _20 = copy _16; ++ _0 = copy (*_1); + StorageDead(_20); +- StorageDead(_16); +- StorageDead(_15); +- StorageDead(_14); +- StorageDead(_13); ++ nop; ++ nop; ++ nop; ++ nop; + StorageDead(_12); + goto -> bb4; + } + + bb3: { + StorageLive(_3); + _3 = &(((*_1) as A).0: AllCopy); +- StorageLive(_4); +- _4 = copy ((*_3).0: i32); +- StorageLive(_5); +- _5 = copy ((*_3).1: u64); +- StorageLive(_6); +- _6 = copy ((*_3).2: [i8; 3]); +- StorageLive(_7); ++ nop; ++ _4 = copy ((((*_1) as A).0: AllCopy).0: i32); ++ nop; ++ _5 = copy ((((*_1) as A).0: AllCopy).1: u64); ++ nop; ++ _6 = copy ((((*_1) as A).0: AllCopy).2: [i8; 3]); ++ nop; + StorageLive(_8); + _8 = copy _4; + StorageLive(_9); + _9 = copy _5; + StorageLive(_10); + _10 = copy _6; +- _7 = AllCopy { a: move _8, b: move _9, c: move _10 }; ++ _7 = copy (((*_1) as A).0: AllCopy); + StorageDead(_10); + StorageDead(_9); + StorageDead(_8); + StorageLive(_11); +- _11 = move _7; +- _0 = Enum1::A(move _11); ++ _11 = copy _7; ++ _0 = copy (*_1); + StorageDead(_11); +- StorageDead(_7); +- StorageDead(_6); +- StorageDead(_5); +- StorageDead(_4); ++ nop; ++ nop; ++ nop; ++ nop; + StorageDead(_3); + goto -> bb4; + } + + bb4: { + return; + } + } + diff --git a/tests/mir-opt/gvn_copy_aggregate.nest_copy.GVN.diff b/tests/mir-opt/gvn_copy_aggregate.nest_copy.GVN.diff new file mode 100644 index 00000000000..ee5906bab11 --- /dev/null +++ b/tests/mir-opt/gvn_copy_aggregate.nest_copy.GVN.diff @@ -0,0 +1,81 @@ +- // MIR for `nest_copy` before GVN ++ // MIR for `nest_copy` after GVN + + fn nest_copy(_1: &NestCopy) -> NestCopy { + debug v => _1; + let mut _0: NestCopy; + let _2: i32; + let mut _6: i32; + let mut _7: u64; + let mut _8: [i8; 3]; + let mut _10: i32; + let mut _11: AllCopy; + scope 1 { + debug a => _2; + let _3: u64; + scope 2 { + debug b => _3; + let _4: [i8; 3]; + scope 3 { + debug c => _4; + let _5: AllCopy; + scope 4 { + debug all_copy => _5; + let _9: i32; + scope 5 { + debug d => _9; + } + } + } + } + } + + bb0: { +- StorageLive(_2); ++ nop; + _2 = copy (((*_1).1: AllCopy).0: i32); +- StorageLive(_3); ++ nop; + _3 = copy (((*_1).1: AllCopy).1: u64); +- StorageLive(_4); ++ nop; + _4 = copy (((*_1).1: AllCopy).2: [i8; 3]); +- StorageLive(_5); ++ nop; + StorageLive(_6); + _6 = copy _2; + StorageLive(_7); + _7 = copy _3; + StorageLive(_8); + _8 = copy _4; +- _5 = AllCopy { a: move _6, b: move _7, c: move _8 }; ++ _5 = copy ((*_1).1: AllCopy); + StorageDead(_8); + StorageDead(_7); + StorageDead(_6); +- StorageLive(_9); ++ nop; + _9 = copy ((*_1).0: i32); + StorageLive(_10); + _10 = copy _9; + StorageLive(_11); +- _11 = move _5; +- _0 = NestCopy { d: move _10, all_copy: move _11 }; ++ _11 = copy _5; ++ _0 = copy (*_1); + StorageDead(_11); + StorageDead(_10); +- StorageDead(_9); +- StorageDead(_5); +- StorageDead(_4); +- StorageDead(_3); +- StorageDead(_2); ++ nop; ++ nop; ++ nop; ++ nop; ++ nop; + return; + } + } + diff --git a/tests/mir-opt/gvn_copy_aggregate.remove_storage_dead.GVN.diff b/tests/mir-opt/gvn_copy_aggregate.remove_storage_dead.GVN.diff new file mode 100644 index 00000000000..c9cfc7efcd1 --- /dev/null +++ b/tests/mir-opt/gvn_copy_aggregate.remove_storage_dead.GVN.diff @@ -0,0 +1,54 @@ +- // MIR for `remove_storage_dead` before GVN ++ // MIR for `remove_storage_dead` after GVN + + fn remove_storage_dead(_1: fn() -> AlwaysSome) -> AlwaysSome { + debug f => _1; + let mut _0: AlwaysSome; + let _2: T; + let mut _3: AlwaysSome; + let mut _4: fn() -> AlwaysSome; + let _5: T; + let mut _6: T; + let mut _7: isize; + let mut _8: isize; + scope 1 { + debug v => _2; + } + scope 2 { + debug v => _5; + } + + bb0: { + StorageLive(_2); +- StorageLive(_3); ++ nop; + StorageLive(_4); + _4 = copy _1; +- _3 = move _4() -> [return: bb1, unwind unreachable]; ++ _3 = copy _1() -> [return: bb1, unwind unreachable]; + } + + bb1: { + StorageDead(_4); +- StorageLive(_5); +- _5 = move ((_3 as Some).0: T); +- _2 = move _5; +- StorageDead(_5); ++ nop; ++ _5 = copy ((_3 as Some).0: T); ++ _2 = copy _5; ++ nop; + _7 = discriminant(_3); +- StorageDead(_3); ++ nop; + StorageLive(_6); +- _6 = move _2; +- _0 = AlwaysSome::::Some(move _6); ++ _6 = copy _5; ++ _0 = copy _3; + StorageDead(_6); + StorageDead(_2); + return; + } + } + diff --git a/tests/mir-opt/gvn_copy_aggregate.remove_storage_dead_from_index.GVN.diff b/tests/mir-opt/gvn_copy_aggregate.remove_storage_dead_from_index.GVN.diff new file mode 100644 index 00000000000..fba5550319a --- /dev/null +++ b/tests/mir-opt/gvn_copy_aggregate.remove_storage_dead_from_index.GVN.diff @@ -0,0 +1,26 @@ +- // MIR for `remove_storage_dead_from_index` before GVN ++ // MIR for `remove_storage_dead_from_index` after GVN + + fn remove_storage_dead_from_index(_1: fn() -> usize, _2: [SameType; 5]) -> SameType { + let mut _0: SameType; + let mut _3: usize; + let mut _4: i32; + let mut _5: i32; + + bb0: { +- StorageLive(_3); ++ nop; + _3 = copy _1() -> [return: bb1, unwind unreachable]; + } + + bb1: { + _4 = copy (_2[_3].0: i32); + _5 = copy (_2[_3].1: i32); +- StorageDead(_3); +- _0 = SameType { a: copy _4, b: copy _5 }; ++ nop; ++ _0 = copy _2[_3]; + return; + } + } + diff --git a/tests/mir-opt/gvn_copy_aggregate.rs b/tests/mir-opt/gvn_copy_aggregate.rs new file mode 100644 index 00000000000..c9473025a15 --- /dev/null +++ b/tests/mir-opt/gvn_copy_aggregate.rs @@ -0,0 +1,261 @@ +//@ test-mir-pass: GVN +//@ compile-flags: -Cpanic=abort + +#![feature(core_intrinsics, custom_mir)] +#![allow(internal_features)] + +use std::intrinsics::mir::*; + +struct AllCopy { + a: i32, + b: u64, + c: [i8; 3], +} + +// EMIT_MIR gvn_copy_aggregate.all_copy.GVN.diff +fn all_copy(v: &AllCopy) -> AllCopy { + // CHECK-LABEL: fn all_copy( + // CHECK: bb0: { + // CHECK-NOT: = AllCopy { {{.*}} }; + // CHECK: _0 = copy (*_1); + let a = v.a; + let b = v.b; + let c = v.c; + AllCopy { a, b, c } +} + +// EMIT_MIR gvn_copy_aggregate.all_copy_2.GVN.diff +fn all_copy_2(v: &&AllCopy) -> AllCopy { + // CHECK-LABEL: fn all_copy_2( + // CHECK: bb0: { + // CHECK-NOT: = AllCopy { {{.*}} }; + // CHECK: [[V1:_.*]] = copy (*_1); + // CHECK: _0 = copy (*[[V1]]); + let a = v.a; + let b = v.b; + let c = v.c; + AllCopy { a, b, c } +} + +// EMIT_MIR gvn_copy_aggregate.all_copy_move.GVN.diff +fn all_copy_move(v: AllCopy) -> AllCopy { + // CHECK-LABEL: fn all_copy_move( + // CHECK: bb0: { + // CHECK-NOT: = AllCopy { {{.*}} }; + // CHECK: _0 = copy _1; + let a = v.a; + let b = v.b; + let c = v.c; + AllCopy { a, b, c } +} + +// EMIT_MIR gvn_copy_aggregate.all_copy_ret_2.GVN.diff +fn all_copy_ret_2(v: &AllCopy) -> (AllCopy, AllCopy) { + // CHECK-LABEL: fn all_copy_ret_2( + // CHECK: bb0: { + // CHECK-NOT: = AllCopy { {{.*}} }; + // CHECK: [[V1:_.*]] = copy (*_1); + // CHECK: [[V2:_.*]] = copy [[V1]]; + // CHECK: _0 = (copy [[V1]], copy [[V1]]); + let a = v.a; + let b = v.b; + let c = v.c; + (AllCopy { a, b, c }, AllCopy { a, b, c }) +} + +struct AllCopy2 { + a: i32, + b: u64, + c: [i8; 3], +} + +// EMIT_MIR gvn_copy_aggregate.all_copy_different_type.GVN.diff +fn all_copy_different_type(v: &AllCopy) -> AllCopy2 { + // CHECK-LABEL: fn all_copy_different_type( + // CHECK: bb0: { + // CHECK: _0 = AllCopy2 { {{.*}} }; + let a = v.a; + let b = v.b; + let c = v.c; + AllCopy2 { a, b, c } +} + +struct SameType { + a: i32, + b: i32, +} + +// EMIT_MIR gvn_copy_aggregate.same_type_different_index.GVN.diff +fn same_type_different_index(v: &SameType) -> SameType { + // CHECK-LABEL: fn same_type_different_index( + // CHECK: bb0: { + // CHECK: _0 = SameType { {{.*}} }; + let a = v.b; + let b = v.a; + SameType { a, b } +} + +// EMIT_MIR gvn_copy_aggregate.all_copy_has_changed.GVN.diff +fn all_copy_has_changed(v: &mut AllCopy) -> AllCopy { + // CHECK-LABEL: fn all_copy_has_changed( + // CHECK: bb0: { + // CHECK: _0 = AllCopy { {{.*}} }; + let a = v.a; + let b = v.b; + let c = v.c; + v.a = 1; + AllCopy { a, b, c } +} + +// FIXME: This can be simplified to `Copy`. +// EMIT_MIR gvn_copy_aggregate.all_copy_use_changed.GVN.diff +fn all_copy_use_changed(v: &mut AllCopy) -> AllCopy { + // CHECK-LABEL: fn all_copy_use_changed( + // CHECK: bb0: { + // CHECK-NOT: _0 = copy (*_1); + // CHECK: = AllCopy { {{.*}} }; + let mut a = v.a; + v.a = 1; + a = v.a; + let b = v.b; + let c = v.c; + AllCopy { a, b, c } +} + +// FIXME: This can be simplified to `Copy`. +// EMIT_MIR gvn_copy_aggregate.all_copy_use_changed_2.GVN.diff +fn all_copy_use_changed_2(v: &mut AllCopy) -> AllCopy { + // CHECK-LABEL: fn all_copy_use_changed_2( + // CHECK: bb0: { + // CHECK-NOT: _0 = (*_1); + // CHECK: = AllCopy { {{.*}} }; + let mut a = v.a; + let b = v.b; + let c = v.c; + v.a = 1; + a = v.a; + AllCopy { a, b, c } +} + +struct NestCopy { + d: i32, + all_copy: AllCopy, +} + +// EMIT_MIR gvn_copy_aggregate.nest_copy.GVN.diff +fn nest_copy(v: &NestCopy) -> NestCopy { + // CHECK-LABEL: fn nest_copy( + // CHECK: bb0: { + // CHECK-NOT: = AllCopy { {{.*}} }; + // CHECK-NOT: = NestCopy { {{.*}} }; + let a = v.all_copy.a; + let b = v.all_copy.b; + let c = v.all_copy.c; + let all_copy = AllCopy { a, b, c }; + let d = v.d; + NestCopy { d, all_copy } +} + +enum Enum1 { + A(AllCopy), + B(AllCopy), +} + +// EMIT_MIR gvn_copy_aggregate.enum_identical_variant.GVN.diff +fn enum_identical_variant(v: &Enum1) -> Enum1 { + // CHECK-LABEL: fn enum_identical_variant( + // CHECK-NOT: = AllCopy { {{.*}} }; + // CHECK: _0 = copy (*_1); + // CHECK-NOT: = AllCopy { {{.*}} }; + // CHECK: _0 = copy (*_1); + match v { + Enum1::A(v) => { + let a = v.a; + let b = v.b; + let c = v.c; + let all_copy = AllCopy { a, b, c }; + Enum1::A(all_copy) + } + Enum1::B(v) => { + let a = v.a; + let b = v.b; + let c = v.c; + let all_copy = AllCopy { a, b, c }; + Enum1::B(all_copy) + } + } +} + +// EMIT_MIR gvn_copy_aggregate.enum_different_variant.GVN.diff +fn enum_different_variant(v: &Enum1) -> Enum1 { + // CHECK-LABEL: fn enum_different_variant( + // CHECK-NOT: = AllCopy { {{.*}} }; + // CHECK: [[V1:_.*]] = copy (((*_1) as [[VARIANT1:.*]]).0: AllCopy); + // CHECK: _0 = Enum1::[[VARIANT2:.*]](copy [[V1]]); + // CHECK-NOT: = AllCopy { {{.*}} }; + // CHECK: [[V2:_.*]] = copy (((*_1) as [[VARIANT2]]).0: AllCopy); + // CHECK: _0 = Enum1::[[VARIANT1]](copy [[V2]]); + match v { + Enum1::A(v) => { + let a = v.a; + let b = v.b; + let c = v.c; + let all_copy = AllCopy { a, b, c }; + Enum1::B(all_copy) + } + Enum1::B(v) => { + let a = v.a; + let b = v.b; + let c = v.c; + let all_copy = AllCopy { a, b, c }; + Enum1::A(all_copy) + } + } +} + +enum AlwaysSome { + Some(T), +} + +// Ensure that we do not access this local after `StorageDead`. +// EMIT_MIR gvn_copy_aggregate.remove_storage_dead.GVN.diff +fn remove_storage_dead(f: fn() -> AlwaysSome) -> AlwaysSome { + // CHECK-LABEL: fn remove_storage_dead( + // CHECK: [[V1:_.*]] = copy _1() -> [return: [[BB1:bb.*]], + // CHECK: [[BB1]]: { + // CHECK-NOT: StorageDead([[V1]]); + // CHECK: _0 = copy [[V1]]; + let v = { + match f() { + AlwaysSome::Some(v) => v, + } + }; + AlwaysSome::Some(v) +} + +// EMIT_MIR gvn_copy_aggregate.remove_storage_dead_from_index.GVN.diff +#[custom_mir(dialect = "analysis")] +fn remove_storage_dead_from_index(f: fn() -> usize, v: [SameType; 5]) -> SameType { + // CHECK-LABEL: fn remove_storage_dead_from_index( + // CHECK: [[V1:_.*]] = copy _1() -> [return: [[BB1:bb.*]], + // CHECK: [[BB1]]: { + // CHECK-NOT: StorageDead([[V1]]); + // CHECK-NOT: = SameType { {{.*}} }; + // CHECK: _0 = copy _2[[[V1]]]; + mir! { + let index: usize; + let a: i32; + let b: i32; + { + StorageLive(index); + Call(index = f(), ReturnTo(bb1), UnwindUnreachable()) + } + bb1 = { + a = v[index].a; + b = v[index].b; + StorageDead(index); + RET = SameType { a, b }; + Return() + } + } +} diff --git a/tests/mir-opt/gvn_copy_aggregate.same_type_different_index.GVN.diff b/tests/mir-opt/gvn_copy_aggregate.same_type_different_index.GVN.diff new file mode 100644 index 00000000000..e3126b09a58 --- /dev/null +++ b/tests/mir-opt/gvn_copy_aggregate.same_type_different_index.GVN.diff @@ -0,0 +1,40 @@ +- // MIR for `same_type_different_index` before GVN ++ // MIR for `same_type_different_index` after GVN + + fn same_type_different_index(_1: &SameType) -> SameType { + debug v => _1; + let mut _0: SameType; + let _2: i32; + let mut _4: i32; + let mut _5: i32; + scope 1 { + debug a => _2; + let _3: i32; + scope 2 { + debug b => _3; + } + } + + bb0: { +- StorageLive(_2); ++ nop; + _2 = copy ((*_1).1: i32); +- StorageLive(_3); ++ nop; + _3 = copy ((*_1).0: i32); + StorageLive(_4); + _4 = copy _2; + StorageLive(_5); + _5 = copy _3; +- _0 = SameType { a: move _4, b: move _5 }; ++ _0 = SameType { a: copy _2, b: copy _3 }; + StorageDead(_5); + StorageDead(_4); +- StorageDead(_3); +- StorageDead(_2); ++ nop; ++ nop; + return; + } + } + diff --git a/tests/mir-opt/pre-codegen/clone_as_copy.clone_as_copy.PreCodegen.after.mir b/tests/mir-opt/pre-codegen/clone_as_copy.clone_as_copy.PreCodegen.after.mir new file mode 100644 index 00000000000..34747e5a928 --- /dev/null +++ b/tests/mir-opt/pre-codegen/clone_as_copy.clone_as_copy.PreCodegen.after.mir @@ -0,0 +1,21 @@ +// MIR for `clone_as_copy` after PreCodegen + +fn clone_as_copy(_1: &NestCopy) -> NestCopy { + debug v => _1; + let mut _0: NestCopy; + scope 1 (inlined ::clone) { + debug self => _1; + let _2: &AllCopy; + scope 2 (inlined ::clone) { + debug self => _2; + } + } + + bb0: { + StorageLive(_2); + _2 = &((*_1).1: AllCopy); + _0 = copy (*_1); + StorageDead(_2); + return; + } +} diff --git a/tests/mir-opt/pre-codegen/clone_as_copy.enum_clone_as_copy.PreCodegen.after.mir b/tests/mir-opt/pre-codegen/clone_as_copy.enum_clone_as_copy.PreCodegen.after.mir new file mode 100644 index 00000000000..9f88e1961ec --- /dev/null +++ b/tests/mir-opt/pre-codegen/clone_as_copy.enum_clone_as_copy.PreCodegen.after.mir @@ -0,0 +1,62 @@ +// MIR for `enum_clone_as_copy` after PreCodegen + +fn enum_clone_as_copy(_1: &Enum1) -> Enum1 { + debug v => _1; + let mut _0: Enum1; + scope 1 (inlined ::clone) { + debug self => _1; + let mut _2: isize; + let mut _3: &AllCopy; + let mut _4: &NestCopy; + scope 2 { + debug __self_0 => _3; + scope 6 (inlined ::clone) { + debug self => _3; + } + } + scope 3 { + debug __self_0 => _4; + scope 4 (inlined ::clone) { + debug self => _4; + let _5: &AllCopy; + scope 5 (inlined ::clone) { + debug self => _5; + } + } + } + } + + bb0: { + StorageLive(_2); + StorageLive(_3); + StorageLive(_4); + _2 = discriminant((*_1)); + switchInt(move _2) -> [0: bb1, 1: bb2, otherwise: bb4]; + } + + bb1: { + _3 = &(((*_1) as A).0: AllCopy); + _0 = copy (*_1); + goto -> bb3; + } + + bb2: { + _4 = &(((*_1) as B).0: NestCopy); + StorageLive(_5); + _5 = &((((*_1) as B).0: NestCopy).1: AllCopy); + StorageDead(_5); + _0 = copy (*_1); + goto -> bb3; + } + + bb3: { + StorageDead(_4); + StorageDead(_3); + StorageDead(_2); + return; + } + + bb4: { + unreachable; + } +} diff --git a/tests/mir-opt/pre-codegen/clone_as_copy.rs b/tests/mir-opt/pre-codegen/clone_as_copy.rs new file mode 100644 index 00000000000..f5ff1854d38 --- /dev/null +++ b/tests/mir-opt/pre-codegen/clone_as_copy.rs @@ -0,0 +1,43 @@ +//@ compile-flags: -Cdebuginfo=full + +// Check if we have transformed the nested clone to the copy in the complete pipeline. + +#[derive(Clone)] +struct AllCopy { + a: i32, + b: u64, + c: [i8; 3], +} + +#[derive(Clone)] +struct NestCopy { + a: i32, + b: AllCopy, + c: [i8; 3], +} + +#[derive(Clone)] +enum Enum1 { + A(AllCopy), + B(NestCopy), +} + +// EMIT_MIR clone_as_copy.clone_as_copy.PreCodegen.after.mir +fn clone_as_copy(v: &NestCopy) -> NestCopy { + // CHECK-LABEL: fn clone_as_copy( + // CHECK-NOT: = AllCopy { {{.*}} }; + // CHECK-NOT: = NestCopy { {{.*}} }; + // CHECK: _0 = copy (*_1); + // CHECK: return; + v.clone() +} + +// FIXME: We can merge into exactly one assignment statement. +// EMIT_MIR clone_as_copy.enum_clone_as_copy.PreCodegen.after.mir +fn enum_clone_as_copy(v: &Enum1) -> Enum1 { + // CHECK-LABEL: fn enum_clone_as_copy( + // CHECK-NOT: = Enum1:: + // CHECK: _0 = copy (*_1); + // CHECK: _0 = copy (*_1); + v.clone() +} diff --git a/tests/mir-opt/pre-codegen/no_inlined_clone.{impl#0}-clone.PreCodegen.after.mir b/tests/mir-opt/pre-codegen/no_inlined_clone.{impl#0}-clone.PreCodegen.after.mir index 62a9cd9131f..9020cf1ef37 100644 --- a/tests/mir-opt/pre-codegen/no_inlined_clone.{impl#0}-clone.PreCodegen.after.mir +++ b/tests/mir-opt/pre-codegen/no_inlined_clone.{impl#0}-clone.PreCodegen.after.mir @@ -3,13 +3,9 @@ fn ::clone(_1: &Foo) -> Foo { debug self => _1; let mut _0: Foo; - let mut _2: i32; bb0: { - StorageLive(_2); - _2 = copy ((*_1).0: i32); - _0 = Foo { a: move _2 }; - StorageDead(_2); + _0 = copy (*_1); return; } } diff --git a/tests/mir-opt/pre-codegen/try_identity.old.PreCodegen.after.mir b/tests/mir-opt/pre-codegen/try_identity.old.PreCodegen.after.mir index ac485f485b1..889e80d26e1 100644 --- a/tests/mir-opt/pre-codegen/try_identity.old.PreCodegen.after.mir +++ b/tests/mir-opt/pre-codegen/try_identity.old.PreCodegen.after.mir @@ -19,14 +19,14 @@ fn old(_1: Result) -> Result { } bb1: { - _3 = move ((_1 as Ok).0: T); - _0 = Result::::Ok(copy _3); + _3 = copy ((_1 as Ok).0: T); + _0 = copy _1; goto -> bb3; } bb2: { - _4 = move ((_1 as Err).0: E); - _0 = Result::::Err(copy _4); + _4 = copy ((_1 as Err).0: E); + _0 = copy _1; goto -> bb3; } diff --git a/tests/mir-opt/pre-codegen/vec_deref.vec_deref_to_slice.PreCodegen.after.panic-abort.mir b/tests/mir-opt/pre-codegen/vec_deref.vec_deref_to_slice.PreCodegen.after.panic-abort.mir index ce1e4a0abd6..0ad7f5910a0 100644 --- a/tests/mir-opt/pre-codegen/vec_deref.vec_deref_to_slice.PreCodegen.after.panic-abort.mir +++ b/tests/mir-opt/pre-codegen/vec_deref.vec_deref_to_slice.PreCodegen.after.panic-abort.mir @@ -5,7 +5,7 @@ fn vec_deref_to_slice(_1: &Vec) -> &[u8] { let mut _0: &[u8]; scope 1 (inlined as Deref>::deref) { debug self => _1; - let mut _7: usize; + let mut _6: usize; scope 2 (inlined Vec::::as_ptr) { debug self => _1; let mut _2: &alloc::raw_vec::RawVec; @@ -14,7 +14,6 @@ fn vec_deref_to_slice(_1: &Vec) -> &[u8] { let mut _3: &alloc::raw_vec::RawVecInner; scope 4 (inlined alloc::raw_vec::RawVecInner::ptr::) { debug self => _3; - let mut _6: std::ptr::NonNull; scope 5 (inlined alloc::raw_vec::RawVecInner::non_null::) { debug self => _3; let mut _4: std::ptr::NonNull; @@ -30,28 +29,28 @@ fn vec_deref_to_slice(_1: &Vec) -> &[u8] { } } scope 9 (inlined #[track_caller] as Into>>::into) { - debug ((self: Unique).0: std::ptr::NonNull) => _6; + debug ((self: Unique).0: std::ptr::NonNull) => _4; debug ((self: Unique).1: std::marker::PhantomData) => const PhantomData::; scope 10 (inlined as From>>::from) { - debug ((unique: Unique).0: std::ptr::NonNull) => _6; + debug ((unique: Unique).0: std::ptr::NonNull) => _4; debug ((unique: Unique).1: std::marker::PhantomData) => const PhantomData::; scope 11 (inlined Unique::::as_non_null_ptr) { - debug ((self: Unique).0: std::ptr::NonNull) => _6; + debug ((self: Unique).0: std::ptr::NonNull) => _4; debug ((self: Unique).1: std::marker::PhantomData) => const PhantomData::; } } } } scope 12 (inlined NonNull::::as_ptr) { - debug self => _6; + debug self => _4; } } } } scope 13 (inlined std::slice::from_raw_parts::<'_, u8>) { debug data => _5; - debug len => _7; - let _8: *const [u8]; + debug len => _6; + let _7: *const [u8]; scope 14 (inlined core::ub_checks::check_language_ub) { scope 15 (inlined core::ub_checks::check_language_ub::runtime) { } @@ -62,10 +61,10 @@ fn vec_deref_to_slice(_1: &Vec) -> &[u8] { } scope 18 (inlined slice_from_raw_parts::) { debug data => _5; - debug len => _7; + debug len => _6; scope 19 (inlined std::ptr::from_raw_parts::<[u8], u8>) { debug data_pointer => _5; - debug metadata => _7; + debug metadata => _6; } } } @@ -76,22 +75,17 @@ fn vec_deref_to_slice(_1: &Vec) -> &[u8] { _2 = &((*_1).0: alloc::raw_vec::RawVec); StorageLive(_3); _3 = &(((*_1).0: alloc::raw_vec::RawVec).0: alloc::raw_vec::RawVecInner); - StorageLive(_6); - StorageLive(_4); _4 = copy (((((*_1).0: alloc::raw_vec::RawVec).0: alloc::raw_vec::RawVecInner).0: std::ptr::Unique).0: std::ptr::NonNull); _5 = copy (_4.0: *const u8); - _6 = NonNull:: { pointer: copy _5 }; - StorageDead(_4); - StorageDead(_6); StorageDead(_3); StorageDead(_2); + StorageLive(_6); + _6 = copy ((*_1).1: usize); StorageLive(_7); - _7 = copy ((*_1).1: usize); - StorageLive(_8); - _8 = *const [u8] from (copy _5, copy _7); - _0 = &(*_8); - StorageDead(_8); + _7 = *const [u8] from (copy _5, copy _6); + _0 = &(*_7); StorageDead(_7); + StorageDead(_6); return; } } diff --git a/tests/mir-opt/pre-codegen/vec_deref.vec_deref_to_slice.PreCodegen.after.panic-unwind.mir b/tests/mir-opt/pre-codegen/vec_deref.vec_deref_to_slice.PreCodegen.after.panic-unwind.mir index ce1e4a0abd6..0ad7f5910a0 100644 --- a/tests/mir-opt/pre-codegen/vec_deref.vec_deref_to_slice.PreCodegen.after.panic-unwind.mir +++ b/tests/mir-opt/pre-codegen/vec_deref.vec_deref_to_slice.PreCodegen.after.panic-unwind.mir @@ -5,7 +5,7 @@ fn vec_deref_to_slice(_1: &Vec) -> &[u8] { let mut _0: &[u8]; scope 1 (inlined as Deref>::deref) { debug self => _1; - let mut _7: usize; + let mut _6: usize; scope 2 (inlined Vec::::as_ptr) { debug self => _1; let mut _2: &alloc::raw_vec::RawVec; @@ -14,7 +14,6 @@ fn vec_deref_to_slice(_1: &Vec) -> &[u8] { let mut _3: &alloc::raw_vec::RawVecInner; scope 4 (inlined alloc::raw_vec::RawVecInner::ptr::) { debug self => _3; - let mut _6: std::ptr::NonNull; scope 5 (inlined alloc::raw_vec::RawVecInner::non_null::) { debug self => _3; let mut _4: std::ptr::NonNull; @@ -30,28 +29,28 @@ fn vec_deref_to_slice(_1: &Vec) -> &[u8] { } } scope 9 (inlined #[track_caller] as Into>>::into) { - debug ((self: Unique).0: std::ptr::NonNull) => _6; + debug ((self: Unique).0: std::ptr::NonNull) => _4; debug ((self: Unique).1: std::marker::PhantomData) => const PhantomData::; scope 10 (inlined as From>>::from) { - debug ((unique: Unique).0: std::ptr::NonNull) => _6; + debug ((unique: Unique).0: std::ptr::NonNull) => _4; debug ((unique: Unique).1: std::marker::PhantomData) => const PhantomData::; scope 11 (inlined Unique::::as_non_null_ptr) { - debug ((self: Unique).0: std::ptr::NonNull) => _6; + debug ((self: Unique).0: std::ptr::NonNull) => _4; debug ((self: Unique).1: std::marker::PhantomData) => const PhantomData::; } } } } scope 12 (inlined NonNull::::as_ptr) { - debug self => _6; + debug self => _4; } } } } scope 13 (inlined std::slice::from_raw_parts::<'_, u8>) { debug data => _5; - debug len => _7; - let _8: *const [u8]; + debug len => _6; + let _7: *const [u8]; scope 14 (inlined core::ub_checks::check_language_ub) { scope 15 (inlined core::ub_checks::check_language_ub::runtime) { } @@ -62,10 +61,10 @@ fn vec_deref_to_slice(_1: &Vec) -> &[u8] { } scope 18 (inlined slice_from_raw_parts::) { debug data => _5; - debug len => _7; + debug len => _6; scope 19 (inlined std::ptr::from_raw_parts::<[u8], u8>) { debug data_pointer => _5; - debug metadata => _7; + debug metadata => _6; } } } @@ -76,22 +75,17 @@ fn vec_deref_to_slice(_1: &Vec) -> &[u8] { _2 = &((*_1).0: alloc::raw_vec::RawVec); StorageLive(_3); _3 = &(((*_1).0: alloc::raw_vec::RawVec).0: alloc::raw_vec::RawVecInner); - StorageLive(_6); - StorageLive(_4); _4 = copy (((((*_1).0: alloc::raw_vec::RawVec).0: alloc::raw_vec::RawVecInner).0: std::ptr::Unique).0: std::ptr::NonNull); _5 = copy (_4.0: *const u8); - _6 = NonNull:: { pointer: copy _5 }; - StorageDead(_4); - StorageDead(_6); StorageDead(_3); StorageDead(_2); + StorageLive(_6); + _6 = copy ((*_1).1: usize); StorageLive(_7); - _7 = copy ((*_1).1: usize); - StorageLive(_8); - _8 = *const [u8] from (copy _5, copy _7); - _0 = &(*_8); - StorageDead(_8); + _7 = *const [u8] from (copy _5, copy _6); + _0 = &(*_7); StorageDead(_7); + StorageDead(_6); return; } } diff --git a/tests/ui/async-await/async-closures/body-check-on-non-fnmut.rs b/tests/ui/async-await/async-closures/body-check-on-non-fnmut.rs new file mode 100644 index 00000000000..4382a689e75 --- /dev/null +++ b/tests/ui/async-await/async-closures/body-check-on-non-fnmut.rs @@ -0,0 +1,20 @@ +//@ aux-build:block-on.rs +//@ edition:2021 +//@ build-pass + +#![feature(async_closure)] + +extern crate block_on; + +// Make sure that we don't call `coroutine_by_move_body_def_id` query +// on async closures that are `FnOnce`. See issue: #130167. + +async fn empty() {} + +pub async fn call_once(f: F) { + f().await; +} + +fn main() { + block_on::block_on(call_once(async || empty().await)); +} diff --git a/tests/ui/coherence/coherence-conflicting-repeated-negative-trait-impl-70849.rs b/tests/ui/coherence/coherence-conflicting-repeated-negative-trait-impl-70849.rs new file mode 100644 index 00000000000..88b9d9e62bf --- /dev/null +++ b/tests/ui/coherence/coherence-conflicting-repeated-negative-trait-impl-70849.rs @@ -0,0 +1,10 @@ +#![feature(negative_impls)] +//@ edition: 2021 +// Test to ensure we are printing the polarity of the impl trait ref +// when printing out conflicting trait impls + +struct MyType; + +impl !Clone for &mut MyType {} +//~^ ERROR conflicting implementations of trait `Clone` for type `&mut MyType` +fn main() {} diff --git a/tests/ui/coherence/coherence-conflicting-repeated-negative-trait-impl-70849.stderr b/tests/ui/coherence/coherence-conflicting-repeated-negative-trait-impl-70849.stderr new file mode 100644 index 00000000000..b317197eb40 --- /dev/null +++ b/tests/ui/coherence/coherence-conflicting-repeated-negative-trait-impl-70849.stderr @@ -0,0 +1,13 @@ +error[E0119]: conflicting implementations of trait `Clone` for type `&mut MyType` + --> $DIR/coherence-conflicting-repeated-negative-trait-impl-70849.rs:8:1 + | +LL | impl !Clone for &mut MyType {} + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | + = note: conflicting implementation in crate `core`: + - impl !Clone for &mut T + where T: ?Sized; + +error: aborting due to 1 previous error + +For more information about this error, try `rustc --explain E0119`. diff --git a/tests/ui/const-generics/issues/issue-100313.rs b/tests/ui/const-generics/issues/issue-100313.rs index e07fde76a4a..553165f90b8 100644 --- a/tests/ui/const-generics/issues/issue-100313.rs +++ b/tests/ui/const-generics/issues/issue-100313.rs @@ -1,5 +1,4 @@ #![allow(incomplete_features)] -#![feature(const_mut_refs)] #![feature(adt_const_params, unsized_const_params)] struct T; diff --git a/tests/ui/const-generics/issues/issue-100313.stderr b/tests/ui/const-generics/issues/issue-100313.stderr index a422764fe2c..6e419078e5e 100644 --- a/tests/ui/const-generics/issues/issue-100313.stderr +++ b/tests/ui/const-generics/issues/issue-100313.stderr @@ -1,16 +1,16 @@ error[E0080]: evaluation of constant value failed - --> $DIR/issue-100313.rs:10:13 + --> $DIR/issue-100313.rs:9:13 | LL | *(B as *const bool as *mut bool) = false; | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ writing to ALLOC0 which is read-only | note: inside `T::<&true>::set_false` - --> $DIR/issue-100313.rs:10:13 + --> $DIR/issue-100313.rs:9:13 | LL | *(B as *const bool as *mut bool) = false; | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ note: inside `_` - --> $DIR/issue-100313.rs:18:5 + --> $DIR/issue-100313.rs:17:5 | LL | x.set_false(); | ^^^^^^^^^^^^^ diff --git a/tests/ui/consts/auxiliary/const_mut_refs_crate.rs b/tests/ui/consts/auxiliary/const_mut_refs_crate.rs index 8e78748e896..d8e4b74d73c 100644 --- a/tests/ui/consts/auxiliary/const_mut_refs_crate.rs +++ b/tests/ui/consts/auxiliary/const_mut_refs_crate.rs @@ -10,8 +10,6 @@ // See also ../const-mut-refs-crate.rs for more details // about this test. -#![feature(const_mut_refs)] - // if we used immutable references here, then promotion would // turn the `&42` into a promoted, which gets duplicated arbitrarily. pub static mut FOO: &'static mut i32 = &mut 42; diff --git a/tests/ui/consts/const-address-of-interior-mut.rs b/tests/ui/consts/const-address-of-interior-mut.rs index 930fa0c492f..450f1c4a94e 100644 --- a/tests/ui/consts/const-address-of-interior-mut.rs +++ b/tests/ui/consts/const-address-of-interior-mut.rs @@ -1,14 +1,15 @@ +//@check-pass use std::cell::Cell; -const A: () = { let x = Cell::new(2); &raw const x; }; //~ ERROR interior mutability +const A: () = { let x = Cell::new(2); &raw const x; }; -static B: () = { let x = Cell::new(2); &raw const x; }; //~ ERROR interior mutability +static B: () = { let x = Cell::new(2); &raw const x; }; -static mut C: () = { let x = Cell::new(2); &raw const x; }; //~ ERROR interior mutability +static mut C: () = { let x = Cell::new(2); &raw const x; }; const fn foo() { let x = Cell::new(0); - let y = &raw const x; //~ ERROR interior mutability + let y = &raw const x; } fn main() {} diff --git a/tests/ui/consts/const-address-of-interior-mut.stderr b/tests/ui/consts/const-address-of-interior-mut.stderr deleted file mode 100644 index 203745f0b01..00000000000 --- a/tests/ui/consts/const-address-of-interior-mut.stderr +++ /dev/null @@ -1,43 +0,0 @@ -error[E0658]: cannot borrow here, since the borrowed element may contain interior mutability - --> $DIR/const-address-of-interior-mut.rs:3:39 - | -LL | const A: () = { let x = Cell::new(2); &raw const x; }; - | ^^^^^^^^^^^^ - | - = note: see issue #80384 for more information - = help: add `#![feature(const_refs_to_cell)]` to the crate attributes to enable - = note: this compiler was built on YYYY-MM-DD; consider upgrading it if it is out of date - -error[E0658]: cannot borrow here, since the borrowed element may contain interior mutability - --> $DIR/const-address-of-interior-mut.rs:5:40 - | -LL | static B: () = { let x = Cell::new(2); &raw const x; }; - | ^^^^^^^^^^^^ - | - = note: see issue #80384 for more information - = help: add `#![feature(const_refs_to_cell)]` to the crate attributes to enable - = note: this compiler was built on YYYY-MM-DD; consider upgrading it if it is out of date - -error[E0658]: cannot borrow here, since the borrowed element may contain interior mutability - --> $DIR/const-address-of-interior-mut.rs:7:44 - | -LL | static mut C: () = { let x = Cell::new(2); &raw const x; }; - | ^^^^^^^^^^^^ - | - = note: see issue #80384 for more information - = help: add `#![feature(const_refs_to_cell)]` to the crate attributes to enable - = note: this compiler was built on YYYY-MM-DD; consider upgrading it if it is out of date - -error[E0658]: cannot borrow here, since the borrowed element may contain interior mutability - --> $DIR/const-address-of-interior-mut.rs:11:13 - | -LL | let y = &raw const x; - | ^^^^^^^^^^^^ - | - = note: see issue #80384 for more information - = help: add `#![feature(const_refs_to_cell)]` to the crate attributes to enable - = note: this compiler was built on YYYY-MM-DD; consider upgrading it if it is out of date - -error: aborting due to 4 previous errors - -For more information about this error, try `rustc --explain E0658`. diff --git a/tests/ui/consts/const-address-of-mut.rs b/tests/ui/consts/const-address-of-mut.rs index c3f37843d3c..2dd909b4ce7 100644 --- a/tests/ui/consts/const-address-of-mut.rs +++ b/tests/ui/consts/const-address-of-mut.rs @@ -1,10 +1,12 @@ -const A: () = { let mut x = 2; &raw mut x; }; //~ mutable pointer +//@check-pass -static B: () = { let mut x = 2; &raw mut x; }; //~ mutable pointer +const A: () = { let mut x = 2; &raw mut x; }; + +static B: () = { let mut x = 2; &raw mut x; }; const fn foo() { let mut x = 0; - let y = &raw mut x; //~ mutable pointer + let y = &raw mut x; } fn main() {} diff --git a/tests/ui/consts/const-address-of-mut.stderr b/tests/ui/consts/const-address-of-mut.stderr deleted file mode 100644 index d4243485de1..00000000000 --- a/tests/ui/consts/const-address-of-mut.stderr +++ /dev/null @@ -1,33 +0,0 @@ -error[E0658]: raw mutable pointers are not allowed in constants - --> $DIR/const-address-of-mut.rs:1:32 - | -LL | const A: () = { let mut x = 2; &raw mut x; }; - | ^^^^^^^^^^ - | - = note: see issue #57349 for more information - = help: add `#![feature(const_mut_refs)]` to the crate attributes to enable - = note: this compiler was built on YYYY-MM-DD; consider upgrading it if it is out of date - -error[E0658]: raw mutable pointers are not allowed in statics - --> $DIR/const-address-of-mut.rs:3:33 - | -LL | static B: () = { let mut x = 2; &raw mut x; }; - | ^^^^^^^^^^ - | - = note: see issue #57349 for more information - = help: add `#![feature(const_mut_refs)]` to the crate attributes to enable - = note: this compiler was built on YYYY-MM-DD; consider upgrading it if it is out of date - -error[E0658]: raw mutable pointers are not allowed in constant functions - --> $DIR/const-address-of-mut.rs:7:13 - | -LL | let y = &raw mut x; - | ^^^^^^^^^^ - | - = note: see issue #57349 for more information - = help: add `#![feature(const_mut_refs)]` to the crate attributes to enable - = note: this compiler was built on YYYY-MM-DD; consider upgrading it if it is out of date - -error: aborting due to 3 previous errors - -For more information about this error, try `rustc --explain E0658`. diff --git a/tests/ui/consts/const-eval/heap/alloc_intrinsic_errors.rs b/tests/ui/consts/const-eval/heap/alloc_intrinsic_errors.rs index ac9e8b64b48..9cf9360dcbd 100644 --- a/tests/ui/consts/const-eval/heap/alloc_intrinsic_errors.rs +++ b/tests/ui/consts/const-eval/heap/alloc_intrinsic_errors.rs @@ -1,6 +1,5 @@ #![feature(core_intrinsics)] #![feature(const_heap)] -#![feature(const_mut_refs)] use std::intrinsics; const FOO: i32 = foo(); diff --git a/tests/ui/consts/const-eval/heap/alloc_intrinsic_errors.stderr b/tests/ui/consts/const-eval/heap/alloc_intrinsic_errors.stderr index cdde14756e4..2fd7222da52 100644 --- a/tests/ui/consts/const-eval/heap/alloc_intrinsic_errors.stderr +++ b/tests/ui/consts/const-eval/heap/alloc_intrinsic_errors.stderr @@ -1,16 +1,16 @@ error[E0080]: evaluation of constant value failed - --> $DIR/alloc_intrinsic_errors.rs:9:17 + --> $DIR/alloc_intrinsic_errors.rs:8:17 | LL | let _ = intrinsics::const_allocate(4, 3) as *mut i32; | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ invalid align passed to `const_allocate`: 3 is not a power of 2 | note: inside `foo` - --> $DIR/alloc_intrinsic_errors.rs:9:17 + --> $DIR/alloc_intrinsic_errors.rs:8:17 | LL | let _ = intrinsics::const_allocate(4, 3) as *mut i32; | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ note: inside `FOO` - --> $DIR/alloc_intrinsic_errors.rs:6:18 + --> $DIR/alloc_intrinsic_errors.rs:5:18 | LL | const FOO: i32 = foo(); | ^^^^^ diff --git a/tests/ui/consts/const-eval/heap/alloc_intrinsic_nontransient.rs b/tests/ui/consts/const-eval/heap/alloc_intrinsic_nontransient.rs index 0c292ec5af7..83ed496ac2c 100644 --- a/tests/ui/consts/const-eval/heap/alloc_intrinsic_nontransient.rs +++ b/tests/ui/consts/const-eval/heap/alloc_intrinsic_nontransient.rs @@ -1,7 +1,6 @@ //@ run-pass #![feature(core_intrinsics)] #![feature(const_heap)] -#![feature(const_mut_refs)] use std::intrinsics; const FOO: &i32 = foo(); diff --git a/tests/ui/consts/const-eval/heap/alloc_intrinsic_transient.rs b/tests/ui/consts/const-eval/heap/alloc_intrinsic_transient.rs index 1ba20f908ea..69e980eb13d 100644 --- a/tests/ui/consts/const-eval/heap/alloc_intrinsic_transient.rs +++ b/tests/ui/consts/const-eval/heap/alloc_intrinsic_transient.rs @@ -1,7 +1,6 @@ //@ run-pass #![feature(core_intrinsics)] #![feature(const_heap)] -#![feature(const_mut_refs)] use std::intrinsics; const FOO: i32 = foo(); diff --git a/tests/ui/consts/const-eval/heap/alloc_intrinsic_uninit.32bit.stderr b/tests/ui/consts/const-eval/heap/alloc_intrinsic_uninit.32bit.stderr index 383c167d3c0..271c8611091 100644 --- a/tests/ui/consts/const-eval/heap/alloc_intrinsic_uninit.32bit.stderr +++ b/tests/ui/consts/const-eval/heap/alloc_intrinsic_uninit.32bit.stderr @@ -1,5 +1,5 @@ error[E0080]: it is undefined behavior to use this value - --> $DIR/alloc_intrinsic_uninit.rs:8:1 + --> $DIR/alloc_intrinsic_uninit.rs:7:1 | LL | const BAR: &i32 = unsafe { &*(intrinsics::const_allocate(4, 4) as *mut i32) }; | ^^^^^^^^^^^^^^^ constructing invalid value at .: encountered uninitialized memory, but expected an integer diff --git a/tests/ui/consts/const-eval/heap/alloc_intrinsic_uninit.64bit.stderr b/tests/ui/consts/const-eval/heap/alloc_intrinsic_uninit.64bit.stderr index d0679228326..ec7cc7d4140 100644 --- a/tests/ui/consts/const-eval/heap/alloc_intrinsic_uninit.64bit.stderr +++ b/tests/ui/consts/const-eval/heap/alloc_intrinsic_uninit.64bit.stderr @@ -1,5 +1,5 @@ error[E0080]: it is undefined behavior to use this value - --> $DIR/alloc_intrinsic_uninit.rs:8:1 + --> $DIR/alloc_intrinsic_uninit.rs:7:1 | LL | const BAR: &i32 = unsafe { &*(intrinsics::const_allocate(4, 4) as *mut i32) }; | ^^^^^^^^^^^^^^^ constructing invalid value at .: encountered uninitialized memory, but expected an integer diff --git a/tests/ui/consts/const-eval/heap/alloc_intrinsic_uninit.rs b/tests/ui/consts/const-eval/heap/alloc_intrinsic_uninit.rs index ed483bccc1f..c283a5fae7d 100644 --- a/tests/ui/consts/const-eval/heap/alloc_intrinsic_uninit.rs +++ b/tests/ui/consts/const-eval/heap/alloc_intrinsic_uninit.rs @@ -2,7 +2,6 @@ // compile-test #![feature(core_intrinsics)] #![feature(const_heap)] -#![feature(const_mut_refs)] use std::intrinsics; const BAR: &i32 = unsafe { &*(intrinsics::const_allocate(4, 4) as *mut i32) }; diff --git a/tests/ui/consts/const-eval/heap/alloc_intrinsic_untyped.rs b/tests/ui/consts/const-eval/heap/alloc_intrinsic_untyped.rs index 7be14e3cff7..26cb69e458b 100644 --- a/tests/ui/consts/const-eval/heap/alloc_intrinsic_untyped.rs +++ b/tests/ui/consts/const-eval/heap/alloc_intrinsic_untyped.rs @@ -1,9 +1,8 @@ // We unleash Miri here since this test demonstrates code that bypasses the checks against interning -// mutable pointers, which currently ICEs. Unleashing Miri silence the ICE. +// mutable pointers, which currently ICEs. Unleashing Miri silences the ICE. //@ compile-flags: -Zunleash-the-miri-inside-of-you #![feature(core_intrinsics)] #![feature(const_heap)] -#![feature(const_mut_refs)] use std::intrinsics; const BAR: *mut i32 = unsafe { intrinsics::const_allocate(4, 4) as *mut i32 }; diff --git a/tests/ui/consts/const-eval/heap/alloc_intrinsic_untyped.stderr b/tests/ui/consts/const-eval/heap/alloc_intrinsic_untyped.stderr index 119198bd347..0dc49dc3cd8 100644 --- a/tests/ui/consts/const-eval/heap/alloc_intrinsic_untyped.stderr +++ b/tests/ui/consts/const-eval/heap/alloc_intrinsic_untyped.stderr @@ -1,5 +1,5 @@ error: encountered mutable pointer in final value of constant - --> $DIR/alloc_intrinsic_untyped.rs:9:1 + --> $DIR/alloc_intrinsic_untyped.rs:8:1 | LL | const BAR: *mut i32 = unsafe { intrinsics::const_allocate(4, 4) as *mut i32 }; | ^^^^^^^^^^^^^^^^^^^ diff --git a/tests/ui/consts/const-eval/heap/dealloc_intrinsic.rs b/tests/ui/consts/const-eval/heap/dealloc_intrinsic.rs index 345fc096ca1..3cc035c66d3 100644 --- a/tests/ui/consts/const-eval/heap/dealloc_intrinsic.rs +++ b/tests/ui/consts/const-eval/heap/dealloc_intrinsic.rs @@ -1,7 +1,6 @@ //@ run-pass #![feature(core_intrinsics)] #![feature(const_heap)] -#![feature(const_mut_refs)] use std::intrinsics; diff --git a/tests/ui/consts/const-eval/heap/dealloc_intrinsic_dangling.rs b/tests/ui/consts/const-eval/heap/dealloc_intrinsic_dangling.rs index da7ab7f8ba4..3054e79770d 100644 --- a/tests/ui/consts/const-eval/heap/dealloc_intrinsic_dangling.rs +++ b/tests/ui/consts/const-eval/heap/dealloc_intrinsic_dangling.rs @@ -1,6 +1,5 @@ #![feature(core_intrinsics)] #![feature(const_heap)] -#![feature(const_mut_refs)] // Strip out raw byte dumps to make comparison platform-independent: //@ normalize-stderr-test: "(the raw bytes of the constant) \(size: [0-9]*, align: [0-9]*\)" -> "$1 (size: $$SIZE, align: $$ALIGN)" diff --git a/tests/ui/consts/const-eval/heap/dealloc_intrinsic_dangling.stderr b/tests/ui/consts/const-eval/heap/dealloc_intrinsic_dangling.stderr index a42c26c0a8d..0b0d2676dd3 100644 --- a/tests/ui/consts/const-eval/heap/dealloc_intrinsic_dangling.stderr +++ b/tests/ui/consts/const-eval/heap/dealloc_intrinsic_dangling.stderr @@ -1,5 +1,5 @@ error[E0080]: it is undefined behavior to use this value - --> $DIR/dealloc_intrinsic_dangling.rs:12:1 + --> $DIR/dealloc_intrinsic_dangling.rs:11:1 | LL | const _X: &'static u8 = unsafe { | ^^^^^^^^^^^^^^^^^^^^^ constructing invalid value: encountered a dangling reference (use-after-free) @@ -10,7 +10,7 @@ LL | const _X: &'static u8 = unsafe { } error[E0080]: evaluation of constant value failed - --> $DIR/dealloc_intrinsic_dangling.rs:23:5 + --> $DIR/dealloc_intrinsic_dangling.rs:22:5 | LL | *reference | ^^^^^^^^^^ memory access failed: ALLOC1 has been freed, so this pointer is dangling diff --git a/tests/ui/consts/const-eval/issue-114994-fail.rs b/tests/ui/consts/const-eval/issue-114994-fail.rs deleted file mode 100644 index 1b9abec3571..00000000000 --- a/tests/ui/consts/const-eval/issue-114994-fail.rs +++ /dev/null @@ -1,14 +0,0 @@ -// This checks that function pointer signatures that are referenced mutably -// but contain a &mut T parameter still fail in a constant context: see issue #114994. -// -//@ check-fail - -const fn use_mut_const_fn(_f: &mut fn(&mut String)) { //~ ERROR mutable references are not allowed in constant functions - () -} - -const fn use_mut_const_tuple_fn(_f: (fn(), &mut u32)) { //~ ERROR mutable references are not allowed in constant functions - -} - -fn main() {} diff --git a/tests/ui/consts/const-eval/issue-114994-fail.stderr b/tests/ui/consts/const-eval/issue-114994-fail.stderr deleted file mode 100644 index 70b224b9b4c..00000000000 --- a/tests/ui/consts/const-eval/issue-114994-fail.stderr +++ /dev/null @@ -1,23 +0,0 @@ -error[E0658]: mutable references are not allowed in constant functions - --> $DIR/issue-114994-fail.rs:6:27 - | -LL | const fn use_mut_const_fn(_f: &mut fn(&mut String)) { - | ^^ - | - = note: see issue #57349 for more information - = help: add `#![feature(const_mut_refs)]` to the crate attributes to enable - = note: this compiler was built on YYYY-MM-DD; consider upgrading it if it is out of date - -error[E0658]: mutable references are not allowed in constant functions - --> $DIR/issue-114994-fail.rs:10:33 - | -LL | const fn use_mut_const_tuple_fn(_f: (fn(), &mut u32)) { - | ^^ - | - = note: see issue #57349 for more information - = help: add `#![feature(const_mut_refs)]` to the crate attributes to enable - = note: this compiler was built on YYYY-MM-DD; consider upgrading it if it is out of date - -error: aborting due to 2 previous errors - -For more information about this error, try `rustc --explain E0658`. diff --git a/tests/ui/consts/const-eval/issue-114994.rs b/tests/ui/consts/const-eval/issue-114994.rs deleted file mode 100644 index 5d99f265e62..00000000000 --- a/tests/ui/consts/const-eval/issue-114994.rs +++ /dev/null @@ -1,18 +0,0 @@ -// This checks that function pointer signatures containing &mut T types -// work in a constant context: see issue #114994. -// -//@ check-pass - -const fn use_const_fn(_f: fn(&mut String)) { - () -} - -const fn get_some_fn() -> fn(&mut String) { - String::clear -} - -const fn some_const_fn() { - let _f: fn(&mut String) = String::clear; -} - -fn main() {} diff --git a/tests/ui/consts/const-eval/issue-65394.rs b/tests/ui/consts/const-eval/issue-65394.rs index e6639826cb2..2304dbebc7e 100644 --- a/tests/ui/consts/const-eval/issue-65394.rs +++ b/tests/ui/consts/const-eval/issue-65394.rs @@ -1,11 +1,16 @@ +//@ revisions: stock precise_drops +//@[precise_drops] check-pass + // This test originated from #65394. We conservatively assume that `x` is still `LiveDrop` even // after it has been moved because a mutable reference to it exists at some point in the const body. // -// We will likely have to change this behavior before we allow `&mut` in a `const`. +// With `&mut` in `const` being stable, this surprising behavior is now observable. +// `const_precise_live_drops` fixes that. +#![cfg_attr(precise_drops, feature(const_precise_live_drops))] const _: Vec = { - let mut x = Vec::::new(); //~ ERROR destructor of - let r = &mut x; //~ ERROR mutable references are not allowed in constants + let mut x = Vec::::new(); //[stock]~ ERROR destructor of + let r = &mut x; let y = x; y }; diff --git a/tests/ui/consts/const-eval/issue-65394.stderr b/tests/ui/consts/const-eval/issue-65394.stderr deleted file mode 100644 index 1fa4da4a78b..00000000000 --- a/tests/ui/consts/const-eval/issue-65394.stderr +++ /dev/null @@ -1,23 +0,0 @@ -error[E0658]: mutable references are not allowed in constants - --> $DIR/issue-65394.rs:8:13 - | -LL | let r = &mut x; - | ^^^^^^ - | - = note: see issue #57349 for more information - = help: add `#![feature(const_mut_refs)]` to the crate attributes to enable - = note: this compiler was built on YYYY-MM-DD; consider upgrading it if it is out of date - -error[E0493]: destructor of `Vec` cannot be evaluated at compile-time - --> $DIR/issue-65394.rs:7:9 - | -LL | let mut x = Vec::::new(); - | ^^^^^ the destructor for this type cannot be evaluated in constants -... -LL | }; - | - value is dropped here - -error: aborting due to 2 previous errors - -Some errors have detailed explanations: E0493, E0658. -For more information about an error, try `rustc --explain E0493`. diff --git a/tests/ui/consts/const-eval/issue-65394.stock.stderr b/tests/ui/consts/const-eval/issue-65394.stock.stderr new file mode 100644 index 00000000000..f33593862a7 --- /dev/null +++ b/tests/ui/consts/const-eval/issue-65394.stock.stderr @@ -0,0 +1,12 @@ +error[E0493]: destructor of `Vec` cannot be evaluated at compile-time + --> $DIR/issue-65394.rs:12:9 + | +LL | let mut x = Vec::::new(); + | ^^^^^ the destructor for this type cannot be evaluated in constants +... +LL | }; + | - value is dropped here + +error: aborting due to 1 previous error + +For more information about this error, try `rustc --explain E0493`. diff --git a/tests/ui/consts/const-eval/mod-static-with-const-fn.rs b/tests/ui/consts/const-eval/mod-static-with-const-fn.rs index b6b74e67d20..7de9d44305d 100644 --- a/tests/ui/consts/const-eval/mod-static-with-const-fn.rs +++ b/tests/ui/consts/const-eval/mod-static-with-const-fn.rs @@ -1,8 +1,6 @@ // New test for #53818: modifying static memory at compile-time is not allowed. // The test should never compile successfully -#![feature(const_mut_refs)] - use std::cell::UnsafeCell; struct Foo(UnsafeCell); diff --git a/tests/ui/consts/const-eval/mod-static-with-const-fn.stderr b/tests/ui/consts/const-eval/mod-static-with-const-fn.stderr index 901ae1922c7..47bfc235a1a 100644 --- a/tests/ui/consts/const-eval/mod-static-with-const-fn.stderr +++ b/tests/ui/consts/const-eval/mod-static-with-const-fn.stderr @@ -1,5 +1,5 @@ error[E0080]: could not evaluate static initializer - --> $DIR/mod-static-with-const-fn.rs:16:5 + --> $DIR/mod-static-with-const-fn.rs:14:5 | LL | *FOO.0.get() = 5; | ^^^^^^^^^^^^^^^^ modifying a static's initial value from another static's initializer diff --git a/tests/ui/consts/const-eval/nrvo.rs b/tests/ui/consts/const-eval/nrvo.rs index 02288d8d60c..e37fe2d8238 100644 --- a/tests/ui/consts/const-eval/nrvo.rs +++ b/tests/ui/consts/const-eval/nrvo.rs @@ -4,8 +4,6 @@ // its address may be taken and it may be written to indirectly. Ensure that the const-eval // interpreter can handle this. -#![feature(const_mut_refs)] - #[inline(never)] // Try to ensure that MIR optimizations don't optimize this away. const fn init(buf: &mut [u8; 1024]) { buf[33] = 3; diff --git a/tests/ui/consts/const-eval/partial_ptr_overwrite.rs b/tests/ui/consts/const-eval/partial_ptr_overwrite.rs index d6c76886853..1e99d84bba4 100644 --- a/tests/ui/consts/const-eval/partial_ptr_overwrite.rs +++ b/tests/ui/consts/const-eval/partial_ptr_overwrite.rs @@ -1,5 +1,4 @@ // Test for the behavior described in . -#![feature(const_mut_refs)] const PARTIAL_OVERWRITE: () = { let mut p = &42; diff --git a/tests/ui/consts/const-eval/partial_ptr_overwrite.stderr b/tests/ui/consts/const-eval/partial_ptr_overwrite.stderr index 3203ca764bb..1443d353848 100644 --- a/tests/ui/consts/const-eval/partial_ptr_overwrite.stderr +++ b/tests/ui/consts/const-eval/partial_ptr_overwrite.stderr @@ -1,5 +1,5 @@ error[E0080]: evaluation of constant value failed - --> $DIR/partial_ptr_overwrite.rs:8:9 + --> $DIR/partial_ptr_overwrite.rs:7:9 | LL | *(ptr as *mut u8) = 123; | ^^^^^^^^^^^^^^^^^^^^^^^ unable to overwrite parts of a pointer in memory at ALLOC0 diff --git a/tests/ui/consts/const-eval/raw-pointer-ub.rs b/tests/ui/consts/const-eval/raw-pointer-ub.rs index 5aced5b1bd6..3320e627812 100644 --- a/tests/ui/consts/const-eval/raw-pointer-ub.rs +++ b/tests/ui/consts/const-eval/raw-pointer-ub.rs @@ -1,4 +1,4 @@ -#![feature(const_mut_refs, const_intrinsic_copy)] +#![feature(const_intrinsic_copy)] const MISALIGNED_LOAD: () = unsafe { diff --git a/tests/ui/consts/const-eval/transmute-const.64bit.stderr b/tests/ui/consts/const-eval/transmute-const.64bit.stderr deleted file mode 100644 index 35a5cabaa67..00000000000 --- a/tests/ui/consts/const-eval/transmute-const.64bit.stderr +++ /dev/null @@ -1,14 +0,0 @@ -error[E0080]: it is undefined behavior to use this value - --> $DIR/transmute-const.rs:4:1 - | -LL | static FOO: bool = unsafe { mem::transmute(3u8) }; - | ^^^^^^^^^^^^^^^^ constructing invalid value: encountered 0x03, but expected a boolean - | - = note: The rules on what exactly is undefined behavior aren't clear, so this check might be overzealous. Please open an issue on the rustc repository if you believe it should not be considered undefined behavior. - = note: the raw bytes of the constant (size: 1, align: 1) { - 03 │ . - } - -error: aborting due to 1 previous error - -For more information about this error, try `rustc --explain E0080`. diff --git a/tests/ui/consts/const-eval/transmute-const.rs b/tests/ui/consts/const-eval/transmute-const.rs index bf25b52ed66..1cfad00ca76 100644 --- a/tests/ui/consts/const-eval/transmute-const.rs +++ b/tests/ui/consts/const-eval/transmute-const.rs @@ -1,4 +1,3 @@ -//@ stderr-per-bitwidth use std::mem; static FOO: bool = unsafe { mem::transmute(3u8) }; diff --git a/tests/ui/consts/const-eval/transmute-const.32bit.stderr b/tests/ui/consts/const-eval/transmute-const.stderr similarity index 95% rename from tests/ui/consts/const-eval/transmute-const.32bit.stderr rename to tests/ui/consts/const-eval/transmute-const.stderr index 35a5cabaa67..d72289487d7 100644 --- a/tests/ui/consts/const-eval/transmute-const.32bit.stderr +++ b/tests/ui/consts/const-eval/transmute-const.stderr @@ -1,5 +1,5 @@ error[E0080]: it is undefined behavior to use this value - --> $DIR/transmute-const.rs:4:1 + --> $DIR/transmute-const.rs:3:1 | LL | static FOO: bool = unsafe { mem::transmute(3u8) }; | ^^^^^^^^^^^^^^^^ constructing invalid value: encountered 0x03, but expected a boolean diff --git a/tests/ui/consts/const-eval/ub-enum-overwrite.rs b/tests/ui/consts/const-eval/ub-enum-overwrite.rs index 086a1001d11..69f1d01b2f3 100644 --- a/tests/ui/consts/const-eval/ub-enum-overwrite.rs +++ b/tests/ui/consts/const-eval/ub-enum-overwrite.rs @@ -1,5 +1,3 @@ -#![feature(const_mut_refs)] - enum E { A(u8), B, diff --git a/tests/ui/consts/const-eval/ub-enum-overwrite.stderr b/tests/ui/consts/const-eval/ub-enum-overwrite.stderr index 2a133c057b3..315e865df93 100644 --- a/tests/ui/consts/const-eval/ub-enum-overwrite.stderr +++ b/tests/ui/consts/const-eval/ub-enum-overwrite.stderr @@ -1,5 +1,5 @@ error[E0080]: evaluation of constant value failed - --> $DIR/ub-enum-overwrite.rs:13:14 + --> $DIR/ub-enum-overwrite.rs:11:14 | LL | unsafe { *p } | ^^ using uninitialized data, but this operation requires initialized memory diff --git a/tests/ui/consts/const-eval/ub-write-through-immutable.rs b/tests/ui/consts/const-eval/ub-write-through-immutable.rs index 9860b8fde4a..d3ae2d81884 100644 --- a/tests/ui/consts/const-eval/ub-write-through-immutable.rs +++ b/tests/ui/consts/const-eval/ub-write-through-immutable.rs @@ -1,5 +1,4 @@ //! Ensure we catch UB due to writing through a shared reference. -#![feature(const_mut_refs, const_refs_to_cell)] #![allow(invalid_reference_casting)] use std::mem; diff --git a/tests/ui/consts/const-eval/ub-write-through-immutable.stderr b/tests/ui/consts/const-eval/ub-write-through-immutable.stderr index dbcd35e0b88..d30df33bc55 100644 --- a/tests/ui/consts/const-eval/ub-write-through-immutable.stderr +++ b/tests/ui/consts/const-eval/ub-write-through-immutable.stderr @@ -1,11 +1,11 @@ error[E0080]: evaluation of constant value failed - --> $DIR/ub-write-through-immutable.rs:11:5 + --> $DIR/ub-write-through-immutable.rs:10:5 | LL | *ptr = 0; | ^^^^^^^^ writing through a pointer that was derived from a shared (immutable) reference error[E0080]: evaluation of constant value failed - --> $DIR/ub-write-through-immutable.rs:18:5 + --> $DIR/ub-write-through-immutable.rs:17:5 | LL | *ptr = 0; | ^^^^^^^^ writing through a pointer that was derived from a shared (immutable) reference diff --git a/tests/ui/consts/const-eval/unwind-abort.rs b/tests/ui/consts/const-eval/unwind-abort.rs index 26113e23888..8d5ed876e43 100644 --- a/tests/ui/consts/const-eval/unwind-abort.rs +++ b/tests/ui/consts/const-eval/unwind-abort.rs @@ -1,5 +1,3 @@ -#![feature(const_extern_fn)] - const extern "C" fn foo() { panic!() //~ ERROR evaluation of constant value failed } diff --git a/tests/ui/consts/const-eval/unwind-abort.stderr b/tests/ui/consts/const-eval/unwind-abort.stderr index d7330beca7b..340f1dbe841 100644 --- a/tests/ui/consts/const-eval/unwind-abort.stderr +++ b/tests/ui/consts/const-eval/unwind-abort.stderr @@ -1,16 +1,16 @@ error[E0080]: evaluation of constant value failed - --> $DIR/unwind-abort.rs:4:5 + --> $DIR/unwind-abort.rs:2:5 | LL | panic!() - | ^^^^^^^^ the evaluated program panicked at 'explicit panic', $DIR/unwind-abort.rs:4:5 + | ^^^^^^^^ the evaluated program panicked at 'explicit panic', $DIR/unwind-abort.rs:2:5 | note: inside `foo` - --> $DIR/unwind-abort.rs:4:5 + --> $DIR/unwind-abort.rs:2:5 | LL | panic!() | ^^^^^^^^ note: inside `_` - --> $DIR/unwind-abort.rs:7:15 + --> $DIR/unwind-abort.rs:5:15 | LL | const _: () = foo(); | ^^^^^ diff --git a/tests/ui/consts/const-extern-fn/const-extern-fn-call-extern-fn.rs b/tests/ui/consts/const-extern-fn/const-extern-fn-call-extern-fn.rs index eccda49db3e..31c15400f84 100644 --- a/tests/ui/consts/const-extern-fn/const-extern-fn-call-extern-fn.rs +++ b/tests/ui/consts/const-extern-fn/const-extern-fn-call-extern-fn.rs @@ -1,5 +1,3 @@ -#![feature(const_extern_fn)] - extern "C" { fn regular_in_block(); } diff --git a/tests/ui/consts/const-extern-fn/const-extern-fn-call-extern-fn.stderr b/tests/ui/consts/const-extern-fn/const-extern-fn-call-extern-fn.stderr index 5acf22e4bc6..5d37f524e03 100644 --- a/tests/ui/consts/const-extern-fn/const-extern-fn-call-extern-fn.stderr +++ b/tests/ui/consts/const-extern-fn/const-extern-fn-call-extern-fn.stderr @@ -1,5 +1,5 @@ error[E0015]: cannot call non-const fn `regular_in_block` in constant functions - --> $DIR/const-extern-fn-call-extern-fn.rs:9:9 + --> $DIR/const-extern-fn-call-extern-fn.rs:7:9 | LL | regular_in_block(); | ^^^^^^^^^^^^^^^^^^ @@ -7,7 +7,7 @@ LL | regular_in_block(); = note: calls in constant functions are limited to constant functions, tuple structs and tuple variants error[E0015]: cannot call non-const fn `regular` in constant functions - --> $DIR/const-extern-fn-call-extern-fn.rs:18:9 + --> $DIR/const-extern-fn-call-extern-fn.rs:16:9 | LL | regular(); | ^^^^^^^^^ diff --git a/tests/ui/consts/const-extern-fn/const-extern-fn-min-const-fn.rs b/tests/ui/consts/const-extern-fn/const-extern-fn-min-const-fn.rs index efc0a1c2fba..73b6dd51db7 100644 --- a/tests/ui/consts/const-extern-fn/const-extern-fn-min-const-fn.rs +++ b/tests/ui/consts/const-extern-fn/const-extern-fn-min-const-fn.rs @@ -1,7 +1,6 @@ -#![feature(const_extern_fn)] - -const extern "C" fn ptr_cast(val: *const u8) { val as usize; } -//~^ ERROR pointers cannot be cast to integers - +const extern "C" fn ptr_cast(val: *const u8) { + val as usize; + //~^ ERROR pointers cannot be cast to integers +} fn main() {} diff --git a/tests/ui/consts/const-extern-fn/const-extern-fn-min-const-fn.stderr b/tests/ui/consts/const-extern-fn/const-extern-fn-min-const-fn.stderr index 9cdeec159be..7c21b1b606e 100644 --- a/tests/ui/consts/const-extern-fn/const-extern-fn-min-const-fn.stderr +++ b/tests/ui/consts/const-extern-fn/const-extern-fn-min-const-fn.stderr @@ -1,8 +1,8 @@ error: pointers cannot be cast to integers during const eval - --> $DIR/const-extern-fn-min-const-fn.rs:3:48 + --> $DIR/const-extern-fn-min-const-fn.rs:2:5 | -LL | const extern "C" fn ptr_cast(val: *const u8) { val as usize; } - | ^^^^^^^^^^^^ +LL | val as usize; + | ^^^^^^^^^^^^ | = note: at compile-time, pointers do not have an integer value = note: avoiding this restriction via `transmute`, `union`, or raw pointers leads to compile-time undefined behavior diff --git a/tests/ui/consts/const-extern-fn/const-extern-fn-requires-unsafe.rs b/tests/ui/consts/const-extern-fn/const-extern-fn-requires-unsafe.rs index 95fb9ef4260..a77ee293820 100644 --- a/tests/ui/consts/const-extern-fn/const-extern-fn-requires-unsafe.rs +++ b/tests/ui/consts/const-extern-fn/const-extern-fn-requires-unsafe.rs @@ -1,12 +1,18 @@ -#![feature(const_extern_fn)] - const unsafe extern "C" fn foo() -> usize { 5 } +const unsafe extern "C-unwind" fn bar() -> usize { + 5 +} + fn main() { let a: [u8; foo()]; //~^ call to unsafe function `foo` is unsafe and requires unsafe function or block foo(); //~^ ERROR call to unsafe function `foo` is unsafe and requires unsafe function or block + let b: [u8; bar()]; + //~^ call to unsafe function `bar` is unsafe and requires unsafe function or block + bar(); + //~^ ERROR call to unsafe function `bar` is unsafe and requires unsafe function or block } diff --git a/tests/ui/consts/const-extern-fn/const-extern-fn-requires-unsafe.stderr b/tests/ui/consts/const-extern-fn/const-extern-fn-requires-unsafe.stderr index 6f59b2f2055..b4c779d59de 100644 --- a/tests/ui/consts/const-extern-fn/const-extern-fn-requires-unsafe.stderr +++ b/tests/ui/consts/const-extern-fn/const-extern-fn-requires-unsafe.stderr @@ -1,19 +1,35 @@ error[E0133]: call to unsafe function `foo` is unsafe and requires unsafe function or block - --> $DIR/const-extern-fn-requires-unsafe.rs:10:5 + --> $DIR/const-extern-fn-requires-unsafe.rs:12:5 | LL | foo(); | ^^^^^ call to unsafe function | = note: consult the function's documentation for information on how to avoid undefined behavior +error[E0133]: call to unsafe function `bar` is unsafe and requires unsafe function or block + --> $DIR/const-extern-fn-requires-unsafe.rs:16:5 + | +LL | bar(); + | ^^^^^ call to unsafe function + | + = note: consult the function's documentation for information on how to avoid undefined behavior + error[E0133]: call to unsafe function `foo` is unsafe and requires unsafe function or block - --> $DIR/const-extern-fn-requires-unsafe.rs:8:17 + --> $DIR/const-extern-fn-requires-unsafe.rs:10:17 | LL | let a: [u8; foo()]; | ^^^^^ call to unsafe function | = note: consult the function's documentation for information on how to avoid undefined behavior -error: aborting due to 2 previous errors +error[E0133]: call to unsafe function `bar` is unsafe and requires unsafe function or block + --> $DIR/const-extern-fn-requires-unsafe.rs:14:17 + | +LL | let b: [u8; bar()]; + | ^^^^^ call to unsafe function + | + = note: consult the function's documentation for information on how to avoid undefined behavior + +error: aborting due to 4 previous errors For more information about this error, try `rustc --explain E0133`. diff --git a/tests/ui/consts/const-extern-fn/const-extern-fn.rs b/tests/ui/consts/const-extern-fn/const-extern-fn.rs index 4b164767064..75ffa783a11 100644 --- a/tests/ui/consts/const-extern-fn/const-extern-fn.rs +++ b/tests/ui/consts/const-extern-fn/const-extern-fn.rs @@ -1,5 +1,4 @@ //@ run-pass -#![feature(const_extern_fn)] const extern "C" fn foo1(val: u8) -> u8 { val + 1 @@ -47,6 +46,10 @@ fn main() { let _bar2_cast: unsafe extern "C" fn(bool) -> bool = bar2; unsize(&[0, 1, 2]); - unsafe { closure(); } - unsafe { use_float(); } + unsafe { + closure(); + } + unsafe { + use_float(); + } } diff --git a/tests/ui/consts/const-extern-fn/feature-gate-const_extern_fn.rs b/tests/ui/consts/const-extern-fn/feature-gate-const_extern_fn.rs deleted file mode 100644 index f7bed91b037..00000000000 --- a/tests/ui/consts/const-extern-fn/feature-gate-const_extern_fn.rs +++ /dev/null @@ -1,13 +0,0 @@ -// Check that `const extern fn` and `const unsafe extern fn` are feature-gated -// for certain ABIs. - -const extern fn foo1() {} -const extern "C" fn foo2() {} -const extern "Rust" fn foo3() {} -const extern "cdecl" fn foo4() {} //~ ERROR `cdecl` as a `const fn` ABI is unstable -const unsafe extern fn bar1() {} -const unsafe extern "C" fn bar2() {} -const unsafe extern "Rust" fn bar3() {} -const unsafe extern "cdecl" fn bar4() {} //~ ERROR `cdecl` as a `const fn` ABI is unstable - -fn main() {} diff --git a/tests/ui/consts/const-extern-fn/feature-gate-const_extern_fn.stderr b/tests/ui/consts/const-extern-fn/feature-gate-const_extern_fn.stderr deleted file mode 100644 index 81fb62e10a7..00000000000 --- a/tests/ui/consts/const-extern-fn/feature-gate-const_extern_fn.stderr +++ /dev/null @@ -1,23 +0,0 @@ -error[E0658]: `cdecl` as a `const fn` ABI is unstable - --> $DIR/feature-gate-const_extern_fn.rs:7:14 - | -LL | const extern "cdecl" fn foo4() {} - | ^^^^^^^ - | - = note: see issue #64926 for more information - = help: add `#![feature(const_extern_fn)]` to the crate attributes to enable - = note: this compiler was built on YYYY-MM-DD; consider upgrading it if it is out of date - -error[E0658]: `cdecl` as a `const fn` ABI is unstable - --> $DIR/feature-gate-const_extern_fn.rs:11:21 - | -LL | const unsafe extern "cdecl" fn bar4() {} - | ^^^^^^^ - | - = note: see issue #64926 for more information - = help: add `#![feature(const_extern_fn)]` to the crate attributes to enable - = note: this compiler was built on YYYY-MM-DD; consider upgrading it if it is out of date - -error: aborting due to 2 previous errors - -For more information about this error, try `rustc --explain E0658`. diff --git a/tests/ui/consts/const-fn-error.rs b/tests/ui/consts/const-fn-error.rs index 50b7ce1f8c0..42061ef0670 100644 --- a/tests/ui/consts/const-fn-error.rs +++ b/tests/ui/consts/const-fn-error.rs @@ -5,7 +5,6 @@ const fn f(x: usize) -> usize { for i in 0..x { //~^ ERROR cannot convert //~| ERROR `for` is not allowed in a `const fn` - //~| ERROR mutable references are not allowed in constant functions //~| ERROR cannot call non-const fn sum += i; } diff --git a/tests/ui/consts/const-fn-error.stderr b/tests/ui/consts/const-fn-error.stderr index 14603e433c1..e886a0b4fe4 100644 --- a/tests/ui/consts/const-fn-error.stderr +++ b/tests/ui/consts/const-fn-error.stderr @@ -5,7 +5,6 @@ LL | / for i in 0..x { LL | | LL | | LL | | -LL | | LL | | sum += i; LL | | } | |_____^ @@ -28,16 +27,6 @@ help: add `#![feature(const_trait_impl)]` to the crate attributes to enable LL + #![feature(const_trait_impl)] | -error[E0658]: mutable references are not allowed in constant functions - --> $DIR/const-fn-error.rs:5:14 - | -LL | for i in 0..x { - | ^^^^ - | - = note: see issue #57349 for more information - = help: add `#![feature(const_mut_refs)]` to the crate attributes to enable - = note: this compiler was built on YYYY-MM-DD; consider upgrading it if it is out of date - error[E0015]: cannot call non-const fn ` as Iterator>::next` in constant functions --> $DIR/const-fn-error.rs:5:14 | @@ -50,7 +39,7 @@ help: add `#![feature(const_trait_impl)]` to the crate attributes to enable LL + #![feature(const_trait_impl)] | -error: aborting due to 4 previous errors +error: aborting due to 3 previous errors Some errors have detailed explanations: E0015, E0658. For more information about an error, try `rustc --explain E0015`. diff --git a/tests/ui/consts/const-for-feature-gate.rs b/tests/ui/consts/const-for-feature-gate.rs index c834046c5b0..d74178662b3 100644 --- a/tests/ui/consts/const-for-feature-gate.rs +++ b/tests/ui/consts/const-for-feature-gate.rs @@ -5,7 +5,6 @@ const _: () = { //~^ error: `for` is not allowed in a `const` //~| ERROR: cannot convert //~| ERROR: cannot call - //~| ERROR: mutable references }; fn main() {} diff --git a/tests/ui/consts/const-for-feature-gate.stderr b/tests/ui/consts/const-for-feature-gate.stderr index 0f2f912572e..3344611a60c 100644 --- a/tests/ui/consts/const-for-feature-gate.stderr +++ b/tests/ui/consts/const-for-feature-gate.stderr @@ -22,16 +22,6 @@ help: add `#![feature(const_trait_impl)]` to the crate attributes to enable LL + #![feature(const_trait_impl)] | -error[E0658]: mutable references are not allowed in constants - --> $DIR/const-for-feature-gate.rs:4:14 - | -LL | for _ in 0..5 {} - | ^^^^ - | - = note: see issue #57349 for more information - = help: add `#![feature(const_mut_refs)]` to the crate attributes to enable - = note: this compiler was built on YYYY-MM-DD; consider upgrading it if it is out of date - error[E0015]: cannot call non-const fn ` as Iterator>::next` in constants --> $DIR/const-for-feature-gate.rs:4:14 | @@ -44,7 +34,7 @@ help: add `#![feature(const_trait_impl)]` to the crate attributes to enable LL + #![feature(const_trait_impl)] | -error: aborting due to 4 previous errors +error: aborting due to 3 previous errors Some errors have detailed explanations: E0015, E0658. For more information about an error, try `rustc --explain E0015`. diff --git a/tests/ui/consts/const-for.rs b/tests/ui/consts/const-for.rs index 8db24853558..4f8034e73f0 100644 --- a/tests/ui/consts/const-for.rs +++ b/tests/ui/consts/const-for.rs @@ -1,5 +1,4 @@ #![feature(const_for)] -#![feature(const_mut_refs)] const _: () = { for _ in 0..5 {} diff --git a/tests/ui/consts/const-for.stderr b/tests/ui/consts/const-for.stderr index 8605fb8eef5..2b817c2d20c 100644 --- a/tests/ui/consts/const-for.stderr +++ b/tests/ui/consts/const-for.stderr @@ -1,5 +1,5 @@ error[E0015]: cannot convert `std::ops::Range` into an iterator in constants - --> $DIR/const-for.rs:5:14 + --> $DIR/const-for.rs:4:14 | LL | for _ in 0..5 {} | ^^^^ @@ -13,7 +13,7 @@ LL + #![feature(const_trait_impl)] | error[E0015]: cannot call non-const fn ` as Iterator>::next` in constants - --> $DIR/const-for.rs:5:14 + --> $DIR/const-for.rs:4:14 | LL | for _ in 0..5 {} | ^^^^ diff --git a/tests/ui/consts/const-multi-ref.rs b/tests/ui/consts/const-multi-ref.rs deleted file mode 100644 index 7e0f1a812fd..00000000000 --- a/tests/ui/consts/const-multi-ref.rs +++ /dev/null @@ -1,24 +0,0 @@ -// Ensure that we point the user to the erroneous borrow but not to any subsequent borrows of that -// initial one. - -const _: i32 = { - let mut a = 5; - let p = &mut a; //~ ERROR mutable references are not allowed in constants - - let reborrow = {p}; - let pp = &reborrow; - let ppp = &pp; - ***ppp -}; - -const _: std::cell::Cell = { - let mut a = std::cell::Cell::new(5); - let p = &a; //~ ERROR borrowed element may contain interior mutability - - let reborrow = {p}; - let pp = &reborrow; - let ppp = &pp; - a -}; - -fn main() {} diff --git a/tests/ui/consts/const-multi-ref.stderr b/tests/ui/consts/const-multi-ref.stderr deleted file mode 100644 index 516162194cd..00000000000 --- a/tests/ui/consts/const-multi-ref.stderr +++ /dev/null @@ -1,23 +0,0 @@ -error[E0658]: mutable references are not allowed in constants - --> $DIR/const-multi-ref.rs:6:13 - | -LL | let p = &mut a; - | ^^^^^^ - | - = note: see issue #57349 for more information - = help: add `#![feature(const_mut_refs)]` to the crate attributes to enable - = note: this compiler was built on YYYY-MM-DD; consider upgrading it if it is out of date - -error[E0658]: cannot borrow here, since the borrowed element may contain interior mutability - --> $DIR/const-multi-ref.rs:16:13 - | -LL | let p = &a; - | ^^ - | - = note: see issue #80384 for more information - = help: add `#![feature(const_refs_to_cell)]` to the crate attributes to enable - = note: this compiler was built on YYYY-MM-DD; consider upgrading it if it is out of date - -error: aborting due to 2 previous errors - -For more information about this error, try `rustc --explain E0658`. diff --git a/tests/ui/consts/const-mut-refs-crate.rs b/tests/ui/consts/const-mut-refs-crate.rs index dcc8ff370e1..aca3589720c 100644 --- a/tests/ui/consts/const-mut-refs-crate.rs +++ b/tests/ui/consts/const-mut-refs-crate.rs @@ -1,8 +1,6 @@ //@ run-pass //@ aux-build:const_mut_refs_crate.rs -#![feature(const_mut_refs)] - //! Regression test for https://github.com/rust-lang/rust/issues/79738 //! Show how we are not duplicating allocations anymore. Statics that //! copy their value from another static used to also duplicate diff --git a/tests/ui/consts/const-mut-refs/const_mut_address_of.rs b/tests/ui/consts/const-mut-refs/const_mut_address_of.rs index 437bdc88722..e88a01ec765 100644 --- a/tests/ui/consts/const-mut-refs/const_mut_address_of.rs +++ b/tests/ui/consts/const-mut-refs/const_mut_address_of.rs @@ -1,5 +1,4 @@ //@ check-pass -#![feature(const_mut_refs)] struct Foo { x: usize diff --git a/tests/ui/consts/const-mut-refs/const_mut_refs.rs b/tests/ui/consts/const-mut-refs/const_mut_refs.rs index 1b3091c8dba..2553ad3199f 100644 --- a/tests/ui/consts/const-mut-refs/const_mut_refs.rs +++ b/tests/ui/consts/const-mut-refs/const_mut_refs.rs @@ -1,5 +1,4 @@ //@ check-pass -#![feature(const_mut_refs)] use std::sync::Mutex; diff --git a/tests/ui/consts/const-mut-refs/feature-gate-const_mut_refs.rs b/tests/ui/consts/const-mut-refs/feature-gate-const_mut_refs.rs deleted file mode 100644 index ce9be4ac5c2..00000000000 --- a/tests/ui/consts/const-mut-refs/feature-gate-const_mut_refs.rs +++ /dev/null @@ -1,8 +0,0 @@ -fn main() { - foo(&mut 5); -} - -const fn foo(x: &mut i32) -> i32 { //~ ERROR mutable references - *x + 1 - -} diff --git a/tests/ui/consts/const-mut-refs/feature-gate-const_mut_refs.stderr b/tests/ui/consts/const-mut-refs/feature-gate-const_mut_refs.stderr deleted file mode 100644 index 212d172fe13..00000000000 --- a/tests/ui/consts/const-mut-refs/feature-gate-const_mut_refs.stderr +++ /dev/null @@ -1,13 +0,0 @@ -error[E0658]: mutable references are not allowed in constant functions - --> $DIR/feature-gate-const_mut_refs.rs:5:14 - | -LL | const fn foo(x: &mut i32) -> i32 { - | ^ - | - = note: see issue #57349 for more information - = help: add `#![feature(const_mut_refs)]` to the crate attributes to enable - = note: this compiler was built on YYYY-MM-DD; consider upgrading it if it is out of date - -error: aborting due to 1 previous error - -For more information about this error, try `rustc --explain E0658`. diff --git a/tests/ui/consts/const-mut-refs/issue-76510.rs b/tests/ui/consts/const-mut-refs/issue-76510.rs index 685e3a129c2..6ebbd4e50f6 100644 --- a/tests/ui/consts/const-mut-refs/issue-76510.rs +++ b/tests/ui/consts/const-mut-refs/issue-76510.rs @@ -2,7 +2,6 @@ use std::mem::{transmute, ManuallyDrop}; const S: &'static mut str = &mut " hello "; //~^ ERROR: mutable references are not allowed in the final value of constants -//~| ERROR: mutation through a reference is not allowed in constants const fn trigger() -> [(); unsafe { let s = transmute::<(*const u8, usize), &ManuallyDrop>((S.as_ptr(), 3)); diff --git a/tests/ui/consts/const-mut-refs/issue-76510.stderr b/tests/ui/consts/const-mut-refs/issue-76510.stderr index ab4487026cf..aff86e83578 100644 --- a/tests/ui/consts/const-mut-refs/issue-76510.stderr +++ b/tests/ui/consts/const-mut-refs/issue-76510.stderr @@ -4,17 +4,6 @@ error[E0764]: mutable references are not allowed in the final value of constants LL | const S: &'static mut str = &mut " hello "; | ^^^^^^^^^^^^^^ -error[E0658]: mutation through a reference is not allowed in constants - --> $DIR/issue-76510.rs:3:29 - | -LL | const S: &'static mut str = &mut " hello "; - | ^^^^^^^^^^^^^^ - | - = note: see issue #57349 for more information - = help: add `#![feature(const_mut_refs)]` to the crate attributes to enable - = note: this compiler was built on YYYY-MM-DD; consider upgrading it if it is out of date +error: aborting due to 1 previous error -error: aborting due to 2 previous errors - -Some errors have detailed explanations: E0658, E0764. -For more information about an error, try `rustc --explain E0658`. +For more information about this error, try `rustc --explain E0764`. diff --git a/tests/ui/consts/const-mut-refs/mut_ref_in_final.rs b/tests/ui/consts/const-mut-refs/mut_ref_in_final.rs index 10339ee6798..af7463e6574 100644 --- a/tests/ui/consts/const-mut-refs/mut_ref_in_final.rs +++ b/tests/ui/consts/const-mut-refs/mut_ref_in_final.rs @@ -1,4 +1,9 @@ -#![feature(const_mut_refs)] +//@ normalize-stderr-test: "(the raw bytes of the constant) \(size: [0-9]*, align: [0-9]*\)" -> "$1 (size: $$SIZE, align: $$ALIGN)" +//@ normalize-stderr-test: "( 0x[0-9a-f][0-9a-f] │)? ([0-9a-f][0-9a-f] |__ |╾─*ALLOC[0-9]+(\+[a-z0-9]+)?()?─*╼ )+ *│.*" -> " HEX_DUMP" +//@ normalize-stderr-test: "HEX_DUMP\s*\n\s*HEX_DUMP" -> "HEX_DUMP" + +use std::cell::UnsafeCell; +use std::mem; const NULL: *mut i32 = std::ptr::null_mut(); const A: *const i32 = &4; @@ -17,6 +22,11 @@ const B3: Option<&mut i32> = Some(&mut 42); //~ ERROR temporary value dropped wh const fn helper(x: &mut i32) -> Option<&mut i32> { Some(x) } const B4: Option<&mut i32> = helper(&mut 42); //~ ERROR temporary value dropped while borrowed +// Not ok, since it points to read-only memory. +const IMMUT_MUT_REF: &mut u16 = unsafe { mem::transmute(&13) }; +//~^ ERROR undefined behavior to use this value +//~| pointing to read-only memory + // Ok, because no references to mutable data exist here, since the `{}` moves // its value and then takes a reference to that. const C: *const i32 = &{ @@ -25,7 +35,14 @@ const C: *const i32 = &{ x }; -use std::cell::UnsafeCell; +// Still ok, since `x` will be moved before the final pointer is crated, +// so `_ref` doesn't actually point to the memory that escapes. +const C_NO: *const i32 = &{ + let mut x = 42; + let _ref = &mut x; + x +}; + struct NotAMutex(UnsafeCell); unsafe impl Sync for NotAMutex {} diff --git a/tests/ui/consts/const-mut-refs/mut_ref_in_final.stderr b/tests/ui/consts/const-mut-refs/mut_ref_in_final.stderr index 00a8421076b..4f50ae32312 100644 --- a/tests/ui/consts/const-mut-refs/mut_ref_in_final.stderr +++ b/tests/ui/consts/const-mut-refs/mut_ref_in_final.stderr @@ -1,11 +1,11 @@ error[E0764]: mutable references are not allowed in the final value of constants - --> $DIR/mut_ref_in_final.rs:9:21 + --> $DIR/mut_ref_in_final.rs:14:21 | LL | const B: *mut i32 = &mut 4; | ^^^^^^ error[E0716]: temporary value dropped while borrowed - --> $DIR/mut_ref_in_final.rs:15:40 + --> $DIR/mut_ref_in_final.rs:20:40 | LL | const B3: Option<&mut i32> = Some(&mut 42); | ----------^^- @@ -15,7 +15,7 @@ LL | const B3: Option<&mut i32> = Some(&mut 42); | using this value as a constant requires that borrow lasts for `'static` error[E0716]: temporary value dropped while borrowed - --> $DIR/mut_ref_in_final.rs:18:42 + --> $DIR/mut_ref_in_final.rs:23:42 | LL | const B4: Option<&mut i32> = helper(&mut 42); | ------------^^- @@ -24,8 +24,19 @@ LL | const B4: Option<&mut i32> = helper(&mut 42); | | creates a temporary value which is freed while still in use | using this value as a constant requires that borrow lasts for `'static` +error[E0080]: it is undefined behavior to use this value + --> $DIR/mut_ref_in_final.rs:26:1 + | +LL | const IMMUT_MUT_REF: &mut u16 = unsafe { mem::transmute(&13) }; + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ constructing invalid value: encountered mutable reference or box pointing to read-only memory + | + = note: The rules on what exactly is undefined behavior aren't clear, so this check might be overzealous. Please open an issue on the rustc repository if you believe it should not be considered undefined behavior. + = note: the raw bytes of the constant (size: $SIZE, align: $ALIGN) { + HEX_DUMP + } + error[E0716]: temporary value dropped while borrowed - --> $DIR/mut_ref_in_final.rs:33:65 + --> $DIR/mut_ref_in_final.rs:50:65 | LL | const FOO: NotAMutex<&mut i32> = NotAMutex(UnsafeCell::new(&mut 42)); | -------------------------------^^-- @@ -35,7 +46,7 @@ LL | const FOO: NotAMutex<&mut i32> = NotAMutex(UnsafeCell::new(&mut 42)); | using this value as a constant requires that borrow lasts for `'static` error[E0716]: temporary value dropped while borrowed - --> $DIR/mut_ref_in_final.rs:36:67 + --> $DIR/mut_ref_in_final.rs:53:67 | LL | static FOO2: NotAMutex<&mut i32> = NotAMutex(UnsafeCell::new(&mut 42)); | -------------------------------^^-- @@ -45,7 +56,7 @@ LL | static FOO2: NotAMutex<&mut i32> = NotAMutex(UnsafeCell::new(&mut 42)); | using this value as a static requires that borrow lasts for `'static` error[E0716]: temporary value dropped while borrowed - --> $DIR/mut_ref_in_final.rs:39:71 + --> $DIR/mut_ref_in_final.rs:56:71 | LL | static mut FOO3: NotAMutex<&mut i32> = NotAMutex(UnsafeCell::new(&mut 42)); | -------------------------------^^-- @@ -55,30 +66,30 @@ LL | static mut FOO3: NotAMutex<&mut i32> = NotAMutex(UnsafeCell::new(&mut 42)); | using this value as a static requires that borrow lasts for `'static` error[E0764]: mutable references are not allowed in the final value of statics - --> $DIR/mut_ref_in_final.rs:52:53 + --> $DIR/mut_ref_in_final.rs:69:53 | LL | static RAW_MUT_CAST_S: SyncPtr = SyncPtr { x : &mut 42 as *mut _ as *const _ }; | ^^^^^^^ error[E0764]: mutable references are not allowed in the final value of statics - --> $DIR/mut_ref_in_final.rs:54:54 + --> $DIR/mut_ref_in_final.rs:71:54 | LL | static RAW_MUT_COERCE_S: SyncPtr = SyncPtr { x: &mut 0 }; | ^^^^^^ error[E0764]: mutable references are not allowed in the final value of constants - --> $DIR/mut_ref_in_final.rs:56:52 + --> $DIR/mut_ref_in_final.rs:73:52 | LL | const RAW_MUT_CAST_C: SyncPtr = SyncPtr { x : &mut 42 as *mut _ as *const _ }; | ^^^^^^^ error[E0764]: mutable references are not allowed in the final value of constants - --> $DIR/mut_ref_in_final.rs:58:53 + --> $DIR/mut_ref_in_final.rs:75:53 | LL | const RAW_MUT_COERCE_C: SyncPtr = SyncPtr { x: &mut 0 }; | ^^^^^^ -error: aborting due to 10 previous errors +error: aborting due to 11 previous errors -Some errors have detailed explanations: E0716, E0764. -For more information about an error, try `rustc --explain E0716`. +Some errors have detailed explanations: E0080, E0716, E0764. +For more information about an error, try `rustc --explain E0080`. diff --git a/tests/ui/consts/const-mut-refs/mut_ref_in_final_dynamic_check.rs b/tests/ui/consts/const-mut-refs/mut_ref_in_final_dynamic_check.rs index e208845e747..7bf178484cc 100644 --- a/tests/ui/consts/const-mut-refs/mut_ref_in_final_dynamic_check.rs +++ b/tests/ui/consts/const-mut-refs/mut_ref_in_final_dynamic_check.rs @@ -1,7 +1,7 @@ //@ normalize-stderr-test: "(the raw bytes of the constant) \(size: [0-9]*, align: [0-9]*\)" -> "$1 (size: $$SIZE, align: $$ALIGN)" //@ normalize-stderr-test: "( 0x[0-9a-f][0-9a-f] │)? ([0-9a-f][0-9a-f] |__ |╾─*ALLOC[0-9]+(\+[a-z0-9]+)?()?─*╼ )+ *│.*" -> " HEX_DUMP" //@ normalize-stderr-test: "HEX_DUMP\s*\n\s*HEX_DUMP" -> "HEX_DUMP" -#![feature(const_mut_refs, const_refs_to_static)] +#![feature(const_refs_to_static)] use std::sync::Mutex; diff --git a/tests/ui/consts/const-promoted-opaque.atomic.stderr b/tests/ui/consts/const-promoted-opaque.atomic.stderr index 1f2a7753ff5..b9d5cbf801a 100644 --- a/tests/ui/consts/const-promoted-opaque.atomic.stderr +++ b/tests/ui/consts/const-promoted-opaque.atomic.stderr @@ -1,30 +1,20 @@ -error[E0658]: cannot borrow here, since the borrowed element may contain interior mutability - --> $DIR/const-promoted-opaque.rs:28:25 - | -LL | let _: &'static _ = &FOO; - | ^^^^ - | - = note: see issue #80384 for more information - = help: add `#![feature(const_refs_to_cell)]` to the crate attributes to enable - = note: this compiler was built on YYYY-MM-DD; consider upgrading it if it is out of date - error[E0493]: destructor of `helper::Foo` cannot be evaluated at compile-time --> $DIR/const-promoted-opaque.rs:28:26 | LL | let _: &'static _ = &FOO; | ^^^ the destructor for this type cannot be evaluated in constants -... +LL | LL | }; | - value is dropped here error[E0492]: constants cannot refer to interior mutable data - --> $DIR/const-promoted-opaque.rs:33:19 + --> $DIR/const-promoted-opaque.rs:32:19 | LL | const BAZ: &Foo = &FOO; | ^^^^ this borrow of an interior mutable value may end up in the final value error[E0716]: temporary value dropped while borrowed - --> $DIR/const-promoted-opaque.rs:37:26 + --> $DIR/const-promoted-opaque.rs:36:26 | LL | let _: &'static _ = &FOO; | ---------- ^^^ creates a temporary value which is freed while still in use @@ -34,7 +24,7 @@ LL | LL | } | - temporary value is freed at the end of this statement -error: aborting due to 4 previous errors +error: aborting due to 3 previous errors -Some errors have detailed explanations: E0492, E0493, E0658, E0716. +Some errors have detailed explanations: E0492, E0493, E0716. For more information about an error, try `rustc --explain E0492`. diff --git a/tests/ui/consts/const-promoted-opaque.rs b/tests/ui/consts/const-promoted-opaque.rs index 303618df9df..bb33e92778a 100644 --- a/tests/ui/consts/const-promoted-opaque.rs +++ b/tests/ui/consts/const-promoted-opaque.rs @@ -27,7 +27,6 @@ use helper::*; const BAR: () = { let _: &'static _ = &FOO; //[string,atomic]~^ ERROR: destructor of `helper::Foo` cannot be evaluated at compile-time - //[atomic]~| ERROR: cannot borrow here }; const BAZ: &Foo = &FOO; diff --git a/tests/ui/consts/const-promoted-opaque.string.stderr b/tests/ui/consts/const-promoted-opaque.string.stderr index fa1dbb05d17..33e5f426448 100644 --- a/tests/ui/consts/const-promoted-opaque.string.stderr +++ b/tests/ui/consts/const-promoted-opaque.string.stderr @@ -3,12 +3,12 @@ error[E0493]: destructor of `helper::Foo` cannot be evaluated at compile-time | LL | let _: &'static _ = &FOO; | ^^^ the destructor for this type cannot be evaluated in constants -... +LL | LL | }; | - value is dropped here error[E0716]: temporary value dropped while borrowed - --> $DIR/const-promoted-opaque.rs:37:26 + --> $DIR/const-promoted-opaque.rs:36:26 | LL | let _: &'static _ = &FOO; | ---------- ^^^ creates a temporary value which is freed while still in use diff --git a/tests/ui/consts/const-ref-to-static-linux-vtable.rs b/tests/ui/consts/const-ref-to-static-linux-vtable.rs index 9325746c1e7..b9d29d0c1f4 100644 --- a/tests/ui/consts/const-ref-to-static-linux-vtable.rs +++ b/tests/ui/consts/const-ref-to-static-linux-vtable.rs @@ -1,6 +1,6 @@ //@check-pass //! This is the reduced version of the "Linux kernel vtable" use-case. -#![feature(const_mut_refs, const_refs_to_static)] +#![feature(const_refs_to_static)] use std::ptr::addr_of_mut; #[repr(C)] diff --git a/tests/ui/consts/const-suggest-feature.rs b/tests/ui/consts/const-suggest-feature.rs index d76d01a3d5e..0c940368976 100644 --- a/tests/ui/consts/const-suggest-feature.rs +++ b/tests/ui/consts/const-suggest-feature.rs @@ -1,7 +1,10 @@ +//@compile-flags: --edition 2018 +use std::cell::Cell; + const WRITE: () = unsafe { - *std::ptr::null_mut() = 0; - //~^ ERROR dereferencing raw mutable pointers in constants is unstable - //~| HELP add `#![feature(const_mut_refs)]` to the crate attributes to enable + let x = async { 13 }; + //~^ ERROR `async` blocks + //~| HELP add `#![feature(const_async_blocks)]` to the crate attributes to enable }; fn main() {} diff --git a/tests/ui/consts/const-suggest-feature.stderr b/tests/ui/consts/const-suggest-feature.stderr index faa1226ca25..398b21caeb0 100644 --- a/tests/ui/consts/const-suggest-feature.stderr +++ b/tests/ui/consts/const-suggest-feature.stderr @@ -1,11 +1,11 @@ -error[E0658]: dereferencing raw mutable pointers in constants is unstable - --> $DIR/const-suggest-feature.rs:2:5 +error[E0658]: `async` blocks are not allowed in constants + --> $DIR/const-suggest-feature.rs:5:13 | -LL | *std::ptr::null_mut() = 0; - | ^^^^^^^^^^^^^^^^^^^^^^^^^ +LL | let x = async { 13 }; + | ^^^^^^^^^^^^ | - = note: see issue #57349 for more information - = help: add `#![feature(const_mut_refs)]` to the crate attributes to enable + = note: see issue #85368 for more information + = help: add `#![feature(const_async_blocks)]` to the crate attributes to enable = note: this compiler was built on YYYY-MM-DD; consider upgrading it if it is out of date error: aborting due to 1 previous error diff --git a/tests/ui/consts/const_let_assign3.rs b/tests/ui/consts/const_let_assign3.rs index 1f68de8eed0..7928b2766e9 100644 --- a/tests/ui/consts/const_let_assign3.rs +++ b/tests/ui/consts/const_let_assign3.rs @@ -1,23 +1,24 @@ +//@ check-pass + struct S { state: u32, } impl S { const fn foo(&mut self, x: u32) { - //~^ ERROR mutable reference self.state = x; } } const FOO: S = { let mut s = S { state: 42 }; - s.foo(3); //~ ERROR mutable reference + s.foo(3); s }; type Array = [u32; { let mut x = 2; - let y = &mut x; //~ ERROR mutable reference + let y = &mut x; *y = 42; *y }]; diff --git a/tests/ui/consts/const_let_assign3.stderr b/tests/ui/consts/const_let_assign3.stderr deleted file mode 100644 index ae890131715..00000000000 --- a/tests/ui/consts/const_let_assign3.stderr +++ /dev/null @@ -1,33 +0,0 @@ -error[E0658]: mutable references are not allowed in constants - --> $DIR/const_let_assign3.rs:14:5 - | -LL | s.foo(3); - | ^ - | - = note: see issue #57349 for more information - = help: add `#![feature(const_mut_refs)]` to the crate attributes to enable - = note: this compiler was built on YYYY-MM-DD; consider upgrading it if it is out of date - -error[E0658]: mutable references are not allowed in constant functions - --> $DIR/const_let_assign3.rs:6:18 - | -LL | const fn foo(&mut self, x: u32) { - | ^^^^^^^^^ - | - = note: see issue #57349 for more information - = help: add `#![feature(const_mut_refs)]` to the crate attributes to enable - = note: this compiler was built on YYYY-MM-DD; consider upgrading it if it is out of date - -error[E0658]: mutable references are not allowed in constants - --> $DIR/const_let_assign3.rs:20:13 - | -LL | let y = &mut x; - | ^^^^^^ - | - = note: see issue #57349 for more information - = help: add `#![feature(const_mut_refs)]` to the crate attributes to enable - = note: this compiler was built on YYYY-MM-DD; consider upgrading it if it is out of date - -error: aborting due to 3 previous errors - -For more information about this error, try `rustc --explain E0658`. diff --git a/tests/ui/consts/const_refs_to_static_fail.rs b/tests/ui/consts/const_refs_to_static_fail.rs index 806aa5f8f6f..a69902c3439 100644 --- a/tests/ui/consts/const_refs_to_static_fail.rs +++ b/tests/ui/consts/const_refs_to_static_fail.rs @@ -1,6 +1,6 @@ //@ normalize-stderr-test: "(the raw bytes of the constant) \(size: [0-9]*, align: [0-9]*\)" -> "$1 (size: $$SIZE, align: $$ALIGN)" //@ normalize-stderr-test: "([0-9a-f][0-9a-f] |╾─*ALLOC[0-9]+(\+[a-z0-9]+)?()?─*╼ )+ *│.*" -> "HEX_DUMP" -#![feature(const_refs_to_static, const_mut_refs, sync_unsafe_cell)] +#![feature(const_refs_to_static, sync_unsafe_cell)] use std::cell::SyncUnsafeCell; static S: SyncUnsafeCell = SyncUnsafeCell::new(0); diff --git a/tests/ui/consts/control-flow/loop.rs b/tests/ui/consts/control-flow/loop.rs index 5b7f8d29df7..f8d9f3ddb9b 100644 --- a/tests/ui/consts/control-flow/loop.rs +++ b/tests/ui/consts/control-flow/loop.rs @@ -52,14 +52,12 @@ const _: i32 = { for i in 0..4 { //~ ERROR `for` is not allowed in a `const` //~^ ERROR: cannot call - //~| ERROR: mutable references //~| ERROR: cannot convert x += i; } for i in 0..4 { //~ ERROR `for` is not allowed in a `const` //~^ ERROR: cannot call - //~| ERROR: mutable references //~| ERROR: cannot convert x += i; } diff --git a/tests/ui/consts/control-flow/loop.stderr b/tests/ui/consts/control-flow/loop.stderr index 2815b888ccd..13d5d3e0b55 100644 --- a/tests/ui/consts/control-flow/loop.stderr +++ b/tests/ui/consts/control-flow/loop.stderr @@ -4,7 +4,6 @@ error[E0658]: `for` is not allowed in a `const` LL | / for i in 0..4 { LL | | LL | | -LL | | LL | | x += i; LL | | } | |_____^ @@ -14,12 +13,11 @@ LL | | } = note: this compiler was built on YYYY-MM-DD; consider upgrading it if it is out of date error[E0658]: `for` is not allowed in a `const` - --> $DIR/loop.rs:60:5 + --> $DIR/loop.rs:59:5 | LL | / for i in 0..4 { LL | | LL | | -LL | | LL | | x += i; LL | | } | |_____^ @@ -42,16 +40,6 @@ help: add `#![feature(const_trait_impl)]` to the crate attributes to enable LL + #![feature(const_trait_impl)] | -error[E0658]: mutable references are not allowed in constants - --> $DIR/loop.rs:53:14 - | -LL | for i in 0..4 { - | ^^^^ - | - = note: see issue #57349 for more information - = help: add `#![feature(const_mut_refs)]` to the crate attributes to enable - = note: this compiler was built on YYYY-MM-DD; consider upgrading it if it is out of date - error[E0015]: cannot call non-const fn ` as Iterator>::next` in constants --> $DIR/loop.rs:53:14 | @@ -65,7 +53,7 @@ LL + #![feature(const_trait_impl)] | error[E0015]: cannot convert `std::ops::Range` into an iterator in constants - --> $DIR/loop.rs:60:14 + --> $DIR/loop.rs:59:14 | LL | for i in 0..4 { | ^^^^ @@ -78,18 +66,8 @@ help: add `#![feature(const_trait_impl)]` to the crate attributes to enable LL + #![feature(const_trait_impl)] | -error[E0658]: mutable references are not allowed in constants - --> $DIR/loop.rs:60:14 - | -LL | for i in 0..4 { - | ^^^^ - | - = note: see issue #57349 for more information - = help: add `#![feature(const_mut_refs)]` to the crate attributes to enable - = note: this compiler was built on YYYY-MM-DD; consider upgrading it if it is out of date - error[E0015]: cannot call non-const fn ` as Iterator>::next` in constants - --> $DIR/loop.rs:60:14 + --> $DIR/loop.rs:59:14 | LL | for i in 0..4 { | ^^^^ @@ -100,7 +78,7 @@ help: add `#![feature(const_trait_impl)]` to the crate attributes to enable LL + #![feature(const_trait_impl)] | -error: aborting due to 8 previous errors +error: aborting due to 6 previous errors Some errors have detailed explanations: E0015, E0658. For more information about an error, try `rustc --explain E0015`. diff --git a/tests/ui/consts/copy-intrinsic.rs b/tests/ui/consts/copy-intrinsic.rs index e3f43ce2037..805c03da546 100644 --- a/tests/ui/consts/copy-intrinsic.rs +++ b/tests/ui/consts/copy-intrinsic.rs @@ -2,7 +2,6 @@ // ignore-tidy-linelength #![feature(intrinsics, staged_api)] -#![feature(const_mut_refs)] use std::mem; extern "rust-intrinsic" { diff --git a/tests/ui/consts/copy-intrinsic.stderr b/tests/ui/consts/copy-intrinsic.stderr index 2dbb471131e..da8139129c9 100644 --- a/tests/ui/consts/copy-intrinsic.stderr +++ b/tests/ui/consts/copy-intrinsic.stderr @@ -1,23 +1,23 @@ error[E0080]: evaluation of constant value failed - --> $DIR/copy-intrinsic.rs:29:5 + --> $DIR/copy-intrinsic.rs:28:5 | LL | copy_nonoverlapping(0x100 as *const i32, dangle, 1); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ memory access failed: expected a pointer to 4 bytes of memory, but got 0x100[noalloc] which is a dangling pointer (it has no provenance) error[E0080]: evaluation of constant value failed - --> $DIR/copy-intrinsic.rs:38:5 + --> $DIR/copy-intrinsic.rs:37:5 | LL | copy_nonoverlapping(dangle, 0x100 as *mut i32, 1); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ memory access failed: expected a pointer to 4 bytes of memory, but got ALLOC0+0x28 which is at or beyond the end of the allocation of size 4 bytes error[E0080]: evaluation of constant value failed - --> $DIR/copy-intrinsic.rs:45:5 + --> $DIR/copy-intrinsic.rs:44:5 | LL | copy(&x, &mut y, 1usize << (mem::size_of::() * 8 - 1)); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ overflow computing total size of `copy` error[E0080]: evaluation of constant value failed - --> $DIR/copy-intrinsic.rs:51:5 + --> $DIR/copy-intrinsic.rs:50:5 | LL | copy_nonoverlapping(&x, &mut y, 1usize << (mem::size_of::() * 8 - 1)); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ overflow computing total size of `copy_nonoverlapping` diff --git a/tests/ui/consts/fn_trait_refs.rs b/tests/ui/consts/fn_trait_refs.rs index e9444e5c094..4defe4dedc7 100644 --- a/tests/ui/consts/fn_trait_refs.rs +++ b/tests/ui/consts/fn_trait_refs.rs @@ -4,9 +4,7 @@ #![feature(fn_traits)] #![feature(unboxed_closures)] #![feature(const_trait_impl)] -#![feature(const_mut_refs)] #![feature(const_cmp)] -#![feature(const_refs_to_cell)] use std::marker::Destruct; diff --git a/tests/ui/consts/fn_trait_refs.stderr b/tests/ui/consts/fn_trait_refs.stderr index 42a6026cfba..218c90f89a9 100644 --- a/tests/ui/consts/fn_trait_refs.stderr +++ b/tests/ui/consts/fn_trait_refs.stderr @@ -5,25 +5,25 @@ LL | #![feature(const_fn_trait_ref_impls)] | ^^^^^^^^^^^^^^^^^^^^^^^^ error[E0635]: unknown feature `const_cmp` - --> $DIR/fn_trait_refs.rs:8:12 + --> $DIR/fn_trait_refs.rs:7:12 | LL | #![feature(const_cmp)] | ^^^^^^^^^ error: `~const` can only be applied to `#[const_trait]` traits - --> $DIR/fn_trait_refs.rs:15:15 + --> $DIR/fn_trait_refs.rs:13:15 | LL | T: ~const Fn<()> + ~const Destruct, | ^^^^^^ error: `~const` can only be applied to `#[const_trait]` traits - --> $DIR/fn_trait_refs.rs:15:31 + --> $DIR/fn_trait_refs.rs:13:31 | LL | T: ~const Fn<()> + ~const Destruct, | ^^^^^^^^ error: `~const` can only be applied to `#[const_trait]` traits - --> $DIR/fn_trait_refs.rs:15:15 + --> $DIR/fn_trait_refs.rs:13:15 | LL | T: ~const Fn<()> + ~const Destruct, | ^^^^^^ @@ -31,19 +31,19 @@ LL | T: ~const Fn<()> + ~const Destruct, = note: duplicate diagnostic emitted due to `-Z deduplicate-diagnostics=no` error: `~const` can only be applied to `#[const_trait]` traits - --> $DIR/fn_trait_refs.rs:22:15 + --> $DIR/fn_trait_refs.rs:20:15 | LL | T: ~const FnMut<()> + ~const Destruct, | ^^^^^^^^^ error: `~const` can only be applied to `#[const_trait]` traits - --> $DIR/fn_trait_refs.rs:22:34 + --> $DIR/fn_trait_refs.rs:20:34 | LL | T: ~const FnMut<()> + ~const Destruct, | ^^^^^^^^ error: `~const` can only be applied to `#[const_trait]` traits - --> $DIR/fn_trait_refs.rs:22:15 + --> $DIR/fn_trait_refs.rs:20:15 | LL | T: ~const FnMut<()> + ~const Destruct, | ^^^^^^^^^ @@ -51,13 +51,13 @@ LL | T: ~const FnMut<()> + ~const Destruct, = note: duplicate diagnostic emitted due to `-Z deduplicate-diagnostics=no` error: `~const` can only be applied to `#[const_trait]` traits - --> $DIR/fn_trait_refs.rs:29:15 + --> $DIR/fn_trait_refs.rs:27:15 | LL | T: ~const FnOnce<()>, | ^^^^^^^^^^ error: `~const` can only be applied to `#[const_trait]` traits - --> $DIR/fn_trait_refs.rs:29:15 + --> $DIR/fn_trait_refs.rs:27:15 | LL | T: ~const FnOnce<()>, | ^^^^^^^^^^ @@ -65,19 +65,19 @@ LL | T: ~const FnOnce<()>, = note: duplicate diagnostic emitted due to `-Z deduplicate-diagnostics=no` error: `~const` can only be applied to `#[const_trait]` traits - --> $DIR/fn_trait_refs.rs:36:15 + --> $DIR/fn_trait_refs.rs:34:15 | LL | T: ~const Fn<()> + ~const Destruct, | ^^^^^^ error: `~const` can only be applied to `#[const_trait]` traits - --> $DIR/fn_trait_refs.rs:36:31 + --> $DIR/fn_trait_refs.rs:34:31 | LL | T: ~const Fn<()> + ~const Destruct, | ^^^^^^^^ error: `~const` can only be applied to `#[const_trait]` traits - --> $DIR/fn_trait_refs.rs:36:15 + --> $DIR/fn_trait_refs.rs:34:15 | LL | T: ~const Fn<()> + ~const Destruct, | ^^^^^^ @@ -85,19 +85,19 @@ LL | T: ~const Fn<()> + ~const Destruct, = note: duplicate diagnostic emitted due to `-Z deduplicate-diagnostics=no` error: `~const` can only be applied to `#[const_trait]` traits - --> $DIR/fn_trait_refs.rs:50:15 + --> $DIR/fn_trait_refs.rs:48:15 | LL | T: ~const FnMut<()> + ~const Destruct, | ^^^^^^^^^ error: `~const` can only be applied to `#[const_trait]` traits - --> $DIR/fn_trait_refs.rs:50:34 + --> $DIR/fn_trait_refs.rs:48:34 | LL | T: ~const FnMut<()> + ~const Destruct, | ^^^^^^^^ error: `~const` can only be applied to `#[const_trait]` traits - --> $DIR/fn_trait_refs.rs:50:15 + --> $DIR/fn_trait_refs.rs:48:15 | LL | T: ~const FnMut<()> + ~const Destruct, | ^^^^^^^^^ @@ -105,7 +105,7 @@ LL | T: ~const FnMut<()> + ~const Destruct, = note: duplicate diagnostic emitted due to `-Z deduplicate-diagnostics=no` error[E0015]: cannot call non-const operator in constants - --> $DIR/fn_trait_refs.rs:72:17 + --> $DIR/fn_trait_refs.rs:70:17 | LL | assert!(test_one == (1, 1, 1)); | ^^^^^^^^^^^^^^^^^^^^^ @@ -117,7 +117,7 @@ LL + #![feature(effects)] | error[E0015]: cannot call non-const operator in constants - --> $DIR/fn_trait_refs.rs:75:17 + --> $DIR/fn_trait_refs.rs:73:17 | LL | assert!(test_two == (2, 2)); | ^^^^^^^^^^^^^^^^^^ @@ -129,7 +129,7 @@ LL + #![feature(effects)] | error[E0015]: cannot call non-const closure in constant functions - --> $DIR/fn_trait_refs.rs:17:5 + --> $DIR/fn_trait_refs.rs:15:5 | LL | f() | ^^^ @@ -145,7 +145,7 @@ LL + #![feature(effects)] | error[E0493]: destructor of `T` cannot be evaluated at compile-time - --> $DIR/fn_trait_refs.rs:13:23 + --> $DIR/fn_trait_refs.rs:11:23 | LL | const fn tester_fn(f: T) -> T::Output | ^ the destructor for this type cannot be evaluated in constant functions @@ -154,7 +154,7 @@ LL | } | - value is dropped here error[E0015]: cannot call non-const closure in constant functions - --> $DIR/fn_trait_refs.rs:24:5 + --> $DIR/fn_trait_refs.rs:22:5 | LL | f() | ^^^ @@ -170,7 +170,7 @@ LL + #![feature(effects)] | error[E0493]: destructor of `T` cannot be evaluated at compile-time - --> $DIR/fn_trait_refs.rs:20:27 + --> $DIR/fn_trait_refs.rs:18:27 | LL | const fn tester_fn_mut(mut f: T) -> T::Output | ^^^^^ the destructor for this type cannot be evaluated in constant functions @@ -179,7 +179,7 @@ LL | } | - value is dropped here error[E0015]: cannot call non-const closure in constant functions - --> $DIR/fn_trait_refs.rs:31:5 + --> $DIR/fn_trait_refs.rs:29:5 | LL | f() | ^^^ @@ -195,7 +195,7 @@ LL + #![feature(effects)] | error[E0493]: destructor of `T` cannot be evaluated at compile-time - --> $DIR/fn_trait_refs.rs:34:21 + --> $DIR/fn_trait_refs.rs:32:21 | LL | const fn test_fn(mut f: T) -> (T::Output, T::Output, T::Output) | ^^^^^ the destructor for this type cannot be evaluated in constant functions @@ -204,7 +204,7 @@ LL | } | - value is dropped here error[E0493]: destructor of `T` cannot be evaluated at compile-time - --> $DIR/fn_trait_refs.rs:48:25 + --> $DIR/fn_trait_refs.rs:46:25 | LL | const fn test_fn_mut(mut f: T) -> (T::Output, T::Output) | ^^^^^ the destructor for this type cannot be evaluated in constant functions diff --git a/tests/ui/consts/interior-mut-const-via-union.32bit.stderr b/tests/ui/consts/interior-mut-const-via-union.32bit.stderr index e9e9f1a4545..fb06643df85 100644 --- a/tests/ui/consts/interior-mut-const-via-union.32bit.stderr +++ b/tests/ui/consts/interior-mut-const-via-union.32bit.stderr @@ -1,5 +1,5 @@ error[E0080]: it is undefined behavior to use this value - --> $DIR/interior-mut-const-via-union.rs:35:1 + --> $DIR/interior-mut-const-via-union.rs:34:1 | LL | fn main() { | ^^^^^^^^^ constructing invalid value at ..y..0: encountered `UnsafeCell` in read-only memory @@ -10,13 +10,13 @@ LL | fn main() { } note: erroneous constant encountered - --> $DIR/interior-mut-const-via-union.rs:37:25 + --> $DIR/interior-mut-const-via-union.rs:36:25 | LL | let _: &'static _ = &C; | ^^ note: erroneous constant encountered - --> $DIR/interior-mut-const-via-union.rs:37:25 + --> $DIR/interior-mut-const-via-union.rs:36:25 | LL | let _: &'static _ = &C; | ^^ diff --git a/tests/ui/consts/interior-mut-const-via-union.64bit.stderr b/tests/ui/consts/interior-mut-const-via-union.64bit.stderr index 9cc98975ca9..f39ebe0afbd 100644 --- a/tests/ui/consts/interior-mut-const-via-union.64bit.stderr +++ b/tests/ui/consts/interior-mut-const-via-union.64bit.stderr @@ -1,5 +1,5 @@ error[E0080]: it is undefined behavior to use this value - --> $DIR/interior-mut-const-via-union.rs:35:1 + --> $DIR/interior-mut-const-via-union.rs:34:1 | LL | fn main() { | ^^^^^^^^^ constructing invalid value at ..y..0: encountered `UnsafeCell` in read-only memory @@ -10,13 +10,13 @@ LL | fn main() { } note: erroneous constant encountered - --> $DIR/interior-mut-const-via-union.rs:37:25 + --> $DIR/interior-mut-const-via-union.rs:36:25 | LL | let _: &'static _ = &C; | ^^ note: erroneous constant encountered - --> $DIR/interior-mut-const-via-union.rs:37:25 + --> $DIR/interior-mut-const-via-union.rs:36:25 | LL | let _: &'static _ = &C; | ^^ diff --git a/tests/ui/consts/interior-mut-const-via-union.rs b/tests/ui/consts/interior-mut-const-via-union.rs index 20485b90bf7..6d40a9ba850 100644 --- a/tests/ui/consts/interior-mut-const-via-union.rs +++ b/tests/ui/consts/interior-mut-const-via-union.rs @@ -3,7 +3,6 @@ // //@ build-fail //@ stderr-per-bitwidth -#![feature(const_mut_refs)] use std::cell::Cell; use std::mem::ManuallyDrop; diff --git a/tests/ui/consts/issue-17718-const-bad-values.rs b/tests/ui/consts/issue-17718-const-bad-values.rs index 33347d8df62..52f8c9bf149 100644 --- a/tests/ui/consts/issue-17718-const-bad-values.rs +++ b/tests/ui/consts/issue-17718-const-bad-values.rs @@ -6,6 +6,5 @@ const C1: &'static mut [usize] = &mut []; static mut S: usize = 3; const C2: &'static mut usize = unsafe { &mut S }; //~^ ERROR: referencing statics in constants -//~| ERROR: mutable references are not allowed fn main() {} diff --git a/tests/ui/consts/issue-17718-const-bad-values.stderr b/tests/ui/consts/issue-17718-const-bad-values.stderr index e755e5601a8..57fcb1c7e9a 100644 --- a/tests/ui/consts/issue-17718-const-bad-values.stderr +++ b/tests/ui/consts/issue-17718-const-bad-values.stderr @@ -16,17 +16,7 @@ LL | const C2: &'static mut usize = unsafe { &mut S }; = note: `static` and `const` variables can refer to other `const` variables. A `const` variable, however, cannot refer to a `static` variable. = help: to fix this, the value can be extracted to a `const` and then used. -error[E0658]: mutable references are not allowed in constants - --> $DIR/issue-17718-const-bad-values.rs:7:41 - | -LL | const C2: &'static mut usize = unsafe { &mut S }; - | ^^^^^^ - | - = note: see issue #57349 for more information - = help: add `#![feature(const_mut_refs)]` to the crate attributes to enable - = note: this compiler was built on YYYY-MM-DD; consider upgrading it if it is out of date - -error: aborting due to 3 previous errors +error: aborting due to 2 previous errors Some errors have detailed explanations: E0658, E0764. For more information about an error, try `rustc --explain E0658`. diff --git a/tests/ui/consts/issue-69488.rs b/tests/ui/consts/issue-69488.rs index 35071999111..d528d6a88de 100644 --- a/tests/ui/consts/issue-69488.rs +++ b/tests/ui/consts/issue-69488.rs @@ -1,7 +1,6 @@ //@ run-pass #![feature(const_ptr_write)] -#![feature(const_mut_refs)] // Or, equivalently: `MaybeUninit`. pub union BagOfBits { diff --git a/tests/ui/consts/issue-94371.rs b/tests/ui/consts/issue-94371.rs index 3484437e571..ad9ee9a5a3e 100644 --- a/tests/ui/consts/issue-94371.rs +++ b/tests/ui/consts/issue-94371.rs @@ -1,7 +1,6 @@ //@ check-pass #![feature(const_swap)] -#![feature(const_mut_refs)] #[repr(C)] struct Demo(u64, bool, u64, u32, u64, u64, u64); diff --git a/tests/ui/consts/issue-94675.rs b/tests/ui/consts/issue-94675.rs index 00f5c3251e0..56c4b6ea36f 100644 --- a/tests/ui/consts/issue-94675.rs +++ b/tests/ui/consts/issue-94675.rs @@ -1,6 +1,6 @@ //@ known-bug: #103507 -#![feature(const_trait_impl, const_mut_refs)] +#![feature(const_trait_impl)] struct Foo<'a> { bar: &'a mut Vec, diff --git a/tests/ui/consts/min_const_fn/address_of.rs b/tests/ui/consts/min_const_fn/address_of.rs deleted file mode 100644 index dc481e17ba3..00000000000 --- a/tests/ui/consts/min_const_fn/address_of.rs +++ /dev/null @@ -1,15 +0,0 @@ -const fn mutable_address_of_in_const() { - let mut a = 0; - let b = &raw mut a; //~ ERROR mutable pointer -} - -struct X; - -impl X { - const fn inherent_mutable_address_of_in_const() { - let mut a = 0; - let b = &raw mut a; //~ ERROR mutable pointer - } -} - -fn main() {} diff --git a/tests/ui/consts/min_const_fn/address_of.stderr b/tests/ui/consts/min_const_fn/address_of.stderr deleted file mode 100644 index dd6fe6486d4..00000000000 --- a/tests/ui/consts/min_const_fn/address_of.stderr +++ /dev/null @@ -1,23 +0,0 @@ -error[E0658]: raw mutable pointers are not allowed in constant functions - --> $DIR/address_of.rs:3:13 - | -LL | let b = &raw mut a; - | ^^^^^^^^^^ - | - = note: see issue #57349 for more information - = help: add `#![feature(const_mut_refs)]` to the crate attributes to enable - = note: this compiler was built on YYYY-MM-DD; consider upgrading it if it is out of date - -error[E0658]: raw mutable pointers are not allowed in constant functions - --> $DIR/address_of.rs:11:17 - | -LL | let b = &raw mut a; - | ^^^^^^^^^^ - | - = note: see issue #57349 for more information - = help: add `#![feature(const_mut_refs)]` to the crate attributes to enable - = note: this compiler was built on YYYY-MM-DD; consider upgrading it if it is out of date - -error: aborting due to 2 previous errors - -For more information about this error, try `rustc --explain E0658`. diff --git a/tests/ui/consts/min_const_fn/min_const_fn.rs b/tests/ui/consts/min_const_fn/min_const_fn.rs index f7663f6044e..ed5aa40b66c 100644 --- a/tests/ui/consts/min_const_fn/min_const_fn.rs +++ b/tests/ui/consts/min_const_fn/min_const_fn.rs @@ -37,34 +37,22 @@ impl Foo { const fn into_inner(self) -> T { self.0 } //~ destructor of const fn get(&self) -> &T { &self.0 } const fn get_mut(&mut self) -> &mut T { &mut self.0 } - //~^ mutable references - //~| mutable references - //~| mutable references } impl<'a, T> Foo { const fn new_lt(t: T) -> Self { Foo(t) } const fn into_inner_lt(self) -> T { self.0 } //~ destructor of - const fn get_lt(&'a self) -> &T { &self.0 } //~ WARNING elided lifetime has a name - const fn get_mut_lt(&'a mut self) -> &mut T { &mut self.0 } //~ WARNING elided lifetime has a name - //~^ mutable references - //~| mutable references - //~| mutable references + const fn get_lt(&self) -> &T { &self.0 } + const fn get_mut_lt(&mut self) -> &mut T { &mut self.0 } } impl Foo { const fn new_s(t: T) -> Self { Foo(t) } const fn into_inner_s(self) -> T { self.0 } //~ ERROR destructor const fn get_s(&self) -> &T { &self.0 } const fn get_mut_s(&mut self) -> &mut T { &mut self.0 } - //~^ mutable references - //~| mutable references - //~| mutable references } impl Foo { const fn get_sq(&self) -> &T { &self.0 } const fn get_mut_sq(&mut self) -> &mut T { &mut self.0 } - //~^ mutable references - //~| mutable references - //~| mutable references } @@ -98,7 +86,6 @@ const fn foo30_2_with_unsafe(x: *mut u32) -> usize { unsafe { x as usize } } //~^ ERROR pointers cannot be cast to integers const fn foo30_6() -> bool { let x = true; x } const fn inc(x: &mut i32) { *x += 1 } -//~^ ERROR mutable references // ok const fn foo36(a: bool, b: bool) -> bool { a && b } diff --git a/tests/ui/consts/min_const_fn/min_const_fn.stderr b/tests/ui/consts/min_const_fn/min_const_fn.stderr index 4b348a182b8..c02f8c76d44 100644 --- a/tests/ui/consts/min_const_fn/min_const_fn.stderr +++ b/tests/ui/consts/min_const_fn/min_const_fn.stderr @@ -1,23 +1,3 @@ -warning: elided lifetime has a name - --> $DIR/min_const_fn.rs:47:34 - | -LL | impl<'a, T> Foo { - | -- lifetime `'a` declared here -... -LL | const fn get_lt(&'a self) -> &T { &self.0 } - | ^ this elided lifetime gets resolved as `'a` - | - = note: `#[warn(elided_named_lifetimes)]` on by default - -warning: elided lifetime has a name - --> $DIR/min_const_fn.rs:48:42 - | -LL | impl<'a, T> Foo { - | -- lifetime `'a` declared here -... -LL | const fn get_mut_lt(&'a mut self) -> &mut T { &mut self.0 } - | ^ this elided lifetime gets resolved as `'a` - error[E0493]: destructor of `Foo` cannot be evaluated at compile-time --> $DIR/min_const_fn.rs:37:25 | @@ -26,144 +6,24 @@ LL | const fn into_inner(self) -> T { self.0 } | | | the destructor for this type cannot be evaluated in constant functions -error[E0658]: mutable references are not allowed in constant functions - --> $DIR/min_const_fn.rs:39:22 - | -LL | const fn get_mut(&mut self) -> &mut T { &mut self.0 } - | ^^^^^^^^^ - | - = note: see issue #57349 for more information - = help: add `#![feature(const_mut_refs)]` to the crate attributes to enable - = note: this compiler was built on YYYY-MM-DD; consider upgrading it if it is out of date - -error[E0658]: mutable references are not allowed in constant functions - --> $DIR/min_const_fn.rs:39:36 - | -LL | const fn get_mut(&mut self) -> &mut T { &mut self.0 } - | ^^^^^^ - | - = note: see issue #57349 for more information - = help: add `#![feature(const_mut_refs)]` to the crate attributes to enable - = note: this compiler was built on YYYY-MM-DD; consider upgrading it if it is out of date - -error[E0658]: mutable references are not allowed in constant functions - --> $DIR/min_const_fn.rs:39:45 - | -LL | const fn get_mut(&mut self) -> &mut T { &mut self.0 } - | ^^^^^^^^^^^ - | - = note: see issue #57349 for more information - = help: add `#![feature(const_mut_refs)]` to the crate attributes to enable - = note: this compiler was built on YYYY-MM-DD; consider upgrading it if it is out of date - error[E0493]: destructor of `Foo` cannot be evaluated at compile-time - --> $DIR/min_const_fn.rs:46:28 + --> $DIR/min_const_fn.rs:43:28 | LL | const fn into_inner_lt(self) -> T { self.0 } | ^^^^ - value is dropped here | | | the destructor for this type cannot be evaluated in constant functions -error[E0658]: mutable references are not allowed in constant functions - --> $DIR/min_const_fn.rs:48:25 - | -LL | const fn get_mut_lt(&'a mut self) -> &mut T { &mut self.0 } - | ^^^^^^^^^^^^ - | - = note: see issue #57349 for more information - = help: add `#![feature(const_mut_refs)]` to the crate attributes to enable - = note: this compiler was built on YYYY-MM-DD; consider upgrading it if it is out of date - -error[E0658]: mutable references are not allowed in constant functions - --> $DIR/min_const_fn.rs:48:42 - | -LL | const fn get_mut_lt(&'a mut self) -> &mut T { &mut self.0 } - | ^^^^^^ - | - = note: see issue #57349 for more information - = help: add `#![feature(const_mut_refs)]` to the crate attributes to enable - = note: this compiler was built on YYYY-MM-DD; consider upgrading it if it is out of date - -error[E0658]: mutable references are not allowed in constant functions - --> $DIR/min_const_fn.rs:48:51 - | -LL | const fn get_mut_lt(&'a mut self) -> &mut T { &mut self.0 } - | ^^^^^^^^^^^ - | - = note: see issue #57349 for more information - = help: add `#![feature(const_mut_refs)]` to the crate attributes to enable - = note: this compiler was built on YYYY-MM-DD; consider upgrading it if it is out of date - error[E0493]: destructor of `Foo` cannot be evaluated at compile-time - --> $DIR/min_const_fn.rs:55:27 + --> $DIR/min_const_fn.rs:49:27 | LL | const fn into_inner_s(self) -> T { self.0 } | ^^^^ - value is dropped here | | | the destructor for this type cannot be evaluated in constant functions -error[E0658]: mutable references are not allowed in constant functions - --> $DIR/min_const_fn.rs:57:24 - | -LL | const fn get_mut_s(&mut self) -> &mut T { &mut self.0 } - | ^^^^^^^^^ - | - = note: see issue #57349 for more information - = help: add `#![feature(const_mut_refs)]` to the crate attributes to enable - = note: this compiler was built on YYYY-MM-DD; consider upgrading it if it is out of date - -error[E0658]: mutable references are not allowed in constant functions - --> $DIR/min_const_fn.rs:57:38 - | -LL | const fn get_mut_s(&mut self) -> &mut T { &mut self.0 } - | ^^^^^^ - | - = note: see issue #57349 for more information - = help: add `#![feature(const_mut_refs)]` to the crate attributes to enable - = note: this compiler was built on YYYY-MM-DD; consider upgrading it if it is out of date - -error[E0658]: mutable references are not allowed in constant functions - --> $DIR/min_const_fn.rs:57:47 - | -LL | const fn get_mut_s(&mut self) -> &mut T { &mut self.0 } - | ^^^^^^^^^^^ - | - = note: see issue #57349 for more information - = help: add `#![feature(const_mut_refs)]` to the crate attributes to enable - = note: this compiler was built on YYYY-MM-DD; consider upgrading it if it is out of date - -error[E0658]: mutable references are not allowed in constant functions - --> $DIR/min_const_fn.rs:64:25 - | -LL | const fn get_mut_sq(&mut self) -> &mut T { &mut self.0 } - | ^^^^^^^^^ - | - = note: see issue #57349 for more information - = help: add `#![feature(const_mut_refs)]` to the crate attributes to enable - = note: this compiler was built on YYYY-MM-DD; consider upgrading it if it is out of date - -error[E0658]: mutable references are not allowed in constant functions - --> $DIR/min_const_fn.rs:64:39 - | -LL | const fn get_mut_sq(&mut self) -> &mut T { &mut self.0 } - | ^^^^^^ - | - = note: see issue #57349 for more information - = help: add `#![feature(const_mut_refs)]` to the crate attributes to enable - = note: this compiler was built on YYYY-MM-DD; consider upgrading it if it is out of date - -error[E0658]: mutable references are not allowed in constant functions - --> $DIR/min_const_fn.rs:64:48 - | -LL | const fn get_mut_sq(&mut self) -> &mut T { &mut self.0 } - | ^^^^^^^^^^^ - | - = note: see issue #57349 for more information - = help: add `#![feature(const_mut_refs)]` to the crate attributes to enable - = note: this compiler was built on YYYY-MM-DD; consider upgrading it if it is out of date - error[E0658]: referencing statics in constant functions is unstable - --> $DIR/min_const_fn.rs:89:27 + --> $DIR/min_const_fn.rs:77:27 | LL | const fn foo25() -> u32 { BAR } | ^^^ @@ -175,7 +35,7 @@ LL | const fn foo25() -> u32 { BAR } = help: to fix this, the value can be extracted to a `const` and then used. error[E0658]: referencing statics in constant functions is unstable - --> $DIR/min_const_fn.rs:90:37 + --> $DIR/min_const_fn.rs:78:37 | LL | const fn foo26() -> &'static u32 { &BAR } | ^^^ @@ -187,7 +47,7 @@ LL | const fn foo26() -> &'static u32 { &BAR } = help: to fix this, the value can be extracted to a `const` and then used. error: pointers cannot be cast to integers during const eval - --> $DIR/min_const_fn.rs:91:42 + --> $DIR/min_const_fn.rs:79:42 | LL | const fn foo30(x: *const u32) -> usize { x as usize } | ^^^^^^^^^^ @@ -196,7 +56,7 @@ LL | const fn foo30(x: *const u32) -> usize { x as usize } = note: avoiding this restriction via `transmute`, `union`, or raw pointers leads to compile-time undefined behavior error: pointers cannot be cast to integers during const eval - --> $DIR/min_const_fn.rs:93:63 + --> $DIR/min_const_fn.rs:81:63 | LL | const fn foo30_with_unsafe(x: *const u32) -> usize { unsafe { x as usize } } | ^^^^^^^^^^ @@ -205,7 +65,7 @@ LL | const fn foo30_with_unsafe(x: *const u32) -> usize { unsafe { x as usize } = note: avoiding this restriction via `transmute`, `union`, or raw pointers leads to compile-time undefined behavior error: pointers cannot be cast to integers during const eval - --> $DIR/min_const_fn.rs:95:42 + --> $DIR/min_const_fn.rs:83:42 | LL | const fn foo30_2(x: *mut u32) -> usize { x as usize } | ^^^^^^^^^^ @@ -214,7 +74,7 @@ LL | const fn foo30_2(x: *mut u32) -> usize { x as usize } = note: avoiding this restriction via `transmute`, `union`, or raw pointers leads to compile-time undefined behavior error: pointers cannot be cast to integers during const eval - --> $DIR/min_const_fn.rs:97:63 + --> $DIR/min_const_fn.rs:85:63 | LL | const fn foo30_2_with_unsafe(x: *mut u32) -> usize { unsafe { x as usize } } | ^^^^^^^^^^ @@ -222,18 +82,8 @@ LL | const fn foo30_2_with_unsafe(x: *mut u32) -> usize { unsafe { x as usize } = note: at compile-time, pointers do not have an integer value = note: avoiding this restriction via `transmute`, `union`, or raw pointers leads to compile-time undefined behavior -error[E0658]: mutable references are not allowed in constant functions - --> $DIR/min_const_fn.rs:100:14 - | -LL | const fn inc(x: &mut i32) { *x += 1 } - | ^ - | - = note: see issue #57349 for more information - = help: add `#![feature(const_mut_refs)]` to the crate attributes to enable - = note: this compiler was built on YYYY-MM-DD; consider upgrading it if it is out of date - error[E0493]: destructor of `AlanTuring` cannot be evaluated at compile-time - --> $DIR/min_const_fn.rs:122:19 + --> $DIR/min_const_fn.rs:109:19 | LL | const fn no_apit2(_x: AlanTuring) {} | ^^ - value is dropped here @@ -241,14 +91,14 @@ LL | const fn no_apit2(_x: AlanTuring) {} | the destructor for this type cannot be evaluated in constant functions error[E0493]: destructor of `impl std::fmt::Debug` cannot be evaluated at compile-time - --> $DIR/min_const_fn.rs:124:18 + --> $DIR/min_const_fn.rs:111:18 | LL | const fn no_apit(_x: impl std::fmt::Debug) {} | ^^ - value is dropped here | | | the destructor for this type cannot be evaluated in constant functions -error: aborting due to 24 previous errors; 2 warnings emitted +error: aborting due to 11 previous errors Some errors have detailed explanations: E0493, E0658. For more information about an error, try `rustc --explain E0493`. diff --git a/tests/ui/consts/min_const_fn/min_const_fn_libstd_stability.rs b/tests/ui/consts/min_const_fn/min_const_fn_libstd_stability.rs index 480b16b28a5..461499e942f 100644 --- a/tests/ui/consts/min_const_fn/min_const_fn_libstd_stability.rs +++ b/tests/ui/consts/min_const_fn/min_const_fn_libstd_stability.rs @@ -1,10 +1,11 @@ +//@ compile-flags: --edition 2018 #![unstable(feature = "humans", reason = "who ever let humans program computers, we're apparently really bad at it", issue = "none")] -#![feature(const_refs_to_cell, foo, foo2)] -#![feature(staged_api)] +#![feature(foo, foo2)] +#![feature(const_async_blocks, staged_api)] #[stable(feature = "rust1", since = "1.0.0")] #[rustc_const_unstable(feature="foo", issue = "none")] @@ -27,10 +28,8 @@ const fn bar2() -> u32 { foo2() } //~ ERROR not yet stable as a const fn #[rustc_const_stable(feature = "rust1", since = "1.0.0")] // conformity is required const fn bar3() -> u32 { - let x = std::cell::Cell::new(0u32); - x.get(); - //~^ ERROR const-stable function cannot use `#[feature(const_refs_to_cell)]` - //~| ERROR cannot call non-const fn + let x = async { 13 }; + //~^ ERROR const-stable function cannot use `#[feature(const_async_blocks)]` foo() //~^ ERROR is not yet stable as a const fn } diff --git a/tests/ui/consts/min_const_fn/min_const_fn_libstd_stability.stderr b/tests/ui/consts/min_const_fn/min_const_fn_libstd_stability.stderr index cb447719f9c..fedc5a4809d 100644 --- a/tests/ui/consts/min_const_fn/min_const_fn_libstd_stability.stderr +++ b/tests/ui/consts/min_const_fn/min_const_fn_libstd_stability.stderr @@ -1,5 +1,5 @@ error: `foo` is not yet stable as a const fn - --> $DIR/min_const_fn_libstd_stability.rs:16:25 + --> $DIR/min_const_fn_libstd_stability.rs:17:25 | LL | const fn bar() -> u32 { foo() } | ^^^^^ @@ -7,18 +7,18 @@ LL | const fn bar() -> u32 { foo() } = help: const-stable functions can only call other const-stable functions error: `foo2` is not yet stable as a const fn - --> $DIR/min_const_fn_libstd_stability.rs:24:26 + --> $DIR/min_const_fn_libstd_stability.rs:25:26 | LL | const fn bar2() -> u32 { foo2() } | ^^^^^^ | = help: const-stable functions can only call other const-stable functions -error: const-stable function cannot use `#[feature(const_refs_to_cell)]` - --> $DIR/min_const_fn_libstd_stability.rs:31:5 +error: const-stable function cannot use `#[feature(const_async_blocks)]` + --> $DIR/min_const_fn_libstd_stability.rs:31:13 | -LL | x.get(); - | ^ +LL | let x = async { 13 }; + | ^^^^^^^^^^^^ | help: if the function is not (yet) meant to be stable, make this function unstably const | @@ -27,20 +27,12 @@ LL | const fn bar3() -> u32 { | help: otherwise, as a last resort `#[rustc_allow_const_fn_unstable]` can be used to bypass stability checks (but requires team approval) | -LL + #[rustc_allow_const_fn_unstable(const_refs_to_cell)] +LL + #[rustc_allow_const_fn_unstable(const_async_blocks)] LL | const fn bar3() -> u32 { | -error[E0015]: cannot call non-const fn `Cell::::get` in constant functions - --> $DIR/min_const_fn_libstd_stability.rs:31:7 - | -LL | x.get(); - | ^^^^^ - | - = note: calls in constant functions are limited to constant functions, tuple structs and tuple variants - error: `foo` is not yet stable as a const fn - --> $DIR/min_const_fn_libstd_stability.rs:34:5 + --> $DIR/min_const_fn_libstd_stability.rs:33:5 | LL | foo() | ^^^^^ @@ -48,13 +40,12 @@ LL | foo() = help: const-stable functions can only call other const-stable functions error: `foo2_gated` is not yet stable as a const fn - --> $DIR/min_const_fn_libstd_stability.rs:45:32 + --> $DIR/min_const_fn_libstd_stability.rs:44:32 | LL | const fn bar2_gated() -> u32 { foo2_gated() } | ^^^^^^^^^^^^ | = help: const-stable functions can only call other const-stable functions -error: aborting due to 6 previous errors +error: aborting due to 5 previous errors -For more information about this error, try `rustc --explain E0015`. diff --git a/tests/ui/consts/min_const_fn/min_const_fn_unsafe_bad.rs b/tests/ui/consts/min_const_fn/min_const_fn_unsafe_bad.rs deleted file mode 100644 index df20ff446cd..00000000000 --- a/tests/ui/consts/min_const_fn/min_const_fn_unsafe_bad.rs +++ /dev/null @@ -1,13 +0,0 @@ -const fn bad_const_fn_deref_raw(x: *mut usize) -> &'static usize { unsafe { &*x } } -//~^ dereferencing raw mutable pointers in constant functions - -const unsafe fn bad_const_unsafe_deref_raw(x: *mut usize) -> usize { *x } -//~^ dereferencing raw mutable pointers in constant functions - -const unsafe fn bad_const_unsafe_deref_raw_ref(x: *mut usize) -> &'static usize { &*x } -//~^ dereferencing raw mutable pointers in constant functions - -const unsafe fn bad_const_unsafe_deref_raw_underscore(x: *mut usize) { let _ = *x; } -//~^ dereferencing raw mutable pointers in constant functions - -fn main() {} diff --git a/tests/ui/consts/min_const_fn/min_const_fn_unsafe_bad.stderr b/tests/ui/consts/min_const_fn/min_const_fn_unsafe_bad.stderr deleted file mode 100644 index 13d733494d2..00000000000 --- a/tests/ui/consts/min_const_fn/min_const_fn_unsafe_bad.stderr +++ /dev/null @@ -1,43 +0,0 @@ -error[E0658]: dereferencing raw mutable pointers in constant functions is unstable - --> $DIR/min_const_fn_unsafe_bad.rs:1:77 - | -LL | const fn bad_const_fn_deref_raw(x: *mut usize) -> &'static usize { unsafe { &*x } } - | ^^^ - | - = note: see issue #57349 for more information - = help: add `#![feature(const_mut_refs)]` to the crate attributes to enable - = note: this compiler was built on YYYY-MM-DD; consider upgrading it if it is out of date - -error[E0658]: dereferencing raw mutable pointers in constant functions is unstable - --> $DIR/min_const_fn_unsafe_bad.rs:4:70 - | -LL | const unsafe fn bad_const_unsafe_deref_raw(x: *mut usize) -> usize { *x } - | ^^ - | - = note: see issue #57349 for more information - = help: add `#![feature(const_mut_refs)]` to the crate attributes to enable - = note: this compiler was built on YYYY-MM-DD; consider upgrading it if it is out of date - -error[E0658]: dereferencing raw mutable pointers in constant functions is unstable - --> $DIR/min_const_fn_unsafe_bad.rs:7:83 - | -LL | const unsafe fn bad_const_unsafe_deref_raw_ref(x: *mut usize) -> &'static usize { &*x } - | ^^^ - | - = note: see issue #57349 for more information - = help: add `#![feature(const_mut_refs)]` to the crate attributes to enable - = note: this compiler was built on YYYY-MM-DD; consider upgrading it if it is out of date - -error[E0658]: dereferencing raw mutable pointers in constant functions is unstable - --> $DIR/min_const_fn_unsafe_bad.rs:10:80 - | -LL | const unsafe fn bad_const_unsafe_deref_raw_underscore(x: *mut usize) { let _ = *x; } - | ^^ - | - = note: see issue #57349 for more information - = help: add `#![feature(const_mut_refs)]` to the crate attributes to enable - = note: this compiler was built on YYYY-MM-DD; consider upgrading it if it is out of date - -error: aborting due to 4 previous errors - -For more information about this error, try `rustc --explain E0658`. diff --git a/tests/ui/consts/min_const_fn/min_const_fn_unsafe_ok.rs b/tests/ui/consts/min_const_fn/min_const_fn_unsafe_ok.rs index 06e7d6f5d70..8b09b529ecc 100644 --- a/tests/ui/consts/min_const_fn/min_const_fn_unsafe_ok.rs +++ b/tests/ui/consts/min_const_fn/min_const_fn_unsafe_ok.rs @@ -41,4 +41,12 @@ const unsafe fn call_unsafe_generic_cell_const_unsafe_fn_immediate() ret_null_mut_ptr_no_unsafe::>>() } +const fn bad_const_fn_deref_raw(x: *mut usize) -> &'static usize { unsafe { &*x } } + +const unsafe fn bad_const_unsafe_deref_raw(x: *mut usize) -> usize { *x } + +const unsafe fn bad_const_unsafe_deref_raw_ref(x: *mut usize) -> &'static usize { &*x } + +const unsafe fn bad_const_unsafe_deref_raw_underscore(x: *mut usize) { let _ = *x; } + fn main() {} diff --git a/tests/ui/consts/min_const_fn/min_const_unsafe_fn_libstd_stability.rs b/tests/ui/consts/min_const_fn/min_const_unsafe_fn_libstd_stability.rs index f2a54b8a13d..274b4444799 100644 --- a/tests/ui/consts/min_const_fn/min_const_unsafe_fn_libstd_stability.rs +++ b/tests/ui/consts/min_const_fn/min_const_unsafe_fn_libstd_stability.rs @@ -3,7 +3,7 @@ we're apparently really bad at it", issue = "none")] -#![feature(const_refs_to_cell, foo, foo2)] +#![feature(foo, foo2)] #![feature(staged_api)] #[stable(feature = "rust1", since = "1.0.0")] diff --git a/tests/ui/consts/min_const_fn/mutable_borrow.rs b/tests/ui/consts/min_const_fn/mutable_borrow.rs deleted file mode 100644 index 580b1d50f77..00000000000 --- a/tests/ui/consts/min_const_fn/mutable_borrow.rs +++ /dev/null @@ -1,17 +0,0 @@ -const fn mutable_ref_in_const() -> u8 { - let mut a = 0; - let b = &mut a; //~ ERROR mutable references - *b -} - -struct X; - -impl X { - const fn inherent_mutable_ref_in_const() -> u8 { - let mut a = 0; - let b = &mut a; //~ ERROR mutable references - *b - } -} - -fn main() {} diff --git a/tests/ui/consts/min_const_fn/mutable_borrow.stderr b/tests/ui/consts/min_const_fn/mutable_borrow.stderr deleted file mode 100644 index 31653602c75..00000000000 --- a/tests/ui/consts/min_const_fn/mutable_borrow.stderr +++ /dev/null @@ -1,23 +0,0 @@ -error[E0658]: mutable references are not allowed in constant functions - --> $DIR/mutable_borrow.rs:3:13 - | -LL | let b = &mut a; - | ^^^^^^ - | - = note: see issue #57349 for more information - = help: add `#![feature(const_mut_refs)]` to the crate attributes to enable - = note: this compiler was built on YYYY-MM-DD; consider upgrading it if it is out of date - -error[E0658]: mutable references are not allowed in constant functions - --> $DIR/mutable_borrow.rs:12:17 - | -LL | let b = &mut a; - | ^^^^^^ - | - = note: see issue #57349 for more information - = help: add `#![feature(const_mut_refs)]` to the crate attributes to enable - = note: this compiler was built on YYYY-MM-DD; consider upgrading it if it is out of date - -error: aborting due to 2 previous errors - -For more information about this error, try `rustc --explain E0658`. diff --git a/tests/ui/consts/miri_unleashed/abi-mismatch.rs b/tests/ui/consts/miri_unleashed/abi-mismatch.rs index 57680479a17..da5b1dd5802 100644 --- a/tests/ui/consts/miri_unleashed/abi-mismatch.rs +++ b/tests/ui/consts/miri_unleashed/abi-mismatch.rs @@ -1,8 +1,6 @@ // Checks that we report ABI mismatches for "const extern fn" //@ compile-flags: -Z unleash-the-miri-inside-of-you -#![feature(const_extern_fn)] - const extern "C" fn c_fn() {} const fn call_rust_fn(my_fn: extern "Rust" fn()) { diff --git a/tests/ui/consts/miri_unleashed/abi-mismatch.stderr b/tests/ui/consts/miri_unleashed/abi-mismatch.stderr index 51364b01a2d..639795efae7 100644 --- a/tests/ui/consts/miri_unleashed/abi-mismatch.stderr +++ b/tests/ui/consts/miri_unleashed/abi-mismatch.stderr @@ -1,16 +1,16 @@ error[E0080]: could not evaluate static initializer - --> $DIR/abi-mismatch.rs:9:5 + --> $DIR/abi-mismatch.rs:7:5 | LL | my_fn(); | ^^^^^^^ calling a function with calling convention C using calling convention Rust | note: inside `call_rust_fn` - --> $DIR/abi-mismatch.rs:9:5 + --> $DIR/abi-mismatch.rs:7:5 | LL | my_fn(); | ^^^^^^^ note: inside `VAL` - --> $DIR/abi-mismatch.rs:15:18 + --> $DIR/abi-mismatch.rs:13:18 | LL | static VAL: () = call_rust_fn(unsafe { std::mem::transmute(c_fn as extern "C" fn()) }); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ @@ -18,7 +18,7 @@ LL | static VAL: () = call_rust_fn(unsafe { std::mem::transmute(c_fn as extern " warning: skipping const checks | help: skipping check that does not even have a feature gate - --> $DIR/abi-mismatch.rs:9:5 + --> $DIR/abi-mismatch.rs:7:5 | LL | my_fn(); | ^^^^^^^ diff --git a/tests/ui/consts/miri_unleashed/box.stderr b/tests/ui/consts/miri_unleashed/box.stderr index a0518c99cda..25cefa036eb 100644 --- a/tests/ui/consts/miri_unleashed/box.stderr +++ b/tests/ui/consts/miri_unleashed/box.stderr @@ -11,16 +11,6 @@ help: skipping check that does not even have a feature gate | LL | &mut *(Box::new(0)) | ^^^^^^^^^^^^^ -help: skipping check for `const_mut_refs` feature - --> $DIR/box.rs:8:5 - | -LL | &mut *(Box::new(0)) - | ^^^^^^^^^^^^^^^^^^^ -help: skipping check for `const_mut_refs` feature - --> $DIR/box.rs:8:5 - | -LL | &mut *(Box::new(0)) - | ^^^^^^^^^^^^^^^^^^^ error: aborting due to 1 previous error; 1 warning emitted diff --git a/tests/ui/consts/miri_unleashed/mutable_references.stderr b/tests/ui/consts/miri_unleashed/mutable_references.stderr index 793cbac6879..874dd0389d4 100644 --- a/tests/ui/consts/miri_unleashed/mutable_references.stderr +++ b/tests/ui/consts/miri_unleashed/mutable_references.stderr @@ -177,11 +177,6 @@ help: skipping check for `const_refs_to_static` feature | LL | const SUBTLE: &mut i32 = unsafe { static mut STATIC: i32 = 0; &mut STATIC }; | ^^^^^^ -help: skipping check for `const_mut_refs` feature - --> $DIR/mutable_references.rs:30:63 - | -LL | const SUBTLE: &mut i32 = unsafe { static mut STATIC: i32 = 0; &mut STATIC }; - | ^^^^^^^^^^^ help: skipping check that does not even have a feature gate --> $DIR/mutable_references.rs:40:28 | @@ -197,16 +192,6 @@ help: skipping check that does not even have a feature gate | LL | const SNEAKY: &dyn Sync = &Synced { x: UnsafeCell::new(42) }; | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ -help: skipping check for `const_mut_refs` feature - --> $DIR/mutable_references.rs:65:49 - | -LL | static mut MUT_TO_READONLY: &mut i32 = unsafe { &mut *(&READONLY as *const _ as *mut _) }; - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ -help: skipping check for `const_mut_refs` feature - --> $DIR/mutable_references.rs:65:49 - | -LL | static mut MUT_TO_READONLY: &mut i32 = unsafe { &mut *(&READONLY as *const _ as *mut _) }; - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: skipping check for `const_refs_to_static` feature --> $DIR/mutable_references.rs:72:43 | diff --git a/tests/ui/consts/miri_unleashed/static-no-inner-mut.rs b/tests/ui/consts/miri_unleashed/static-no-inner-mut.rs index 2b8f32deda7..126d78158fe 100644 --- a/tests/ui/consts/miri_unleashed/static-no-inner-mut.rs +++ b/tests/ui/consts/miri_unleashed/static-no-inner-mut.rs @@ -1,6 +1,6 @@ //@ stderr-per-bitwidth //@ compile-flags: -Zunleash-the-miri-inside-of-you -#![feature(const_refs_to_cell, const_mut_refs)] + // All "inner" allocations that come with a `static` are interned immutably. This means it is // crucial that we do not accept any form of (interior) mutability there. use std::sync::atomic::*; diff --git a/tests/ui/consts/missing_span_in_backtrace.rs b/tests/ui/consts/missing_span_in_backtrace.rs index d45deee18fa..ea457c96f15 100644 --- a/tests/ui/consts/missing_span_in_backtrace.rs +++ b/tests/ui/consts/missing_span_in_backtrace.rs @@ -2,7 +2,6 @@ #![feature(const_swap)] -#![feature(const_mut_refs)] use std::{ mem::{self, MaybeUninit}, ptr, diff --git a/tests/ui/consts/missing_span_in_backtrace.stderr b/tests/ui/consts/missing_span_in_backtrace.stderr index 9e0506e7e38..72d15702e89 100644 --- a/tests/ui/consts/missing_span_in_backtrace.stderr +++ b/tests/ui/consts/missing_span_in_backtrace.stderr @@ -10,13 +10,13 @@ note: inside `std::ptr::swap_nonoverlapping_simple_untyped::>` note: inside `swap_nonoverlapping::>` --> $SRC_DIR/core/src/ptr/mod.rs:LL:COL note: inside `X` - --> $DIR/missing_span_in_backtrace.rs:17:9 + --> $DIR/missing_span_in_backtrace.rs:16:9 | -17 | / ptr::swap_nonoverlapping( -18 | | &mut ptr1 as *mut _ as *mut MaybeUninit, -19 | | &mut ptr2 as *mut _ as *mut MaybeUninit, -20 | | mem::size_of::<&i32>(), -21 | | ); +16 | / ptr::swap_nonoverlapping( +17 | | &mut ptr1 as *mut _ as *mut MaybeUninit, +18 | | &mut ptr2 as *mut _ as *mut MaybeUninit, +19 | | mem::size_of::<&i32>(), +20 | | ); | |_________^ = help: this code performed an operation that depends on the underlying bytes representing a pointer = help: the absolute address of a pointer is not known at compile-time, so such operations are not supported diff --git a/tests/ui/consts/mut-ptr-to-static.rs b/tests/ui/consts/mut-ptr-to-static.rs index e921365c7d4..e2e256980d2 100644 --- a/tests/ui/consts/mut-ptr-to-static.rs +++ b/tests/ui/consts/mut-ptr-to-static.rs @@ -1,5 +1,4 @@ //@run-pass -#![feature(const_mut_refs)] #![feature(sync_unsafe_cell)] use std::cell::SyncUnsafeCell; diff --git a/tests/ui/consts/promoted-const-drop.rs b/tests/ui/consts/promoted-const-drop.rs index b7d92d6523a..c6ea0d0c924 100644 --- a/tests/ui/consts/promoted-const-drop.rs +++ b/tests/ui/consts/promoted-const-drop.rs @@ -1,5 +1,4 @@ #![feature(const_trait_impl)] -#![feature(const_mut_refs)] struct A(); diff --git a/tests/ui/consts/promoted-const-drop.stderr b/tests/ui/consts/promoted-const-drop.stderr index 1201f608232..e015f756206 100644 --- a/tests/ui/consts/promoted-const-drop.stderr +++ b/tests/ui/consts/promoted-const-drop.stderr @@ -1,5 +1,5 @@ error: const `impl` for trait `Drop` which is not marked with `#[const_trait]` - --> $DIR/promoted-const-drop.rs:6:12 + --> $DIR/promoted-const-drop.rs:5:12 | LL | impl const Drop for A { | ^^^^ @@ -8,7 +8,7 @@ LL | impl const Drop for A { = note: adding a non-const method body in the future would be a breaking change error[E0716]: temporary value dropped while borrowed - --> $DIR/promoted-const-drop.rs:14:26 + --> $DIR/promoted-const-drop.rs:13:26 | LL | let _: &'static A = &A(); | ---------- ^^^ creates a temporary value which is freed while still in use @@ -19,7 +19,7 @@ LL | } | - temporary value is freed at the end of this statement error[E0716]: temporary value dropped while borrowed - --> $DIR/promoted-const-drop.rs:15:28 + --> $DIR/promoted-const-drop.rs:14:28 | LL | let _: &'static [A] = &[C]; | ------------ ^^^ creates a temporary value which is freed while still in use diff --git a/tests/ui/consts/promoted_const_call.rs b/tests/ui/consts/promoted_const_call.rs index deaa053c415..c3920ff7241 100644 --- a/tests/ui/consts/promoted_const_call.rs +++ b/tests/ui/consts/promoted_const_call.rs @@ -1,6 +1,5 @@ //@ known-bug: #103507 -#![feature(const_mut_refs)] #![feature(const_trait_impl)] struct Panic; diff --git a/tests/ui/consts/promoted_const_call.stderr b/tests/ui/consts/promoted_const_call.stderr index 64bf6bd73b0..bcb9dfb704b 100644 --- a/tests/ui/consts/promoted_const_call.stderr +++ b/tests/ui/consts/promoted_const_call.stderr @@ -1,5 +1,5 @@ error: const `impl` for trait `Drop` which is not marked with `#[const_trait]` - --> $DIR/promoted_const_call.rs:7:12 + --> $DIR/promoted_const_call.rs:6:12 | LL | impl const Drop for Panic { fn drop(&mut self) { panic!(); } } | ^^^^ @@ -8,7 +8,7 @@ LL | impl const Drop for Panic { fn drop(&mut self) { panic!(); } } = note: adding a non-const method body in the future would be a breaking change error[E0716]: temporary value dropped while borrowed - --> $DIR/promoted_const_call.rs:11:26 + --> $DIR/promoted_const_call.rs:10:26 | LL | let _: &'static _ = &id(&Panic); | ---------- ^^^^^^^^^^ creates a temporary value which is freed while still in use @@ -19,7 +19,7 @@ LL | }; | - temporary value is freed at the end of this statement error[E0716]: temporary value dropped while borrowed - --> $DIR/promoted_const_call.rs:11:30 + --> $DIR/promoted_const_call.rs:10:30 | LL | let _: &'static _ = &id(&Panic); | ---------- ^^^^^ - temporary value is freed at the end of this statement @@ -28,7 +28,7 @@ LL | let _: &'static _ = &id(&Panic); | type annotation requires that borrow lasts for `'static` error[E0716]: temporary value dropped while borrowed - --> $DIR/promoted_const_call.rs:17:26 + --> $DIR/promoted_const_call.rs:16:26 | LL | let _: &'static _ = &id(&Panic); | ---------- ^^^^^^^^^^ creates a temporary value which is freed while still in use @@ -39,7 +39,7 @@ LL | } | - temporary value is freed at the end of this statement error[E0716]: temporary value dropped while borrowed - --> $DIR/promoted_const_call.rs:17:30 + --> $DIR/promoted_const_call.rs:16:30 | LL | let _: &'static _ = &id(&Panic); | ---------- ^^^^^ - temporary value is freed at the end of this statement @@ -48,7 +48,7 @@ LL | let _: &'static _ = &id(&Panic); | type annotation requires that borrow lasts for `'static` error[E0716]: temporary value dropped while borrowed - --> $DIR/promoted_const_call.rs:20:26 + --> $DIR/promoted_const_call.rs:19:26 | LL | let _: &'static _ = &&(Panic, 0).1; | ---------- ^^^^^^^^^^^^^ creates a temporary value which is freed while still in use @@ -59,7 +59,7 @@ LL | } | - temporary value is freed at the end of this statement error[E0716]: temporary value dropped while borrowed - --> $DIR/promoted_const_call.rs:20:27 + --> $DIR/promoted_const_call.rs:19:27 | LL | let _: &'static _ = &&(Panic, 0).1; | ---------- ^^^^^^^^^^ creates a temporary value which is freed while still in use diff --git a/tests/ui/consts/promotion-mutable-ref.rs b/tests/ui/consts/promotion-mutable-ref.rs index 0bca8a8dca4..36a0c8ad805 100644 --- a/tests/ui/consts/promotion-mutable-ref.rs +++ b/tests/ui/consts/promotion-mutable-ref.rs @@ -1,5 +1,4 @@ //@ run-pass -#![feature(const_mut_refs)] static mut TEST: i32 = { // We must not promote this, as CTFE needs to be able to mutate it later. diff --git a/tests/ui/consts/qualif-indirect-mutation-fail.rs b/tests/ui/consts/qualif-indirect-mutation-fail.rs index a99d0633ba1..c6e08a557c8 100644 --- a/tests/ui/consts/qualif-indirect-mutation-fail.rs +++ b/tests/ui/consts/qualif-indirect-mutation-fail.rs @@ -1,5 +1,4 @@ //@ compile-flags: --crate-type=lib -#![feature(const_mut_refs)] #![feature(const_precise_live_drops)] #![feature(const_swap)] diff --git a/tests/ui/consts/qualif-indirect-mutation-fail.stderr b/tests/ui/consts/qualif-indirect-mutation-fail.stderr index 21c872ed13f..433dfba2257 100644 --- a/tests/ui/consts/qualif-indirect-mutation-fail.stderr +++ b/tests/ui/consts/qualif-indirect-mutation-fail.stderr @@ -1,5 +1,5 @@ error[E0493]: destructor of `Option` cannot be evaluated at compile-time - --> $DIR/qualif-indirect-mutation-fail.rs:14:9 + --> $DIR/qualif-indirect-mutation-fail.rs:13:9 | LL | let mut x = None; | ^^^^^ the destructor for this type cannot be evaluated in constants @@ -16,13 +16,13 @@ note: inside `std::ptr::drop_in_place:: - shim(Some(String))` note: inside `std::ptr::drop_in_place::> - shim(Some(Option))` --> $SRC_DIR/core/src/ptr/mod.rs:LL:COL note: inside `A1` - --> $DIR/qualif-indirect-mutation-fail.rs:20:1 + --> $DIR/qualif-indirect-mutation-fail.rs:19:1 | LL | }; | ^ error[E0493]: destructor of `Option` cannot be evaluated at compile-time - --> $DIR/qualif-indirect-mutation-fail.rs:30:9 + --> $DIR/qualif-indirect-mutation-fail.rs:29:9 | LL | let _z = x; | ^^ the destructor for this type cannot be evaluated in constants @@ -39,49 +39,49 @@ note: inside `std::ptr::drop_in_place:: - shim(Some(String))` note: inside `std::ptr::drop_in_place::> - shim(Some(Option))` --> $SRC_DIR/core/src/ptr/mod.rs:LL:COL note: inside `A2` - --> $DIR/qualif-indirect-mutation-fail.rs:31:1 + --> $DIR/qualif-indirect-mutation-fail.rs:30:1 | LL | }; | ^ error[E0493]: destructor of `(u32, Option)` cannot be evaluated at compile-time - --> $DIR/qualif-indirect-mutation-fail.rs:8:9 + --> $DIR/qualif-indirect-mutation-fail.rs:7:9 | LL | let mut a: (u32, Option) = (0, None); | ^^^^^ the destructor for this type cannot be evaluated in constant functions error[E0493]: destructor of `Option` cannot be evaluated at compile-time - --> $DIR/qualif-indirect-mutation-fail.rs:35:9 + --> $DIR/qualif-indirect-mutation-fail.rs:34:9 | LL | let x: Option = None; | ^ the destructor for this type cannot be evaluated in constant functions error[E0493]: destructor of `Option` cannot be evaluated at compile-time - --> $DIR/qualif-indirect-mutation-fail.rs:43:9 + --> $DIR/qualif-indirect-mutation-fail.rs:42:9 | LL | let _y = x; | ^^ the destructor for this type cannot be evaluated in constant functions error[E0493]: destructor of `Option` cannot be evaluated at compile-time - --> $DIR/qualif-indirect-mutation-fail.rs:51:9 + --> $DIR/qualif-indirect-mutation-fail.rs:50:9 | LL | let mut y: Option = None; | ^^^^^ the destructor for this type cannot be evaluated in constant functions error[E0493]: destructor of `Option` cannot be evaluated at compile-time - --> $DIR/qualif-indirect-mutation-fail.rs:48:9 + --> $DIR/qualif-indirect-mutation-fail.rs:47:9 | LL | let mut x: Option = None; | ^^^^^ the destructor for this type cannot be evaluated in constant functions error[E0493]: destructor of `Option` cannot be evaluated at compile-time - --> $DIR/qualif-indirect-mutation-fail.rs:61:9 + --> $DIR/qualif-indirect-mutation-fail.rs:60:9 | LL | let y: Option = None; | ^ the destructor for this type cannot be evaluated in constant functions error[E0493]: destructor of `Option` cannot be evaluated at compile-time - --> $DIR/qualif-indirect-mutation-fail.rs:58:9 + --> $DIR/qualif-indirect-mutation-fail.rs:57:9 | LL | let x: Option = None; | ^ the destructor for this type cannot be evaluated in constant functions diff --git a/tests/ui/consts/qualif-indirect-mutation-pass.rs b/tests/ui/consts/qualif-indirect-mutation-pass.rs index 9d5f0d4306d..de417216a49 100644 --- a/tests/ui/consts/qualif-indirect-mutation-pass.rs +++ b/tests/ui/consts/qualif-indirect-mutation-pass.rs @@ -1,6 +1,5 @@ //@ compile-flags: --crate-type=lib //@ check-pass -#![feature(const_mut_refs)] #![feature(const_precise_live_drops)] // Mutable reference allows only mutation of !Drop place. diff --git a/tests/ui/consts/refs-to-cell-in-final.rs b/tests/ui/consts/refs-to-cell-in-final.rs index cfb458e7ace..844b140cff2 100644 --- a/tests/ui/consts/refs-to-cell-in-final.rs +++ b/tests/ui/consts/refs-to-cell-in-final.rs @@ -1,8 +1,8 @@ -#![feature(const_refs_to_cell)] - use std::cell::*; -struct SyncPtr { x : *const T } +struct SyncPtr { + x: *const T, +} unsafe impl Sync for SyncPtr {} // These pass the lifetime checks because of the "tail expression" / "outer scope" rule. @@ -37,4 +37,13 @@ const NONE_EXPLICIT_PROMOTED: &'static Option> = { x }; +// Not okay, since we are borrowing something with interior mutability. +const INTERIOR_MUT_VARIANT: &Option> = &{ + //~^ERROR: cannot refer to interior mutable data + let mut x = None; + assert!(x.is_none()); + x = Some(UnsafeCell::new(false)); + x +}; + fn main() {} diff --git a/tests/ui/consts/refs-to-cell-in-final.stderr b/tests/ui/consts/refs-to-cell-in-final.stderr index fae16fa0125..8d82d94f412 100644 --- a/tests/ui/consts/refs-to-cell-in-final.stderr +++ b/tests/ui/consts/refs-to-cell-in-final.stderr @@ -12,6 +12,19 @@ error[E0492]: constants cannot refer to interior mutable data LL | const RAW_SYNC_C: SyncPtr> = SyncPtr { x: &Cell::new(42) }; | ^^^^^^^^^^^^^^ this borrow of an interior mutable value may end up in the final value -error: aborting due to 2 previous errors +error[E0492]: constants cannot refer to interior mutable data + --> $DIR/refs-to-cell-in-final.rs:41:57 + | +LL | const INTERIOR_MUT_VARIANT: &Option> = &{ + | _________________________________________________________^ +LL | | +LL | | let mut x = None; +LL | | assert!(x.is_none()); +LL | | x = Some(UnsafeCell::new(false)); +LL | | x +LL | | }; + | |_^ this borrow of an interior mutable value may end up in the final value + +error: aborting due to 3 previous errors For more information about this error, try `rustc --explain E0492`. diff --git a/tests/ui/consts/slice-index-overflow-issue-130284.rs b/tests/ui/consts/slice-index-overflow-issue-130284.rs new file mode 100644 index 00000000000..29900908256 --- /dev/null +++ b/tests/ui/consts/slice-index-overflow-issue-130284.rs @@ -0,0 +1,13 @@ +const C: () = { + let value = [1, 2]; + let ptr = value.as_ptr().wrapping_add(2); + let fat = std::ptr::slice_from_raw_parts(ptr, usize::MAX); + unsafe { + // This used to ICE, but it should just report UB. + let _ice = (*fat)[usize::MAX - 1]; + //~^ERROR: constant value failed + //~| overflow + } +}; + +fn main() {} diff --git a/tests/ui/consts/slice-index-overflow-issue-130284.stderr b/tests/ui/consts/slice-index-overflow-issue-130284.stderr new file mode 100644 index 00000000000..e3e676c8949 --- /dev/null +++ b/tests/ui/consts/slice-index-overflow-issue-130284.stderr @@ -0,0 +1,9 @@ +error[E0080]: evaluation of constant value failed + --> $DIR/slice-index-overflow-issue-130284.rs:7:20 + | +LL | let _ice = (*fat)[usize::MAX - 1]; + | ^^^^^^^^^^^^^^^^^^^^^^ overflowing pointer arithmetic: the total offset in bytes does not fit in an `isize` + +error: aborting due to 1 previous error + +For more information about this error, try `rustc --explain E0080`. diff --git a/tests/ui/consts/static_mut_containing_mut_ref2.rs b/tests/ui/consts/static_mut_containing_mut_ref2.rs index 547f6449f13..2b1fe55df78 100644 --- a/tests/ui/consts/static_mut_containing_mut_ref2.rs +++ b/tests/ui/consts/static_mut_containing_mut_ref2.rs @@ -1,13 +1,10 @@ -//@ revisions: stock mut_refs #![allow(static_mut_refs)] -#![cfg_attr(mut_refs, feature(const_mut_refs))] static mut STDERR_BUFFER_SPACE: u8 = 0; pub static mut STDERR_BUFFER: () = unsafe { *(&mut STDERR_BUFFER_SPACE) = 42; - //[mut_refs]~^ ERROR could not evaluate static initializer - //[stock]~^^ ERROR mutation through a reference is not allowed in statics + //~^ ERROR could not evaluate static initializer }; fn main() {} diff --git a/tests/ui/consts/static_mut_containing_mut_ref2.mut_refs.stderr b/tests/ui/consts/static_mut_containing_mut_ref2.stderr similarity index 86% rename from tests/ui/consts/static_mut_containing_mut_ref2.mut_refs.stderr rename to tests/ui/consts/static_mut_containing_mut_ref2.stderr index 42cb119d2ae..37cd2b51ad1 100644 --- a/tests/ui/consts/static_mut_containing_mut_ref2.mut_refs.stderr +++ b/tests/ui/consts/static_mut_containing_mut_ref2.stderr @@ -1,5 +1,5 @@ error[E0080]: could not evaluate static initializer - --> $DIR/static_mut_containing_mut_ref2.rs:8:5 + --> $DIR/static_mut_containing_mut_ref2.rs:6:5 | LL | *(&mut STDERR_BUFFER_SPACE) = 42; | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ modifying a static's initial value from another static's initializer diff --git a/tests/ui/consts/static_mut_containing_mut_ref2.stock.stderr b/tests/ui/consts/static_mut_containing_mut_ref2.stock.stderr deleted file mode 100644 index 5ff9c0b6e2b..00000000000 --- a/tests/ui/consts/static_mut_containing_mut_ref2.stock.stderr +++ /dev/null @@ -1,13 +0,0 @@ -error[E0658]: mutation through a reference is not allowed in statics - --> $DIR/static_mut_containing_mut_ref2.rs:8:5 - | -LL | *(&mut STDERR_BUFFER_SPACE) = 42; - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ - | - = note: see issue #57349 for more information - = help: add `#![feature(const_mut_refs)]` to the crate attributes to enable - = note: this compiler was built on YYYY-MM-DD; consider upgrading it if it is out of date - -error: aborting due to 1 previous error - -For more information about this error, try `rustc --explain E0658`. diff --git a/tests/ui/consts/std/cell.rs b/tests/ui/consts/std/cell.rs index f1ef541319a..5f8236245ab 100644 --- a/tests/ui/consts/std/cell.rs +++ b/tests/ui/consts/std/cell.rs @@ -1,5 +1,3 @@ -#![feature(const_refs_to_cell)] - use std::cell::*; // not ok, because this creates a dangling pointer, just like `let x = Cell::new(42).as_ptr()` would diff --git a/tests/ui/consts/std/cell.stderr b/tests/ui/consts/std/cell.stderr index 873b797a466..d505454b9ad 100644 --- a/tests/ui/consts/std/cell.stderr +++ b/tests/ui/consts/std/cell.stderr @@ -1,23 +1,23 @@ error: encountered dangling pointer in final value of static - --> $DIR/cell.rs:6:1 + --> $DIR/cell.rs:4:1 | LL | static FOO: Wrap<*mut u32> = Wrap(Cell::new(42).as_ptr()); | ^^^^^^^^^^^^^^^^^^^^^^^^^^ error: encountered dangling pointer in final value of constant - --> $DIR/cell.rs:8:1 + --> $DIR/cell.rs:6:1 | LL | const FOO_CONST: Wrap<*mut u32> = Wrap(Cell::new(42).as_ptr()); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ error: encountered dangling pointer in final value of constant - --> $DIR/cell.rs:22:1 + --> $DIR/cell.rs:20:1 | LL | const FOO4_CONST: Wrap<*mut u32> = Wrap(FOO3_CONST.0.as_ptr()); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ error: encountered dangling pointer in final value of constant - --> $DIR/cell.rs:27:1 + --> $DIR/cell.rs:25:1 | LL | const FOO2: *mut u32 = Cell::new(42).as_ptr(); | ^^^^^^^^^^^^^^^^^^^^ diff --git a/tests/ui/consts/unwind-abort.rs b/tests/ui/consts/unwind-abort.rs index 1dd33f327fb..b62fa81da06 100644 --- a/tests/ui/consts/unwind-abort.rs +++ b/tests/ui/consts/unwind-abort.rs @@ -1,7 +1,5 @@ //@ check-pass -#![feature(const_extern_fn)] - // We don't unwind in const-eval anyways. const extern "C" fn foo() { panic!() diff --git a/tests/ui/consts/write_to_mut_ref_dest.rs b/tests/ui/consts/write_to_mut_ref_dest.rs index 42ac2284038..18ded32a76f 100644 --- a/tests/ui/consts/write_to_mut_ref_dest.rs +++ b/tests/ui/consts/write_to_mut_ref_dest.rs @@ -1,17 +1,14 @@ -//@ revisions: stock mut_refs -//@[mut_refs] check-pass - -#![cfg_attr(mut_refs, feature(const_mut_refs))] - -use std::cell::Cell; +//@run-pass const FOO: &u32 = { let mut a = 42; { - let b: *mut u32 = &mut a; //[stock]~ ERROR mutable references are not allowed in constants - unsafe { *b = 5; } //[stock]~ ERROR dereferencing raw mutable pointers in constants + let b: *mut u32 = &mut a; + unsafe { *b = 5; } } &{a} }; -fn main() {} +fn main() { + assert_eq!(*FOO, 5); +} diff --git a/tests/ui/consts/write_to_static_via_mut_ref.rs b/tests/ui/consts/write_to_static_via_mut_ref.rs index 39b830ae4e9..82ac85bd250 100644 --- a/tests/ui/consts/write_to_static_via_mut_ref.rs +++ b/tests/ui/consts/write_to_static_via_mut_ref.rs @@ -1,5 +1,3 @@ -#![feature(const_mut_refs)] - static OH_NO: &mut i32 = &mut 42; //~ ERROR mutable references are not allowed fn main() { assert_eq!(*OH_NO, 42); diff --git a/tests/ui/consts/write_to_static_via_mut_ref.stderr b/tests/ui/consts/write_to_static_via_mut_ref.stderr index f64f0db6b25..63ef788032f 100644 --- a/tests/ui/consts/write_to_static_via_mut_ref.stderr +++ b/tests/ui/consts/write_to_static_via_mut_ref.stderr @@ -1,11 +1,11 @@ error[E0764]: mutable references are not allowed in the final value of statics - --> $DIR/write_to_static_via_mut_ref.rs:3:26 + --> $DIR/write_to_static_via_mut_ref.rs:1:26 | LL | static OH_NO: &mut i32 = &mut 42; | ^^^^^^^ error[E0594]: cannot assign to `*OH_NO`, as `OH_NO` is an immutable static item - --> $DIR/write_to_static_via_mut_ref.rs:6:5 + --> $DIR/write_to_static_via_mut_ref.rs:4:5 | LL | *OH_NO = 43; | ^^^^^^^^^^^ cannot assign diff --git a/tests/ui/error-codes/E0017.rs b/tests/ui/error-codes/E0017.rs index c046f7859fa..e103d3bf5b1 100644 --- a/tests/ui/error-codes/E0017.rs +++ b/tests/ui/error-codes/E0017.rs @@ -1,5 +1,3 @@ -#![feature(const_mut_refs)] - //@ normalize-stderr-test: "\(size: ., align: .\)" -> "" //@ normalize-stderr-test: " +│ ╾─+╼" -> "" diff --git a/tests/ui/error-codes/E0017.stderr b/tests/ui/error-codes/E0017.stderr index bb9f718b895..285d363592f 100644 --- a/tests/ui/error-codes/E0017.stderr +++ b/tests/ui/error-codes/E0017.stderr @@ -1,5 +1,5 @@ warning: taking a mutable reference to a `const` item - --> $DIR/E0017.rs:10:30 + --> $DIR/E0017.rs:8:30 | LL | const CR: &'static mut i32 = &mut C; | ^^^^^^ @@ -7,26 +7,26 @@ LL | const CR: &'static mut i32 = &mut C; = note: each usage of a `const` item creates a new temporary = note: the mutable reference will refer to this temporary, not the original `const` item note: `const` item defined here - --> $DIR/E0017.rs:7:1 + --> $DIR/E0017.rs:5:1 | LL | const C: i32 = 2; | ^^^^^^^^^^^^ = note: `#[warn(const_item_mutation)]` on by default error[E0764]: mutable references are not allowed in the final value of constants - --> $DIR/E0017.rs:10:30 + --> $DIR/E0017.rs:8:30 | LL | const CR: &'static mut i32 = &mut C; | ^^^^^^ error[E0596]: cannot borrow immutable static item `X` as mutable - --> $DIR/E0017.rs:13:39 + --> $DIR/E0017.rs:11:39 | LL | static STATIC_REF: &'static mut i32 = &mut X; | ^^^^^^ cannot borrow as mutable warning: taking a mutable reference to a `const` item - --> $DIR/E0017.rs:15:38 + --> $DIR/E0017.rs:13:38 | LL | static CONST_REF: &'static mut i32 = &mut C; | ^^^^^^ @@ -34,13 +34,13 @@ LL | static CONST_REF: &'static mut i32 = &mut C; = note: each usage of a `const` item creates a new temporary = note: the mutable reference will refer to this temporary, not the original `const` item note: `const` item defined here - --> $DIR/E0017.rs:7:1 + --> $DIR/E0017.rs:5:1 | LL | const C: i32 = 2; | ^^^^^^^^^^^^ error[E0764]: mutable references are not allowed in the final value of statics - --> $DIR/E0017.rs:15:38 + --> $DIR/E0017.rs:13:38 | LL | static CONST_REF: &'static mut i32 = &mut C; | ^^^^^^ diff --git a/tests/ui/error-codes/E0388.rs b/tests/ui/error-codes/E0388.rs deleted file mode 100644 index bbc5f2710bf..00000000000 --- a/tests/ui/error-codes/E0388.rs +++ /dev/null @@ -1,13 +0,0 @@ -static X: i32 = 1; -const C: i32 = 2; - -const CR: &'static mut i32 = &mut C; //~ ERROR mutable references are not allowed - -//~| WARN taking a mutable -static STATIC_REF: &'static mut i32 = &mut X; //~ ERROR E0658 - -static CONST_REF: &'static mut i32 = &mut C; //~ ERROR mutable references are not allowed - -//~| WARN taking a mutable - -fn main() {} diff --git a/tests/ui/error-codes/E0388.stderr b/tests/ui/error-codes/E0388.stderr deleted file mode 100644 index cb7047072bd..00000000000 --- a/tests/ui/error-codes/E0388.stderr +++ /dev/null @@ -1,55 +0,0 @@ -warning: taking a mutable reference to a `const` item - --> $DIR/E0388.rs:4:30 - | -LL | const CR: &'static mut i32 = &mut C; - | ^^^^^^ - | - = note: each usage of a `const` item creates a new temporary - = note: the mutable reference will refer to this temporary, not the original `const` item -note: `const` item defined here - --> $DIR/E0388.rs:2:1 - | -LL | const C: i32 = 2; - | ^^^^^^^^^^^^ - = note: `#[warn(const_item_mutation)]` on by default - -error[E0764]: mutable references are not allowed in the final value of constants - --> $DIR/E0388.rs:4:30 - | -LL | const CR: &'static mut i32 = &mut C; - | ^^^^^^ - -error[E0658]: mutable references are not allowed in statics - --> $DIR/E0388.rs:7:39 - | -LL | static STATIC_REF: &'static mut i32 = &mut X; - | ^^^^^^ - | - = note: see issue #57349 for more information - = help: add `#![feature(const_mut_refs)]` to the crate attributes to enable - = note: this compiler was built on YYYY-MM-DD; consider upgrading it if it is out of date - -warning: taking a mutable reference to a `const` item - --> $DIR/E0388.rs:9:38 - | -LL | static CONST_REF: &'static mut i32 = &mut C; - | ^^^^^^ - | - = note: each usage of a `const` item creates a new temporary - = note: the mutable reference will refer to this temporary, not the original `const` item -note: `const` item defined here - --> $DIR/E0388.rs:2:1 - | -LL | const C: i32 = 2; - | ^^^^^^^^^^^^ - -error[E0764]: mutable references are not allowed in the final value of statics - --> $DIR/E0388.rs:9:38 - | -LL | static CONST_REF: &'static mut i32 = &mut C; - | ^^^^^^ - -error: aborting due to 3 previous errors; 2 warnings emitted - -Some errors have detailed explanations: E0658, E0764. -For more information about an error, try `rustc --explain E0658`. diff --git a/tests/ui/error-codes/E0396-fixed.rs b/tests/ui/error-codes/E0396-fixed.rs deleted file mode 100644 index fe20da1a8ea..00000000000 --- a/tests/ui/error-codes/E0396-fixed.rs +++ /dev/null @@ -1,9 +0,0 @@ -#![feature(const_mut_refs)] - -const REG_ADDR: *mut u8 = 0x5f3759df as *mut u8; - -const VALUE: u8 = unsafe { *REG_ADDR }; -//~^ ERROR evaluation of constant value failed - -fn main() { -} diff --git a/tests/ui/error-codes/E0396-fixed.stderr b/tests/ui/error-codes/E0396-fixed.stderr deleted file mode 100644 index c14f4948095..00000000000 --- a/tests/ui/error-codes/E0396-fixed.stderr +++ /dev/null @@ -1,9 +0,0 @@ -error[E0080]: evaluation of constant value failed - --> $DIR/E0396-fixed.rs:5:28 - | -LL | const VALUE: u8 = unsafe { *REG_ADDR }; - | ^^^^^^^^^ memory access failed: expected a pointer to 1 byte of memory, but got 0x5f3759df[noalloc] which is a dangling pointer (it has no provenance) - -error: aborting due to 1 previous error - -For more information about this error, try `rustc --explain E0080`. diff --git a/tests/ui/error-codes/E0396.rs b/tests/ui/error-codes/E0396.rs deleted file mode 100644 index 383eda3d636..00000000000 --- a/tests/ui/error-codes/E0396.rs +++ /dev/null @@ -1,20 +0,0 @@ -const REG_ADDR: *mut u8 = 0x5f3759df as *mut u8; - -const VALUE: u8 = unsafe { *REG_ADDR }; -//~^ ERROR dereferencing raw mutable pointers in constants is unstable - -const unsafe fn unreachable() -> ! { - use std::convert::Infallible; - - const INFALLIBLE: *mut Infallible = &[] as *const [Infallible] as *const _ as _; - match *INFALLIBLE {} - //~^ ERROR dereferencing raw mutable pointers in constant functions is unstable - //~| ERROR dereferencing raw mutable pointers in constant functions is unstable - - const BAD: () = unsafe { match *INFALLIBLE {} }; - //~^ ERROR dereferencing raw mutable pointers in constants is unstable - //~| ERROR dereferencing raw mutable pointers in constants is unstable -} - -fn main() { -} diff --git a/tests/ui/error-codes/E0396.stderr b/tests/ui/error-codes/E0396.stderr deleted file mode 100644 index 8bc14139d63..00000000000 --- a/tests/ui/error-codes/E0396.stderr +++ /dev/null @@ -1,55 +0,0 @@ -error[E0658]: dereferencing raw mutable pointers in constants is unstable - --> $DIR/E0396.rs:3:28 - | -LL | const VALUE: u8 = unsafe { *REG_ADDR }; - | ^^^^^^^^^ - | - = note: see issue #57349 for more information - = help: add `#![feature(const_mut_refs)]` to the crate attributes to enable - = note: this compiler was built on YYYY-MM-DD; consider upgrading it if it is out of date - -error[E0658]: dereferencing raw mutable pointers in constants is unstable - --> $DIR/E0396.rs:14:36 - | -LL | const BAD: () = unsafe { match *INFALLIBLE {} }; - | ^^^^^^^^^^^ - | - = note: see issue #57349 for more information - = help: add `#![feature(const_mut_refs)]` to the crate attributes to enable - = note: this compiler was built on YYYY-MM-DD; consider upgrading it if it is out of date - -error[E0658]: dereferencing raw mutable pointers in constants is unstable - --> $DIR/E0396.rs:14:36 - | -LL | const BAD: () = unsafe { match *INFALLIBLE {} }; - | ^^^^^^^^^^^ - | - = note: see issue #57349 for more information - = help: add `#![feature(const_mut_refs)]` 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: duplicate diagnostic emitted due to `-Z deduplicate-diagnostics=no` - -error[E0658]: dereferencing raw mutable pointers in constant functions is unstable - --> $DIR/E0396.rs:10:11 - | -LL | match *INFALLIBLE {} - | ^^^^^^^^^^^ - | - = note: see issue #57349 for more information - = help: add `#![feature(const_mut_refs)]` to the crate attributes to enable - = note: this compiler was built on YYYY-MM-DD; consider upgrading it if it is out of date - -error[E0658]: dereferencing raw mutable pointers in constant functions is unstable - --> $DIR/E0396.rs:10:11 - | -LL | match *INFALLIBLE {} - | ^^^^^^^^^^^ - | - = note: see issue #57349 for more information - = help: add `#![feature(const_mut_refs)]` 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: duplicate diagnostic emitted due to `-Z deduplicate-diagnostics=no` - -error: aborting due to 5 previous errors - -For more information about this error, try `rustc --explain E0658`. diff --git a/tests/ui/feature-gates/feature-gate-const_refs_to_cell.rs b/tests/ui/feature-gates/feature-gate-const_refs_to_cell.rs deleted file mode 100644 index bd908676c8b..00000000000 --- a/tests/ui/feature-gates/feature-gate-const_refs_to_cell.rs +++ /dev/null @@ -1,12 +0,0 @@ -//@ check-pass - -#![feature(const_refs_to_cell)] - -const FOO: () = { - let x = std::cell::Cell::new(42); - let y = &x; -}; - -fn main() { - FOO; -} diff --git a/tests/ui/impl-trait/normalize-tait-in-const.rs b/tests/ui/impl-trait/normalize-tait-in-const.rs index e3f53e5f8a8..134b202d655 100644 --- a/tests/ui/impl-trait/normalize-tait-in-const.rs +++ b/tests/ui/impl-trait/normalize-tait-in-const.rs @@ -2,7 +2,6 @@ #![feature(type_alias_impl_trait)] #![feature(const_trait_impl)] -#![feature(const_refs_to_cell)] use std::marker::Destruct; diff --git a/tests/ui/impl-trait/normalize-tait-in-const.stderr b/tests/ui/impl-trait/normalize-tait-in-const.stderr index b20dabe7b25..e0d193b5d40 100644 --- a/tests/ui/impl-trait/normalize-tait-in-const.stderr +++ b/tests/ui/impl-trait/normalize-tait-in-const.stderr @@ -1,17 +1,17 @@ error: `~const` can only be applied to `#[const_trait]` traits - --> $DIR/normalize-tait-in-const.rs:27:42 + --> $DIR/normalize-tait-in-const.rs:26:42 | LL | const fn with_positive ~const Fn(&'a Alias<'a>) + ~const Destruct>(fun: F) { | ^^^^^^^^^^^^^^^^^ error: `~const` can only be applied to `#[const_trait]` traits - --> $DIR/normalize-tait-in-const.rs:27:69 + --> $DIR/normalize-tait-in-const.rs:26:69 | LL | const fn with_positive ~const Fn(&'a Alias<'a>) + ~const Destruct>(fun: F) { | ^^^^^^^^ error[E0015]: cannot call non-const closure in constant functions - --> $DIR/normalize-tait-in-const.rs:28:5 + --> $DIR/normalize-tait-in-const.rs:27:5 | LL | fun(filter_positive()); | ^^^^^^^^^^^^^^^^^^^^^^ @@ -27,7 +27,7 @@ LL + #![feature(effects)] | error[E0493]: destructor of `F` cannot be evaluated at compile-time - --> $DIR/normalize-tait-in-const.rs:27:79 + --> $DIR/normalize-tait-in-const.rs:26:79 | LL | const fn with_positive ~const Fn(&'a Alias<'a>) + ~const Destruct>(fun: F) { | ^^^ the destructor for this type cannot be evaluated in constant functions diff --git a/tests/ui/inline-const/const-expr-lifetime-err.rs b/tests/ui/inline-const/const-expr-lifetime-err.rs index df1e5fcb473..8e8e0146728 100644 --- a/tests/ui/inline-const/const-expr-lifetime-err.rs +++ b/tests/ui/inline-const/const-expr-lifetime-err.rs @@ -1,5 +1,3 @@ -#![feature(const_mut_refs)] - use std::marker::PhantomData; #[derive(PartialEq, Eq)] diff --git a/tests/ui/inline-const/const-expr-lifetime-err.stderr b/tests/ui/inline-const/const-expr-lifetime-err.stderr index f97e2d25e6c..be3fc8d28c5 100644 --- a/tests/ui/inline-const/const-expr-lifetime-err.stderr +++ b/tests/ui/inline-const/const-expr-lifetime-err.stderr @@ -1,5 +1,5 @@ error[E0597]: `y` does not live long enough - --> $DIR/const-expr-lifetime-err.rs:22:30 + --> $DIR/const-expr-lifetime-err.rs:20:30 | LL | fn foo<'a>() { | -- lifetime `'a` defined here diff --git a/tests/ui/inline-const/const-expr-lifetime.rs b/tests/ui/inline-const/const-expr-lifetime.rs index 071e724a0fa..61c507f9791 100644 --- a/tests/ui/inline-const/const-expr-lifetime.rs +++ b/tests/ui/inline-const/const-expr-lifetime.rs @@ -1,7 +1,5 @@ //@ run-pass -#![feature(const_mut_refs)] - use std::marker::PhantomData; // rust-lang/rust#78174: ICE: "cannot convert ReErased to a region vid" diff --git a/tests/ui/inline-const/const-match-pat-lifetime-err.rs b/tests/ui/inline-const/const-match-pat-lifetime-err.rs index ff0a9dbf110..7f450ebe6fc 100644 --- a/tests/ui/inline-const/const-match-pat-lifetime-err.rs +++ b/tests/ui/inline-const/const-match-pat-lifetime-err.rs @@ -1,4 +1,3 @@ -#![feature(const_mut_refs)] #![feature(inline_const_pat)] use std::marker::PhantomData; diff --git a/tests/ui/inline-const/const-match-pat-lifetime-err.stderr b/tests/ui/inline-const/const-match-pat-lifetime-err.stderr index 98ce6cfae7b..95fe7085e50 100644 --- a/tests/ui/inline-const/const-match-pat-lifetime-err.stderr +++ b/tests/ui/inline-const/const-match-pat-lifetime-err.stderr @@ -1,5 +1,5 @@ error[E0597]: `y` does not live long enough - --> $DIR/const-match-pat-lifetime-err.rs:28:29 + --> $DIR/const-match-pat-lifetime-err.rs:27:29 | LL | fn match_invariant_ref<'a>() { | -- lifetime `'a` defined here @@ -15,7 +15,7 @@ LL | } | - `y` dropped here while still borrowed error: lifetime may not live long enough - --> $DIR/const-match-pat-lifetime-err.rs:38:12 + --> $DIR/const-match-pat-lifetime-err.rs:37:12 | LL | fn match_covariant_ref<'a>() { | -- lifetime `'a` defined here diff --git a/tests/ui/inline-const/const-match-pat-lifetime.rs b/tests/ui/inline-const/const-match-pat-lifetime.rs index 590c426c773..7f1011ea240 100644 --- a/tests/ui/inline-const/const-match-pat-lifetime.rs +++ b/tests/ui/inline-const/const-match-pat-lifetime.rs @@ -1,6 +1,5 @@ //@ run-pass -#![feature(const_mut_refs)] #![feature(inline_const_pat)] use std::marker::PhantomData; diff --git a/tests/ui/lint/lints-on-stmt-not-overridden-130142.rs b/tests/ui/lint/lints-on-stmt-not-overridden-130142.rs new file mode 100644 index 00000000000..8b514f21283 --- /dev/null +++ b/tests/ui/lint/lints-on-stmt-not-overridden-130142.rs @@ -0,0 +1,19 @@ +// Regression test for issue #130142 + +// Checks that we emit no warnings when a lint's level +// is overridden by an expect or allow attr on a Stmt node + +//@ check-pass + +#[must_use] +pub fn must_use_result() -> i32 { + 42 +} + +fn main() { + #[expect(unused_must_use)] + must_use_result(); + + #[allow(unused_must_use)] + must_use_result(); +} diff --git a/tests/ui/lint/rfc-2383-lint-reason/expect_tool_lint_rfc_2383.rs b/tests/ui/lint/rfc-2383-lint-reason/expect_tool_lint_rfc_2383.rs index c99317d6aa8..7d5a3a43ecf 100644 --- a/tests/ui/lint/rfc-2383-lint-reason/expect_tool_lint_rfc_2383.rs +++ b/tests/ui/lint/rfc-2383-lint-reason/expect_tool_lint_rfc_2383.rs @@ -37,6 +37,8 @@ mod rustc_warn { #[expect(invalid_nan_comparisons)] //~^ WARNING this lint expectation is unfulfilled [unfulfilled_lint_expectations] + //~| WARNING this lint expectation is unfulfilled [unfulfilled_lint_expectations] + //~| NOTE duplicate diagnostic emitted due to `-Z deduplicate-diagnostics=no` let _b = x == 5; } } diff --git a/tests/ui/lint/rfc-2383-lint-reason/expect_tool_lint_rfc_2383.stderr b/tests/ui/lint/rfc-2383-lint-reason/expect_tool_lint_rfc_2383.stderr index cd6dae0d761..8f25b90b031 100644 --- a/tests/ui/lint/rfc-2383-lint-reason/expect_tool_lint_rfc_2383.stderr +++ b/tests/ui/lint/rfc-2383-lint-reason/expect_tool_lint_rfc_2383.stderr @@ -12,5 +12,13 @@ warning: this lint expectation is unfulfilled LL | #[expect(invalid_nan_comparisons)] | ^^^^^^^^^^^^^^^^^^^^^^^ -warning: 2 warnings emitted +warning: this lint expectation is unfulfilled + --> $DIR/expect_tool_lint_rfc_2383.rs:38:18 + | +LL | #[expect(invalid_nan_comparisons)] + | ^^^^^^^^^^^^^^^^^^^^^^^ + | + = note: duplicate diagnostic emitted due to `-Z deduplicate-diagnostics=no` + +warning: 3 warnings emitted diff --git a/tests/ui/lint/rfc-2383-lint-reason/expect_unfulfilled_expectation.rs b/tests/ui/lint/rfc-2383-lint-reason/expect_unfulfilled_expectation.rs index 413833ba351..ee715bfd5a3 100644 --- a/tests/ui/lint/rfc-2383-lint-reason/expect_unfulfilled_expectation.rs +++ b/tests/ui/lint/rfc-2383-lint-reason/expect_unfulfilled_expectation.rs @@ -16,15 +16,22 @@ pub fn normal_test_fn() { #[expect(unused_mut, reason = "this expectation will create a diagnostic with the default lint level")] //~^ WARNING this lint expectation is unfulfilled + //~| WARNING this lint expectation is unfulfilled //~| NOTE this expectation will create a diagnostic with the default lint level + //~| NOTE this expectation will create a diagnostic with the default lint level + //~| NOTE duplicate diagnostic emitted due to `-Z deduplicate-diagnostics=no` let mut v = vec![1, 1, 2, 3, 5]; v.sort(); // Check that lint lists including `unfulfilled_lint_expectations` are also handled correctly #[expect(unused, unfulfilled_lint_expectations, reason = "the expectation for `unused` should be fulfilled")] //~^ WARNING this lint expectation is unfulfilled + //~| WARNING this lint expectation is unfulfilled + //~| NOTE the expectation for `unused` should be fulfilled //~| NOTE the expectation for `unused` should be fulfilled //~| NOTE the `unfulfilled_lint_expectations` lint can't be expected and will always produce this message + //~| NOTE the `unfulfilled_lint_expectations` lint can't be expected and will always produce this message + //~| NOTE duplicate diagnostic emitted due to `-Z deduplicate-diagnostics=no` let value = "I'm unused"; } diff --git a/tests/ui/lint/rfc-2383-lint-reason/expect_unfulfilled_expectation.stderr b/tests/ui/lint/rfc-2383-lint-reason/expect_unfulfilled_expectation.stderr index bd2df362a77..ac126804e0e 100644 --- a/tests/ui/lint/rfc-2383-lint-reason/expect_unfulfilled_expectation.stderr +++ b/tests/ui/lint/rfc-2383-lint-reason/expect_unfulfilled_expectation.stderr @@ -26,7 +26,16 @@ LL | #[expect(unused_mut, reason = "this expectation will create a diagnosti = note: this expectation will create a diagnostic with the default lint level warning: this lint expectation is unfulfilled - --> $DIR/expect_unfulfilled_expectation.rs:24:22 + --> $DIR/expect_unfulfilled_expectation.rs:17:14 + | +LL | #[expect(unused_mut, reason = "this expectation will create a diagnostic with the default lint level")] + | ^^^^^^^^^^ + | + = note: this expectation will create a diagnostic with the default lint level + = note: duplicate diagnostic emitted due to `-Z deduplicate-diagnostics=no` + +warning: this lint expectation is unfulfilled + --> $DIR/expect_unfulfilled_expectation.rs:27:22 | LL | #[expect(unused, unfulfilled_lint_expectations, reason = "the expectation for `unused` should be fulfilled")] | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ @@ -34,5 +43,15 @@ LL | #[expect(unused, unfulfilled_lint_expectations, reason = "the expectati = note: the expectation for `unused` should be fulfilled = note: the `unfulfilled_lint_expectations` lint can't be expected and will always produce this message -warning: 4 warnings emitted +warning: this lint expectation is unfulfilled + --> $DIR/expect_unfulfilled_expectation.rs:27:22 + | +LL | #[expect(unused, unfulfilled_lint_expectations, reason = "the expectation for `unused` should be fulfilled")] + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | + = note: the expectation for `unused` should be fulfilled + = note: the `unfulfilled_lint_expectations` lint can't be expected and will always produce this message + = note: duplicate diagnostic emitted due to `-Z deduplicate-diagnostics=no` + +warning: 6 warnings emitted diff --git a/tests/ui/never_type/issue-52443.rs b/tests/ui/never_type/issue-52443.rs index 0498a8a1625..dcda2b9536a 100644 --- a/tests/ui/never_type/issue-52443.rs +++ b/tests/ui/never_type/issue-52443.rs @@ -9,6 +9,5 @@ fn main() { [(); { for _ in 0usize.. {}; 0}]; //~^ ERROR `for` is not allowed in a `const` //~| ERROR cannot convert - //~| ERROR mutable references //~| ERROR cannot call } diff --git a/tests/ui/never_type/issue-52443.stderr b/tests/ui/never_type/issue-52443.stderr index 02cb9cb22a3..adcff6637b0 100644 --- a/tests/ui/never_type/issue-52443.stderr +++ b/tests/ui/never_type/issue-52443.stderr @@ -55,16 +55,6 @@ help: add `#![feature(const_trait_impl)]` to the crate attributes to enable LL + #![feature(const_trait_impl)] | -error[E0658]: mutable references are not allowed in constants - --> $DIR/issue-52443.rs:9:21 - | -LL | [(); { for _ in 0usize.. {}; 0}]; - | ^^^^^^^^ - | - = note: see issue #57349 for more information - = help: add `#![feature(const_mut_refs)]` to the crate attributes to enable - = note: this compiler was built on YYYY-MM-DD; consider upgrading it if it is out of date - error[E0015]: cannot call non-const fn ` as Iterator>::next` in constants --> $DIR/issue-52443.rs:9:21 | @@ -77,7 +67,7 @@ help: add `#![feature(const_trait_impl)]` to the crate attributes to enable LL + #![feature(const_trait_impl)] | -error: aborting due to 6 previous errors; 1 warning emitted +error: aborting due to 5 previous errors; 1 warning emitted Some errors have detailed explanations: E0015, E0308, E0658. For more information about an error, try `rustc --explain E0015`. diff --git a/tests/ui/offset-of/offset-of-tuple.rs b/tests/ui/offset-of/offset-of-tuple.rs index b0822352c9d..db00fe05583 100644 --- a/tests/ui/offset-of/offset-of-tuple.rs +++ b/tests/ui/offset-of/offset-of-tuple.rs @@ -28,6 +28,7 @@ type ComplexTup = (((u8, u8), u8), u8); fn nested() { offset_of!(((u8, u16), (u32, u16, u8)), 0.2); //~ ERROR no field `2` + offset_of!(((u8, u16), (u32, u16, u8)), 0.1e2); //~ ERROR no field `1e2` offset_of!(((u8, u16), (u32, u16, u8)), 1.2); offset_of!(((u8, u16), (u32, u16, u8)), 1.2.0); //~ ERROR no field `0` diff --git a/tests/ui/offset-of/offset-of-tuple.stderr b/tests/ui/offset-of/offset-of-tuple.stderr index e6b45c0b6b8..dd20859e04e 100644 --- a/tests/ui/offset-of/offset-of-tuple.stderr +++ b/tests/ui/offset-of/offset-of-tuple.stderr @@ -29,43 +29,43 @@ LL | { builtin # offset_of((u8, u8), 1 .) }; | ^ error: unexpected token: `)` - --> $DIR/offset-of-tuple.rs:46:45 + --> $DIR/offset-of-tuple.rs:47:45 | LL | { builtin # offset_of(ComplexTup, 0.0.1.) }; | ^ error: unexpected token: `)` - --> $DIR/offset-of-tuple.rs:47:46 + --> $DIR/offset-of-tuple.rs:48:46 | LL | { builtin # offset_of(ComplexTup, 0 .0.1.) }; | ^ error: unexpected token: `)` - --> $DIR/offset-of-tuple.rs:48:47 + --> $DIR/offset-of-tuple.rs:49:47 | LL | { builtin # offset_of(ComplexTup, 0 . 0.1.) }; | ^ error: unexpected token: `)` - --> $DIR/offset-of-tuple.rs:49:46 + --> $DIR/offset-of-tuple.rs:50:46 | LL | { builtin # offset_of(ComplexTup, 0. 0.1.) }; | ^ error: unexpected token: `)` - --> $DIR/offset-of-tuple.rs:50:46 + --> $DIR/offset-of-tuple.rs:51:46 | LL | { builtin # offset_of(ComplexTup, 0.0 .1.) }; | ^ error: unexpected token: `)` - --> $DIR/offset-of-tuple.rs:51:47 + --> $DIR/offset-of-tuple.rs:52:47 | LL | { builtin # offset_of(ComplexTup, 0.0 . 1.) }; | ^ error: unexpected token: `)` - --> $DIR/offset-of-tuple.rs:52:46 + --> $DIR/offset-of-tuple.rs:53:46 | LL | { builtin # offset_of(ComplexTup, 0.0. 1.) }; | ^ @@ -104,43 +104,43 @@ LL | offset_of!((u8, u8), 1 .); | ^ error: unexpected token: `)` - --> $DIR/offset-of-tuple.rs:35:34 + --> $DIR/offset-of-tuple.rs:36:34 | LL | offset_of!(ComplexTup, 0.0.1.); | ^ error: unexpected token: `)` - --> $DIR/offset-of-tuple.rs:36:35 + --> $DIR/offset-of-tuple.rs:37:35 | LL | offset_of!(ComplexTup, 0 .0.1.); | ^ error: unexpected token: `)` - --> $DIR/offset-of-tuple.rs:37:36 + --> $DIR/offset-of-tuple.rs:38:36 | LL | offset_of!(ComplexTup, 0 . 0.1.); | ^ error: unexpected token: `)` - --> $DIR/offset-of-tuple.rs:38:35 + --> $DIR/offset-of-tuple.rs:39:35 | LL | offset_of!(ComplexTup, 0. 0.1.); | ^ error: unexpected token: `)` - --> $DIR/offset-of-tuple.rs:39:35 + --> $DIR/offset-of-tuple.rs:40:35 | LL | offset_of!(ComplexTup, 0.0 .1.); | ^ error: unexpected token: `)` - --> $DIR/offset-of-tuple.rs:40:36 + --> $DIR/offset-of-tuple.rs:41:36 | LL | offset_of!(ComplexTup, 0.0 . 1.); | ^ error: unexpected token: `)` - --> $DIR/offset-of-tuple.rs:41:35 + --> $DIR/offset-of-tuple.rs:42:35 | LL | offset_of!(ComplexTup, 0.0. 1.); | ^ @@ -196,22 +196,21 @@ LL | builtin # offset_of((u8, u8), 1_u8); error[E0609]: no field `2` on type `(u8, u16)` --> $DIR/offset-of-tuple.rs:30:47 | -LL | offset_of!(((u8, u16), (u32, u16, u8)), 0.2); - | _____------------------------------------------^- - | | | - | | in this macro invocation -LL | | offset_of!(((u8, u16), (u32, u16, u8)), 1.2); -LL | | offset_of!(((u8, u16), (u32, u16, u8)), 1.2.0); -... | +LL | offset_of!(((u8, u16), (u32, u16, u8)), 0.2); + | ^ + +error[E0609]: no field `1e2` on type `(u8, u16)` + --> $DIR/offset-of-tuple.rs:31:47 | - = note: this error originates in the macro `offset_of` (in Nightly builds, run with -Z macro-backtrace for more info) +LL | offset_of!(((u8, u16), (u32, u16, u8)), 0.1e2); + | ^^^ error[E0609]: no field `0` on type `u8` - --> $DIR/offset-of-tuple.rs:32:49 + --> $DIR/offset-of-tuple.rs:33:49 | LL | offset_of!(((u8, u16), (u32, u16, u8)), 1.2.0); | ^ -error: aborting due to 33 previous errors +error: aborting due to 34 previous errors For more information about this error, try `rustc --explain E0609`. diff --git a/tests/ui/parser/fn-header-semantic-fail.rs b/tests/ui/parser/fn-header-semantic-fail.rs index 5907ac05260..972e52d75da 100644 --- a/tests/ui/parser/fn-header-semantic-fail.rs +++ b/tests/ui/parser/fn-header-semantic-fail.rs @@ -2,8 +2,6 @@ //@ edition:2018 -#![feature(const_extern_fn)] - fn main() { async fn ff1() {} // OK. unsafe fn ff2() {} // OK. diff --git a/tests/ui/parser/fn-header-semantic-fail.stderr b/tests/ui/parser/fn-header-semantic-fail.stderr index b519ddbe2b4..dda42f24b32 100644 --- a/tests/ui/parser/fn-header-semantic-fail.stderr +++ b/tests/ui/parser/fn-header-semantic-fail.stderr @@ -1,5 +1,5 @@ error: functions cannot be both `const` and `async` - --> $DIR/fn-header-semantic-fail.rs:12:5 + --> $DIR/fn-header-semantic-fail.rs:10:5 | LL | const async unsafe extern "C" fn ff5() {} | ^^^^^-^^^^^------------------------------ @@ -8,7 +8,7 @@ LL | const async unsafe extern "C" fn ff5() {} | `const` because of this error[E0379]: functions in traits cannot be declared const - --> $DIR/fn-header-semantic-fail.rs:18:9 + --> $DIR/fn-header-semantic-fail.rs:16:9 | LL | const fn ft3(); | ^^^^^- @@ -17,7 +17,7 @@ LL | const fn ft3(); | help: remove the `const` error[E0379]: functions in traits cannot be declared const - --> $DIR/fn-header-semantic-fail.rs:20:9 + --> $DIR/fn-header-semantic-fail.rs:18:9 | LL | const async unsafe extern "C" fn ft5(); | ^^^^^- @@ -26,7 +26,7 @@ LL | const async unsafe extern "C" fn ft5(); | help: remove the `const` error: functions cannot be both `const` and `async` - --> $DIR/fn-header-semantic-fail.rs:20:9 + --> $DIR/fn-header-semantic-fail.rs:18:9 | LL | const async unsafe extern "C" fn ft5(); | ^^^^^-^^^^^---------------------------- @@ -35,7 +35,7 @@ LL | const async unsafe extern "C" fn ft5(); | `const` because of this error[E0379]: functions in trait impls cannot be declared const - --> $DIR/fn-header-semantic-fail.rs:29:9 + --> $DIR/fn-header-semantic-fail.rs:27:9 | LL | const fn ft3() {} | ^^^^^- @@ -44,7 +44,7 @@ LL | const fn ft3() {} | help: remove the `const` error[E0379]: functions in trait impls cannot be declared const - --> $DIR/fn-header-semantic-fail.rs:31:9 + --> $DIR/fn-header-semantic-fail.rs:29:9 | LL | const async unsafe extern "C" fn ft5() {} | ^^^^^- @@ -53,7 +53,7 @@ LL | const async unsafe extern "C" fn ft5() {} | help: remove the `const` error: functions cannot be both `const` and `async` - --> $DIR/fn-header-semantic-fail.rs:31:9 + --> $DIR/fn-header-semantic-fail.rs:29:9 | LL | const async unsafe extern "C" fn ft5() {} | ^^^^^-^^^^^------------------------------ @@ -62,7 +62,7 @@ LL | const async unsafe extern "C" fn ft5() {} | `const` because of this error: functions cannot be both `const` and `async` - --> $DIR/fn-header-semantic-fail.rs:41:9 + --> $DIR/fn-header-semantic-fail.rs:39:9 | LL | const async unsafe extern "C" fn fi5() {} | ^^^^^-^^^^^------------------------------ @@ -71,7 +71,7 @@ LL | const async unsafe extern "C" fn fi5() {} | `const` because of this error: functions in `extern` blocks cannot have qualifiers - --> $DIR/fn-header-semantic-fail.rs:46:9 + --> $DIR/fn-header-semantic-fail.rs:44:9 | LL | extern "C" { | ---------- in this `extern` block @@ -79,7 +79,7 @@ LL | async fn fe1(); | ^^^^^ help: remove this qualifier error: items in unadorned `extern` blocks cannot have safety qualifiers - --> $DIR/fn-header-semantic-fail.rs:47:9 + --> $DIR/fn-header-semantic-fail.rs:45:9 | LL | unsafe fn fe2(); | ^^^^^^^^^^^^^^^^ @@ -90,7 +90,7 @@ LL | unsafe extern "C" { | ++++++ error: functions in `extern` blocks cannot have qualifiers - --> $DIR/fn-header-semantic-fail.rs:48:9 + --> $DIR/fn-header-semantic-fail.rs:46:9 | LL | extern "C" { | ---------- in this `extern` block @@ -99,7 +99,7 @@ LL | const fn fe3(); | ^^^^^ help: remove this qualifier error: functions in `extern` blocks cannot have qualifiers - --> $DIR/fn-header-semantic-fail.rs:49:9 + --> $DIR/fn-header-semantic-fail.rs:47:9 | LL | extern "C" { | ---------- in this `extern` block @@ -108,7 +108,7 @@ LL | extern "C" fn fe4(); | ^^^^^^^^^^ help: remove this qualifier error: functions in `extern` blocks cannot have qualifiers - --> $DIR/fn-header-semantic-fail.rs:50:15 + --> $DIR/fn-header-semantic-fail.rs:48:15 | LL | extern "C" { | ---------- in this `extern` block @@ -117,7 +117,7 @@ LL | const async unsafe extern "C" fn fe5(); | ^^^^^ help: remove this qualifier error: functions in `extern` blocks cannot have qualifiers - --> $DIR/fn-header-semantic-fail.rs:50:9 + --> $DIR/fn-header-semantic-fail.rs:48:9 | LL | extern "C" { | ---------- in this `extern` block @@ -126,7 +126,7 @@ LL | const async unsafe extern "C" fn fe5(); | ^^^^^ help: remove this qualifier error: functions in `extern` blocks cannot have qualifiers - --> $DIR/fn-header-semantic-fail.rs:50:28 + --> $DIR/fn-header-semantic-fail.rs:48:28 | LL | extern "C" { | ---------- in this `extern` block @@ -135,7 +135,7 @@ LL | const async unsafe extern "C" fn fe5(); | ^^^^^^^^^^ help: remove this qualifier error: items in unadorned `extern` blocks cannot have safety qualifiers - --> $DIR/fn-header-semantic-fail.rs:50:9 + --> $DIR/fn-header-semantic-fail.rs:48:9 | LL | const async unsafe extern "C" fn fe5(); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ @@ -146,7 +146,7 @@ LL | unsafe extern "C" { | ++++++ error: functions cannot be both `const` and `async` - --> $DIR/fn-header-semantic-fail.rs:50:9 + --> $DIR/fn-header-semantic-fail.rs:48:9 | LL | const async unsafe extern "C" fn fe5(); | ^^^^^-^^^^^---------------------------- diff --git a/tests/ui/pattern/usefulness/empty-match-check-notes.exhaustive_patterns.stderr b/tests/ui/pattern/usefulness/empty-match-check-notes.exhaustive_patterns.stderr index 60ab4d52c30..ec08e22e2ca 100644 --- a/tests/ui/pattern/usefulness/empty-match-check-notes.exhaustive_patterns.stderr +++ b/tests/ui/pattern/usefulness/empty-match-check-notes.exhaustive_patterns.stderr @@ -2,7 +2,10 @@ error: unreachable pattern --> $DIR/empty-match-check-notes.rs:17:9 | LL | _ => {} - | ^ matches no values because `EmptyEnum` is uninhabited + | ^------ + | | + | matches no values because `EmptyEnum` is uninhabited + | help: remove the match arm | = note: to learn more about uninhabited types, see https://doc.rust-lang.org/nomicon/exotic-sizes.html#empty-types note: the lint level is defined here @@ -15,7 +18,10 @@ error: unreachable pattern --> $DIR/empty-match-check-notes.rs:22:9 | LL | _ if false => {} - | ^ matches no values because `EmptyEnum` is uninhabited + | ^--------------- + | | + | matches no values because `EmptyEnum` is uninhabited + | help: remove the match arm | = note: to learn more about uninhabited types, see https://doc.rust-lang.org/nomicon/exotic-sizes.html#empty-types @@ -23,7 +29,10 @@ error: unreachable pattern --> $DIR/empty-match-check-notes.rs:31:9 | LL | _ => {} - | ^ matches no values because `EmptyForeignEnum` is uninhabited + | ^------ + | | + | matches no values because `EmptyForeignEnum` is uninhabited + | help: remove the match arm | = note: to learn more about uninhabited types, see https://doc.rust-lang.org/nomicon/exotic-sizes.html#empty-types @@ -31,7 +40,10 @@ error: unreachable pattern --> $DIR/empty-match-check-notes.rs:36:9 | LL | _ if false => {} - | ^ matches no values because `EmptyForeignEnum` is uninhabited + | ^--------------- + | | + | matches no values because `EmptyForeignEnum` is uninhabited + | help: remove the match arm | = note: to learn more about uninhabited types, see https://doc.rust-lang.org/nomicon/exotic-sizes.html#empty-types diff --git a/tests/ui/pattern/usefulness/empty-match-check-notes.normal.stderr b/tests/ui/pattern/usefulness/empty-match-check-notes.normal.stderr index 60ab4d52c30..ec08e22e2ca 100644 --- a/tests/ui/pattern/usefulness/empty-match-check-notes.normal.stderr +++ b/tests/ui/pattern/usefulness/empty-match-check-notes.normal.stderr @@ -2,7 +2,10 @@ error: unreachable pattern --> $DIR/empty-match-check-notes.rs:17:9 | LL | _ => {} - | ^ matches no values because `EmptyEnum` is uninhabited + | ^------ + | | + | matches no values because `EmptyEnum` is uninhabited + | help: remove the match arm | = note: to learn more about uninhabited types, see https://doc.rust-lang.org/nomicon/exotic-sizes.html#empty-types note: the lint level is defined here @@ -15,7 +18,10 @@ error: unreachable pattern --> $DIR/empty-match-check-notes.rs:22:9 | LL | _ if false => {} - | ^ matches no values because `EmptyEnum` is uninhabited + | ^--------------- + | | + | matches no values because `EmptyEnum` is uninhabited + | help: remove the match arm | = note: to learn more about uninhabited types, see https://doc.rust-lang.org/nomicon/exotic-sizes.html#empty-types @@ -23,7 +29,10 @@ error: unreachable pattern --> $DIR/empty-match-check-notes.rs:31:9 | LL | _ => {} - | ^ matches no values because `EmptyForeignEnum` is uninhabited + | ^------ + | | + | matches no values because `EmptyForeignEnum` is uninhabited + | help: remove the match arm | = note: to learn more about uninhabited types, see https://doc.rust-lang.org/nomicon/exotic-sizes.html#empty-types @@ -31,7 +40,10 @@ error: unreachable pattern --> $DIR/empty-match-check-notes.rs:36:9 | LL | _ if false => {} - | ^ matches no values because `EmptyForeignEnum` is uninhabited + | ^--------------- + | | + | matches no values because `EmptyForeignEnum` is uninhabited + | help: remove the match arm | = note: to learn more about uninhabited types, see https://doc.rust-lang.org/nomicon/exotic-sizes.html#empty-types diff --git a/tests/ui/pattern/usefulness/empty-types.exhaustive_patterns.stderr b/tests/ui/pattern/usefulness/empty-types.exhaustive_patterns.stderr index 9decddfe5de..c6e41c1875f 100644 --- a/tests/ui/pattern/usefulness/empty-types.exhaustive_patterns.stderr +++ b/tests/ui/pattern/usefulness/empty-types.exhaustive_patterns.stderr @@ -2,7 +2,10 @@ error: unreachable pattern --> $DIR/empty-types.rs:49:9 | LL | _ => {} - | ^ matches no values because `!` is uninhabited + | ^------ + | | + | matches no values because `!` is uninhabited + | help: remove the match arm | = note: to learn more about uninhabited types, see https://doc.rust-lang.org/nomicon/exotic-sizes.html#empty-types note: the lint level is defined here @@ -15,7 +18,10 @@ error: unreachable pattern --> $DIR/empty-types.rs:52:9 | LL | _x => {} - | ^^ matches no values because `!` is uninhabited + | ^^------ + | | + | matches no values because `!` is uninhabited + | help: remove the match arm | = note: to learn more about uninhabited types, see https://doc.rust-lang.org/nomicon/exotic-sizes.html#empty-types @@ -38,7 +44,10 @@ error: unreachable pattern --> $DIR/empty-types.rs:70:9 | LL | (_, _) => {} - | ^^^^^^ matches no values because `(u32, !)` is uninhabited + | ^^^^^^------ + | | + | matches no values because `(u32, !)` is uninhabited + | help: remove the match arm | = note: to learn more about uninhabited types, see https://doc.rust-lang.org/nomicon/exotic-sizes.html#empty-types @@ -46,7 +55,10 @@ error: unreachable pattern --> $DIR/empty-types.rs:76:9 | LL | _ => {} - | ^ matches no values because `(!, !)` is uninhabited + | ^------ + | | + | matches no values because `(!, !)` is uninhabited + | help: remove the match arm | = note: to learn more about uninhabited types, see https://doc.rust-lang.org/nomicon/exotic-sizes.html#empty-types @@ -54,7 +66,10 @@ error: unreachable pattern --> $DIR/empty-types.rs:79:9 | LL | (_, _) => {} - | ^^^^^^ matches no values because `(!, !)` is uninhabited + | ^^^^^^------ + | | + | matches no values because `(!, !)` is uninhabited + | help: remove the match arm | = note: to learn more about uninhabited types, see https://doc.rust-lang.org/nomicon/exotic-sizes.html#empty-types @@ -62,7 +77,10 @@ error: unreachable pattern --> $DIR/empty-types.rs:83:9 | LL | _ => {} - | ^ matches no values because `!` is uninhabited + | ^------ + | | + | matches no values because `!` is uninhabited + | help: remove the match arm | = note: to learn more about uninhabited types, see https://doc.rust-lang.org/nomicon/exotic-sizes.html#empty-types @@ -89,7 +107,10 @@ error: unreachable pattern --> $DIR/empty-types.rs:94:9 | LL | Err(_) => {} - | ^^^^^^ matches no values because `!` is uninhabited + | ^^^^^^------ + | | + | matches no values because `!` is uninhabited + | help: remove the match arm | = note: to learn more about uninhabited types, see https://doc.rust-lang.org/nomicon/exotic-sizes.html#empty-types @@ -97,7 +118,10 @@ error: unreachable pattern --> $DIR/empty-types.rs:99:9 | LL | Err(_) => {} - | ^^^^^^ matches no values because `!` is uninhabited + | ^^^^^^------ + | | + | matches no values because `!` is uninhabited + | help: remove the match arm | = note: to learn more about uninhabited types, see https://doc.rust-lang.org/nomicon/exotic-sizes.html#empty-types @@ -137,7 +161,10 @@ error: unreachable pattern --> $DIR/empty-types.rs:112:9 | LL | _ => {} - | ^ matches no values because `Result` is uninhabited + | ^------ + | | + | matches no values because `Result` is uninhabited + | help: remove the match arm | = note: to learn more about uninhabited types, see https://doc.rust-lang.org/nomicon/exotic-sizes.html#empty-types @@ -145,7 +172,10 @@ error: unreachable pattern --> $DIR/empty-types.rs:115:9 | LL | Ok(_) => {} - | ^^^^^ matches no values because `Result` is uninhabited + | ^^^^^------ + | | + | matches no values because `Result` is uninhabited + | help: remove the match arm | = note: to learn more about uninhabited types, see https://doc.rust-lang.org/nomicon/exotic-sizes.html#empty-types @@ -153,7 +183,10 @@ error: unreachable pattern --> $DIR/empty-types.rs:118:9 | LL | Ok(_) => {} - | ^^^^^ matches no values because `Result` is uninhabited + | ^^^^^------ + | | + | matches no values because `Result` is uninhabited + | help: remove the match arm | = note: to learn more about uninhabited types, see https://doc.rust-lang.org/nomicon/exotic-sizes.html#empty-types @@ -161,7 +194,10 @@ error: unreachable pattern --> $DIR/empty-types.rs:119:9 | LL | _ => {} - | ^ matches no values because `Result` is uninhabited + | ^------ + | | + | matches no values because `Result` is uninhabited + | help: remove the match arm | = note: to learn more about uninhabited types, see https://doc.rust-lang.org/nomicon/exotic-sizes.html#empty-types @@ -169,7 +205,10 @@ error: unreachable pattern --> $DIR/empty-types.rs:122:9 | LL | Ok(_) => {} - | ^^^^^ matches no values because `Result` is uninhabited + | ^^^^^------ + | | + | matches no values because `Result` is uninhabited + | help: remove the match arm | = note: to learn more about uninhabited types, see https://doc.rust-lang.org/nomicon/exotic-sizes.html#empty-types @@ -177,7 +216,10 @@ error: unreachable pattern --> $DIR/empty-types.rs:123:9 | LL | Err(_) => {} - | ^^^^^^ matches no values because `Result` is uninhabited + | ^^^^^^------ + | | + | matches no values because `Result` is uninhabited + | help: remove the match arm | = note: to learn more about uninhabited types, see https://doc.rust-lang.org/nomicon/exotic-sizes.html#empty-types @@ -185,7 +227,10 @@ error: unreachable pattern --> $DIR/empty-types.rs:132:13 | LL | _ => {} - | ^ matches no values because `Void` is uninhabited + | ^------ + | | + | matches no values because `Void` is uninhabited + | help: remove the match arm | = note: to learn more about uninhabited types, see https://doc.rust-lang.org/nomicon/exotic-sizes.html#empty-types @@ -193,7 +238,10 @@ error: unreachable pattern --> $DIR/empty-types.rs:135:13 | LL | _ if false => {} - | ^ matches no values because `Void` is uninhabited + | ^--------------- + | | + | matches no values because `Void` is uninhabited + | help: remove the match arm | = note: to learn more about uninhabited types, see https://doc.rust-lang.org/nomicon/exotic-sizes.html#empty-types @@ -201,7 +249,10 @@ error: unreachable pattern --> $DIR/empty-types.rs:143:13 | LL | Some(_) => {} - | ^^^^^^^ matches no values because `Void` is uninhabited + | ^^^^^^^------ + | | + | matches no values because `Void` is uninhabited + | help: remove the match arm | = note: to learn more about uninhabited types, see https://doc.rust-lang.org/nomicon/exotic-sizes.html#empty-types @@ -217,7 +268,10 @@ error: unreachable pattern --> $DIR/empty-types.rs:199:13 | LL | _ => {} - | ^ matches no values because `!` is uninhabited + | ^------ + | | + | matches no values because `!` is uninhabited + | help: remove the match arm | = note: to learn more about uninhabited types, see https://doc.rust-lang.org/nomicon/exotic-sizes.html#empty-types @@ -225,7 +279,10 @@ error: unreachable pattern --> $DIR/empty-types.rs:204:13 | LL | _ => {} - | ^ matches no values because `!` is uninhabited + | ^------ + | | + | matches no values because `!` is uninhabited + | help: remove the match arm | = note: to learn more about uninhabited types, see https://doc.rust-lang.org/nomicon/exotic-sizes.html#empty-types @@ -233,7 +290,10 @@ error: unreachable pattern --> $DIR/empty-types.rs:209:13 | LL | _ => {} - | ^ matches no values because `!` is uninhabited + | ^------ + | | + | matches no values because `!` is uninhabited + | help: remove the match arm | = note: to learn more about uninhabited types, see https://doc.rust-lang.org/nomicon/exotic-sizes.html#empty-types @@ -241,7 +301,10 @@ error: unreachable pattern --> $DIR/empty-types.rs:214:13 | LL | _ => {} - | ^ matches no values because `!` is uninhabited + | ^------ + | | + | matches no values because `!` is uninhabited + | help: remove the match arm | = note: to learn more about uninhabited types, see https://doc.rust-lang.org/nomicon/exotic-sizes.html#empty-types @@ -249,7 +312,10 @@ error: unreachable pattern --> $DIR/empty-types.rs:220:13 | LL | _ => {} - | ^ matches no values because `!` is uninhabited + | ^------ + | | + | matches no values because `!` is uninhabited + | help: remove the match arm | = note: to learn more about uninhabited types, see https://doc.rust-lang.org/nomicon/exotic-sizes.html#empty-types @@ -257,7 +323,10 @@ error: unreachable pattern --> $DIR/empty-types.rs:281:9 | LL | _ => {} - | ^ matches no values because `!` is uninhabited + | ^------ + | | + | matches no values because `!` is uninhabited + | help: remove the match arm | = note: to learn more about uninhabited types, see https://doc.rust-lang.org/nomicon/exotic-sizes.html#empty-types @@ -265,7 +334,10 @@ error: unreachable pattern --> $DIR/empty-types.rs:284:9 | LL | (_, _) => {} - | ^^^^^^ matches no values because `(!, !)` is uninhabited + | ^^^^^^------ + | | + | matches no values because `(!, !)` is uninhabited + | help: remove the match arm | = note: to learn more about uninhabited types, see https://doc.rust-lang.org/nomicon/exotic-sizes.html#empty-types @@ -273,7 +345,10 @@ error: unreachable pattern --> $DIR/empty-types.rs:287:9 | LL | Ok(_) => {} - | ^^^^^ matches no values because `Result` is uninhabited + | ^^^^^------ + | | + | matches no values because `Result` is uninhabited + | help: remove the match arm | = note: to learn more about uninhabited types, see https://doc.rust-lang.org/nomicon/exotic-sizes.html#empty-types @@ -281,7 +356,10 @@ error: unreachable pattern --> $DIR/empty-types.rs:288:9 | LL | Err(_) => {} - | ^^^^^^ matches no values because `Result` is uninhabited + | ^^^^^^------ + | | + | matches no values because `Result` is uninhabited + | help: remove the match arm | = note: to learn more about uninhabited types, see https://doc.rust-lang.org/nomicon/exotic-sizes.html#empty-types @@ -344,7 +422,10 @@ error: unreachable pattern --> $DIR/empty-types.rs:368:9 | LL | _ => {} - | ^ matches no values because `[!; 3]` is uninhabited + | ^------ + | | + | matches no values because `[!; 3]` is uninhabited + | help: remove the match arm | = note: to learn more about uninhabited types, see https://doc.rust-lang.org/nomicon/exotic-sizes.html#empty-types @@ -352,7 +433,10 @@ error: unreachable pattern --> $DIR/empty-types.rs:371:9 | LL | [_, _, _] => {} - | ^^^^^^^^^ matches no values because `[!; 3]` is uninhabited + | ^^^^^^^^^------ + | | + | matches no values because `[!; 3]` is uninhabited + | help: remove the match arm | = note: to learn more about uninhabited types, see https://doc.rust-lang.org/nomicon/exotic-sizes.html#empty-types @@ -360,7 +444,10 @@ error: unreachable pattern --> $DIR/empty-types.rs:374:9 | LL | [_, ..] => {} - | ^^^^^^^ matches no values because `[!; 3]` is uninhabited + | ^^^^^^^------ + | | + | matches no values because `[!; 3]` is uninhabited + | help: remove the match arm | = note: to learn more about uninhabited types, see https://doc.rust-lang.org/nomicon/exotic-sizes.html#empty-types @@ -404,7 +491,10 @@ error: unreachable pattern --> $DIR/empty-types.rs:416:9 | LL | Some(_) => {} - | ^^^^^^^ matches no values because `!` is uninhabited + | ^^^^^^^------ + | | + | matches no values because `!` is uninhabited + | help: remove the match arm | = note: to learn more about uninhabited types, see https://doc.rust-lang.org/nomicon/exotic-sizes.html#empty-types @@ -412,7 +502,10 @@ error: unreachable pattern --> $DIR/empty-types.rs:421:9 | LL | Some(_a) => {} - | ^^^^^^^^ matches no values because `!` is uninhabited + | ^^^^^^^^------ + | | + | matches no values because `!` is uninhabited + | help: remove the match arm | = note: to learn more about uninhabited types, see https://doc.rust-lang.org/nomicon/exotic-sizes.html#empty-types @@ -438,7 +531,10 @@ error: unreachable pattern --> $DIR/empty-types.rs:603:9 | LL | _ => {} - | ^ matches no values because `!` is uninhabited + | ^------ + | | + | matches no values because `!` is uninhabited + | help: remove the match arm | = note: to learn more about uninhabited types, see https://doc.rust-lang.org/nomicon/exotic-sizes.html#empty-types @@ -446,7 +542,10 @@ error: unreachable pattern --> $DIR/empty-types.rs:606:9 | LL | _x => {} - | ^^ matches no values because `!` is uninhabited + | ^^------ + | | + | matches no values because `!` is uninhabited + | help: remove the match arm | = note: to learn more about uninhabited types, see https://doc.rust-lang.org/nomicon/exotic-sizes.html#empty-types @@ -454,7 +553,10 @@ error: unreachable pattern --> $DIR/empty-types.rs:609:9 | LL | _ if false => {} - | ^ matches no values because `!` is uninhabited + | ^--------------- + | | + | matches no values because `!` is uninhabited + | help: remove the match arm | = note: to learn more about uninhabited types, see https://doc.rust-lang.org/nomicon/exotic-sizes.html#empty-types @@ -462,7 +564,10 @@ error: unreachable pattern --> $DIR/empty-types.rs:612:9 | LL | _x if false => {} - | ^^ matches no values because `!` is uninhabited + | ^^--------------- + | | + | matches no values because `!` is uninhabited + | help: remove the match arm | = note: to learn more about uninhabited types, see https://doc.rust-lang.org/nomicon/exotic-sizes.html#empty-types diff --git a/tests/ui/pattern/usefulness/empty-types.never_pats.stderr b/tests/ui/pattern/usefulness/empty-types.never_pats.stderr index fe9c4319820..3f312d46c7e 100644 --- a/tests/ui/pattern/usefulness/empty-types.never_pats.stderr +++ b/tests/ui/pattern/usefulness/empty-types.never_pats.stderr @@ -11,7 +11,10 @@ error: unreachable pattern --> $DIR/empty-types.rs:49:9 | LL | _ => {} - | ^ matches no values because `!` is uninhabited + | ^------ + | | + | matches no values because `!` is uninhabited + | help: remove the match arm | = note: to learn more about uninhabited types, see https://doc.rust-lang.org/nomicon/exotic-sizes.html#empty-types note: the lint level is defined here @@ -24,7 +27,10 @@ error: unreachable pattern --> $DIR/empty-types.rs:52:9 | LL | _x => {} - | ^^ matches no values because `!` is uninhabited + | ^^------ + | | + | matches no values because `!` is uninhabited + | help: remove the match arm | = note: to learn more about uninhabited types, see https://doc.rust-lang.org/nomicon/exotic-sizes.html#empty-types @@ -47,7 +53,10 @@ error: unreachable pattern --> $DIR/empty-types.rs:83:9 | LL | _ => {} - | ^ matches no values because `!` is uninhabited + | ^------ + | | + | matches no values because `!` is uninhabited + | help: remove the match arm | = note: to learn more about uninhabited types, see https://doc.rust-lang.org/nomicon/exotic-sizes.html#empty-types @@ -120,7 +129,10 @@ error: unreachable pattern --> $DIR/empty-types.rs:132:13 | LL | _ => {} - | ^ matches no values because `Void` is uninhabited + | ^------ + | | + | matches no values because `Void` is uninhabited + | help: remove the match arm | = note: to learn more about uninhabited types, see https://doc.rust-lang.org/nomicon/exotic-sizes.html#empty-types @@ -128,7 +140,10 @@ error: unreachable pattern --> $DIR/empty-types.rs:135:13 | LL | _ if false => {} - | ^ matches no values because `Void` is uninhabited + | ^--------------- + | | + | matches no values because `Void` is uninhabited + | help: remove the match arm | = note: to learn more about uninhabited types, see https://doc.rust-lang.org/nomicon/exotic-sizes.html#empty-types @@ -155,7 +170,10 @@ error: unreachable pattern --> $DIR/empty-types.rs:199:13 | LL | _ => {} - | ^ matches no values because `!` is uninhabited + | ^------ + | | + | matches no values because `!` is uninhabited + | help: remove the match arm | = note: to learn more about uninhabited types, see https://doc.rust-lang.org/nomicon/exotic-sizes.html#empty-types @@ -163,7 +181,10 @@ error: unreachable pattern --> $DIR/empty-types.rs:204:13 | LL | _ => {} - | ^ matches no values because `!` is uninhabited + | ^------ + | | + | matches no values because `!` is uninhabited + | help: remove the match arm | = note: to learn more about uninhabited types, see https://doc.rust-lang.org/nomicon/exotic-sizes.html#empty-types @@ -171,7 +192,10 @@ error: unreachable pattern --> $DIR/empty-types.rs:209:13 | LL | _ => {} - | ^ matches no values because `!` is uninhabited + | ^------ + | | + | matches no values because `!` is uninhabited + | help: remove the match arm | = note: to learn more about uninhabited types, see https://doc.rust-lang.org/nomicon/exotic-sizes.html#empty-types @@ -179,7 +203,10 @@ error: unreachable pattern --> $DIR/empty-types.rs:214:13 | LL | _ => {} - | ^ matches no values because `!` is uninhabited + | ^------ + | | + | matches no values because `!` is uninhabited + | help: remove the match arm | = note: to learn more about uninhabited types, see https://doc.rust-lang.org/nomicon/exotic-sizes.html#empty-types @@ -187,7 +214,10 @@ error: unreachable pattern --> $DIR/empty-types.rs:220:13 | LL | _ => {} - | ^ matches no values because `!` is uninhabited + | ^------ + | | + | matches no values because `!` is uninhabited + | help: remove the match arm | = note: to learn more about uninhabited types, see https://doc.rust-lang.org/nomicon/exotic-sizes.html#empty-types @@ -195,7 +225,10 @@ error: unreachable pattern --> $DIR/empty-types.rs:281:9 | LL | _ => {} - | ^ matches no values because `!` is uninhabited + | ^------ + | | + | matches no values because `!` is uninhabited + | help: remove the match arm | = note: to learn more about uninhabited types, see https://doc.rust-lang.org/nomicon/exotic-sizes.html#empty-types @@ -476,7 +509,10 @@ error: unreachable pattern --> $DIR/empty-types.rs:603:9 | LL | _ => {} - | ^ matches no values because `!` is uninhabited + | ^------ + | | + | matches no values because `!` is uninhabited + | help: remove the match arm | = note: to learn more about uninhabited types, see https://doc.rust-lang.org/nomicon/exotic-sizes.html#empty-types @@ -484,7 +520,10 @@ error: unreachable pattern --> $DIR/empty-types.rs:606:9 | LL | _x => {} - | ^^ matches no values because `!` is uninhabited + | ^^------ + | | + | matches no values because `!` is uninhabited + | help: remove the match arm | = note: to learn more about uninhabited types, see https://doc.rust-lang.org/nomicon/exotic-sizes.html#empty-types @@ -492,7 +531,10 @@ error: unreachable pattern --> $DIR/empty-types.rs:609:9 | LL | _ if false => {} - | ^ matches no values because `!` is uninhabited + | ^--------------- + | | + | matches no values because `!` is uninhabited + | help: remove the match arm | = note: to learn more about uninhabited types, see https://doc.rust-lang.org/nomicon/exotic-sizes.html#empty-types @@ -500,7 +542,10 @@ error: unreachable pattern --> $DIR/empty-types.rs:612:9 | LL | _x if false => {} - | ^^ matches no values because `!` is uninhabited + | ^^--------------- + | | + | matches no values because `!` is uninhabited + | help: remove the match arm | = note: to learn more about uninhabited types, see https://doc.rust-lang.org/nomicon/exotic-sizes.html#empty-types diff --git a/tests/ui/pattern/usefulness/empty-types.normal.stderr b/tests/ui/pattern/usefulness/empty-types.normal.stderr index 201b0b5c3fd..bba50dab27b 100644 --- a/tests/ui/pattern/usefulness/empty-types.normal.stderr +++ b/tests/ui/pattern/usefulness/empty-types.normal.stderr @@ -2,7 +2,10 @@ error: unreachable pattern --> $DIR/empty-types.rs:49:9 | LL | _ => {} - | ^ matches no values because `!` is uninhabited + | ^------ + | | + | matches no values because `!` is uninhabited + | help: remove the match arm | = note: to learn more about uninhabited types, see https://doc.rust-lang.org/nomicon/exotic-sizes.html#empty-types note: the lint level is defined here @@ -15,7 +18,10 @@ error: unreachable pattern --> $DIR/empty-types.rs:52:9 | LL | _x => {} - | ^^ matches no values because `!` is uninhabited + | ^^------ + | | + | matches no values because `!` is uninhabited + | help: remove the match arm | = note: to learn more about uninhabited types, see https://doc.rust-lang.org/nomicon/exotic-sizes.html#empty-types @@ -38,7 +44,10 @@ error: unreachable pattern --> $DIR/empty-types.rs:83:9 | LL | _ => {} - | ^ matches no values because `!` is uninhabited + | ^------ + | | + | matches no values because `!` is uninhabited + | help: remove the match arm | = note: to learn more about uninhabited types, see https://doc.rust-lang.org/nomicon/exotic-sizes.html#empty-types @@ -111,7 +120,10 @@ error: unreachable pattern --> $DIR/empty-types.rs:132:13 | LL | _ => {} - | ^ matches no values because `Void` is uninhabited + | ^------ + | | + | matches no values because `Void` is uninhabited + | help: remove the match arm | = note: to learn more about uninhabited types, see https://doc.rust-lang.org/nomicon/exotic-sizes.html#empty-types @@ -119,7 +131,10 @@ error: unreachable pattern --> $DIR/empty-types.rs:135:13 | LL | _ if false => {} - | ^ matches no values because `Void` is uninhabited + | ^--------------- + | | + | matches no values because `Void` is uninhabited + | help: remove the match arm | = note: to learn more about uninhabited types, see https://doc.rust-lang.org/nomicon/exotic-sizes.html#empty-types @@ -146,7 +161,10 @@ error: unreachable pattern --> $DIR/empty-types.rs:199:13 | LL | _ => {} - | ^ matches no values because `!` is uninhabited + | ^------ + | | + | matches no values because `!` is uninhabited + | help: remove the match arm | = note: to learn more about uninhabited types, see https://doc.rust-lang.org/nomicon/exotic-sizes.html#empty-types @@ -154,7 +172,10 @@ error: unreachable pattern --> $DIR/empty-types.rs:204:13 | LL | _ => {} - | ^ matches no values because `!` is uninhabited + | ^------ + | | + | matches no values because `!` is uninhabited + | help: remove the match arm | = note: to learn more about uninhabited types, see https://doc.rust-lang.org/nomicon/exotic-sizes.html#empty-types @@ -162,7 +183,10 @@ error: unreachable pattern --> $DIR/empty-types.rs:209:13 | LL | _ => {} - | ^ matches no values because `!` is uninhabited + | ^------ + | | + | matches no values because `!` is uninhabited + | help: remove the match arm | = note: to learn more about uninhabited types, see https://doc.rust-lang.org/nomicon/exotic-sizes.html#empty-types @@ -170,7 +194,10 @@ error: unreachable pattern --> $DIR/empty-types.rs:214:13 | LL | _ => {} - | ^ matches no values because `!` is uninhabited + | ^------ + | | + | matches no values because `!` is uninhabited + | help: remove the match arm | = note: to learn more about uninhabited types, see https://doc.rust-lang.org/nomicon/exotic-sizes.html#empty-types @@ -178,7 +205,10 @@ error: unreachable pattern --> $DIR/empty-types.rs:220:13 | LL | _ => {} - | ^ matches no values because `!` is uninhabited + | ^------ + | | + | matches no values because `!` is uninhabited + | help: remove the match arm | = note: to learn more about uninhabited types, see https://doc.rust-lang.org/nomicon/exotic-sizes.html#empty-types @@ -186,7 +216,10 @@ error: unreachable pattern --> $DIR/empty-types.rs:281:9 | LL | _ => {} - | ^ matches no values because `!` is uninhabited + | ^------ + | | + | matches no values because `!` is uninhabited + | help: remove the match arm | = note: to learn more about uninhabited types, see https://doc.rust-lang.org/nomicon/exotic-sizes.html#empty-types @@ -467,7 +500,10 @@ error: unreachable pattern --> $DIR/empty-types.rs:603:9 | LL | _ => {} - | ^ matches no values because `!` is uninhabited + | ^------ + | | + | matches no values because `!` is uninhabited + | help: remove the match arm | = note: to learn more about uninhabited types, see https://doc.rust-lang.org/nomicon/exotic-sizes.html#empty-types @@ -475,7 +511,10 @@ error: unreachable pattern --> $DIR/empty-types.rs:606:9 | LL | _x => {} - | ^^ matches no values because `!` is uninhabited + | ^^------ + | | + | matches no values because `!` is uninhabited + | help: remove the match arm | = note: to learn more about uninhabited types, see https://doc.rust-lang.org/nomicon/exotic-sizes.html#empty-types @@ -483,7 +522,10 @@ error: unreachable pattern --> $DIR/empty-types.rs:609:9 | LL | _ if false => {} - | ^ matches no values because `!` is uninhabited + | ^--------------- + | | + | matches no values because `!` is uninhabited + | help: remove the match arm | = note: to learn more about uninhabited types, see https://doc.rust-lang.org/nomicon/exotic-sizes.html#empty-types @@ -491,7 +533,10 @@ error: unreachable pattern --> $DIR/empty-types.rs:612:9 | LL | _x if false => {} - | ^^ matches no values because `!` is uninhabited + | ^^--------------- + | | + | matches no values because `!` is uninhabited + | help: remove the match arm | = note: to learn more about uninhabited types, see https://doc.rust-lang.org/nomicon/exotic-sizes.html#empty-types diff --git a/tests/ui/pattern/usefulness/explain-unreachable-pats.stderr b/tests/ui/pattern/usefulness/explain-unreachable-pats.stderr index 67f83a85175..8651be2055f 100644 --- a/tests/ui/pattern/usefulness/explain-unreachable-pats.stderr +++ b/tests/ui/pattern/usefulness/explain-unreachable-pats.stderr @@ -59,7 +59,10 @@ error: unreachable pattern --> $DIR/explain-unreachable-pats.rs:52:9 | LL | Err(_) => {} - | ^^^^^^ matches no values because `!` is uninhabited + | ^^^^^^------ + | | + | matches no values because `!` is uninhabited + | help: remove the match arm | = note: to learn more about uninhabited types, see https://doc.rust-lang.org/nomicon/exotic-sizes.html#empty-types @@ -67,7 +70,10 @@ error: unreachable pattern --> $DIR/explain-unreachable-pats.rs:66:9 | LL | (Err(_), Err(_)) => {} - | ^^^^^^^^^^^^^^^^ matches no values because `Void2` is uninhabited + | ^^^^^^^^^^^^^^^^------ + | | + | matches no values because `Void2` is uninhabited + | help: remove the match arm | = note: to learn more about uninhabited types, see https://doc.rust-lang.org/nomicon/exotic-sizes.html#empty-types @@ -75,7 +81,10 @@ error: unreachable pattern --> $DIR/explain-unreachable-pats.rs:73:9 | LL | (Err(_), Err(_)) => {} - | ^^^^^^^^^^^^^^^^ matches no values because `Void1` is uninhabited + | ^^^^^^^^^^^^^^^^------ + | | + | matches no values because `Void1` is uninhabited + | help: remove the match arm | = note: to learn more about uninhabited types, see https://doc.rust-lang.org/nomicon/exotic-sizes.html#empty-types diff --git a/tests/ui/pattern/usefulness/impl-trait.stderr b/tests/ui/pattern/usefulness/impl-trait.stderr index f2945fca82b..75cba4b5f02 100644 --- a/tests/ui/pattern/usefulness/impl-trait.stderr +++ b/tests/ui/pattern/usefulness/impl-trait.stderr @@ -2,7 +2,10 @@ error: unreachable pattern --> $DIR/impl-trait.rs:17:13 | LL | _ => {} - | ^ matches no values because `Void` is uninhabited + | ^------ + | | + | matches no values because `Void` is uninhabited + | help: remove the match arm | = note: to learn more about uninhabited types, see https://doc.rust-lang.org/nomicon/exotic-sizes.html#empty-types note: the lint level is defined here @@ -15,7 +18,10 @@ error: unreachable pattern --> $DIR/impl-trait.rs:31:13 | LL | _ => {} - | ^ matches no values because `Void` is uninhabited + | ^------ + | | + | matches no values because `Void` is uninhabited + | help: remove the match arm | = note: to learn more about uninhabited types, see https://doc.rust-lang.org/nomicon/exotic-sizes.html#empty-types @@ -23,7 +29,10 @@ error: unreachable pattern --> $DIR/impl-trait.rs:45:13 | LL | Some(_) => {} - | ^^^^^^^ matches no values because `Void` is uninhabited + | ^^^^^^^------ + | | + | matches no values because `Void` is uninhabited + | help: remove the match arm | = note: to learn more about uninhabited types, see https://doc.rust-lang.org/nomicon/exotic-sizes.html#empty-types @@ -39,7 +48,10 @@ error: unreachable pattern --> $DIR/impl-trait.rs:59:13 | LL | Some(_) => {} - | ^^^^^^^ matches no values because `Void` is uninhabited + | ^^^^^^^------ + | | + | matches no values because `Void` is uninhabited + | help: remove the match arm | = note: to learn more about uninhabited types, see https://doc.rust-lang.org/nomicon/exotic-sizes.html#empty-types @@ -55,7 +67,10 @@ error: unreachable pattern --> $DIR/impl-trait.rs:76:9 | LL | _ => {} - | ^ matches no values because `Void` is uninhabited + | ^------ + | | + | matches no values because `Void` is uninhabited + | help: remove the match arm | = note: to learn more about uninhabited types, see https://doc.rust-lang.org/nomicon/exotic-sizes.html#empty-types @@ -71,7 +86,10 @@ error: unreachable pattern --> $DIR/impl-trait.rs:94:13 | LL | _ => {} - | ^ matches no values because `Void` is uninhabited + | ^------ + | | + | matches no values because `Void` is uninhabited + | help: remove the match arm | = note: to learn more about uninhabited types, see https://doc.rust-lang.org/nomicon/exotic-sizes.html#empty-types @@ -95,7 +113,10 @@ error: unreachable pattern --> $DIR/impl-trait.rs:138:13 | LL | _ => {} - | ^ matches no values because `SecretelyVoid` is uninhabited + | ^------ + | | + | matches no values because `SecretelyVoid` is uninhabited + | help: remove the match arm | = note: to learn more about uninhabited types, see https://doc.rust-lang.org/nomicon/exotic-sizes.html#empty-types @@ -103,7 +124,10 @@ error: unreachable pattern --> $DIR/impl-trait.rs:151:13 | LL | _ => {} - | ^ matches no values because `SecretelyDoubleVoid` is uninhabited + | ^------ + | | + | matches no values because `SecretelyDoubleVoid` is uninhabited + | help: remove the match arm | = note: to learn more about uninhabited types, see https://doc.rust-lang.org/nomicon/exotic-sizes.html#empty-types diff --git a/tests/ui/pattern/usefulness/rustfix-unreachable-pattern.fixed b/tests/ui/pattern/usefulness/rustfix-unreachable-pattern.fixed new file mode 100644 index 00000000000..18e3aecbd0d --- /dev/null +++ b/tests/ui/pattern/usefulness/rustfix-unreachable-pattern.fixed @@ -0,0 +1,23 @@ +//@ run-rustfix +#![feature(never_patterns)] +#![feature(exhaustive_patterns)] +#![allow(incomplete_features)] +#![deny(unreachable_patterns)] + +enum Void {} + +#[rustfmt::skip] +fn main() { + let res: Result<(), Void> = Ok(()); + match res { + Ok(_) => {} + //~ ERROR unreachable + //~ ERROR unreachable + } + + match res { + Ok(_x) => {} + //~ ERROR unreachable + //~ ERROR unreachable + } +} diff --git a/tests/ui/pattern/usefulness/rustfix-unreachable-pattern.rs b/tests/ui/pattern/usefulness/rustfix-unreachable-pattern.rs new file mode 100644 index 00000000000..a81420d1496 --- /dev/null +++ b/tests/ui/pattern/usefulness/rustfix-unreachable-pattern.rs @@ -0,0 +1,23 @@ +//@ run-rustfix +#![feature(never_patterns)] +#![feature(exhaustive_patterns)] +#![allow(incomplete_features)] +#![deny(unreachable_patterns)] + +enum Void {} + +#[rustfmt::skip] +fn main() { + let res: Result<(), Void> = Ok(()); + match res { + Ok(_) => {} + Err(_) => {} //~ ERROR unreachable + Err(_) => {}, //~ ERROR unreachable + } + + match res { + Ok(_x) => {} + Err(!), //~ ERROR unreachable + Err(!) //~ ERROR unreachable + } +} diff --git a/tests/ui/pattern/usefulness/rustfix-unreachable-pattern.stderr b/tests/ui/pattern/usefulness/rustfix-unreachable-pattern.stderr new file mode 100644 index 00000000000..bb246cea0a0 --- /dev/null +++ b/tests/ui/pattern/usefulness/rustfix-unreachable-pattern.stderr @@ -0,0 +1,51 @@ +error: unreachable pattern + --> $DIR/rustfix-unreachable-pattern.rs:14:9 + | +LL | Err(_) => {} + | ^^^^^^------ + | | + | matches no values because `Void` is uninhabited + | help: remove the match arm + | + = note: to learn more about uninhabited types, see https://doc.rust-lang.org/nomicon/exotic-sizes.html#empty-types +note: the lint level is defined here + --> $DIR/rustfix-unreachable-pattern.rs:5:9 + | +LL | #![deny(unreachable_patterns)] + | ^^^^^^^^^^^^^^^^^^^^ + +error: unreachable pattern + --> $DIR/rustfix-unreachable-pattern.rs:15:9 + | +LL | Err(_) => {}, + | ^^^^^^------- + | | + | matches no values because `Void` is uninhabited + | help: remove the match arm + | + = note: to learn more about uninhabited types, see https://doc.rust-lang.org/nomicon/exotic-sizes.html#empty-types + +error: unreachable pattern + --> $DIR/rustfix-unreachable-pattern.rs:20:9 + | +LL | Err(!), + | ^^^^^^- + | | + | matches no values because `Void` is uninhabited + | help: remove the match arm + | + = note: to learn more about uninhabited types, see https://doc.rust-lang.org/nomicon/exotic-sizes.html#empty-types + +error: unreachable pattern + --> $DIR/rustfix-unreachable-pattern.rs:21:9 + | +LL | Err(!) + | ^^^^^^ + | | + | matches no values because `Void` is uninhabited + | help: remove the match arm + | + = note: to learn more about uninhabited types, see https://doc.rust-lang.org/nomicon/exotic-sizes.html#empty-types + +error: aborting due to 4 previous errors + diff --git a/tests/ui/privacy/suggest-box-new.stderr b/tests/ui/privacy/suggest-box-new.stderr index 8b01e8c3c10..1e28b9fbd86 100644 --- a/tests/ui/privacy/suggest-box-new.stderr +++ b/tests/ui/privacy/suggest-box-new.stderr @@ -44,7 +44,7 @@ LL | wtf: Some(Box::new_zeroed()), | ~~~~~~~~~~~~~~ LL | wtf: Some(Box::new_in(_, _)), | ~~~~~~~~~~~~~~ - and 10 other candidates + and 12 other candidates help: consider using the `Default` trait | LL | wtf: Some(::default()), @@ -89,7 +89,7 @@ LL | let _ = Box::new_zeroed(); | ~~~~~~~~~~~~~~ LL | let _ = Box::new_in(_, _); | ~~~~~~~~~~~~~~ - and 10 other candidates + and 12 other candidates help: consider using the `Default` trait | LL | let _ = ::default(); diff --git a/tests/ui/reachable/unreachable-try-pattern.stderr b/tests/ui/reachable/unreachable-try-pattern.stderr index b082bc11603..40b11613105 100644 --- a/tests/ui/reachable/unreachable-try-pattern.stderr +++ b/tests/ui/reachable/unreachable-try-pattern.stderr @@ -17,7 +17,10 @@ warning: unreachable pattern --> $DIR/unreachable-try-pattern.rs:19:24 | LL | let y = (match x { Ok(n) => Ok(n as u32), Err(e) => Err(e) })?; - | ^^^^^ matches no values because `!` is uninhabited + | ^^^^^----------------- + | | + | matches no values because `!` is uninhabited + | help: remove the match arm | = note: to learn more about uninhabited types, see https://doc.rust-lang.org/nomicon/exotic-sizes.html#empty-types note: the lint level is defined here @@ -30,7 +33,10 @@ warning: unreachable pattern --> $DIR/unreachable-try-pattern.rs:30:40 | LL | let y = (match x { Ok(n) => Ok(n), Err(e) => Err(e) })?; - | ^^^^^^ matches no values because `Void` is uninhabited + | ^^^^^^---------- + | | + | matches no values because `Void` is uninhabited + | help: remove the match arm | = note: to learn more about uninhabited types, see https://doc.rust-lang.org/nomicon/exotic-sizes.html#empty-types diff --git a/tests/ui/rfcs/rfc-0000-never_patterns/unreachable.stderr b/tests/ui/rfcs/rfc-0000-never_patterns/unreachable.stderr index 90874760a56..0c9552bb950 100644 --- a/tests/ui/rfcs/rfc-0000-never_patterns/unreachable.stderr +++ b/tests/ui/rfcs/rfc-0000-never_patterns/unreachable.stderr @@ -2,7 +2,10 @@ error: unreachable pattern --> $DIR/unreachable.rs:15:9 | LL | Err(!), - | ^^^^^^ matches no values because `Void` is uninhabited + | ^^^^^^- + | | + | matches no values because `Void` is uninhabited + | help: remove the match arm | = note: to learn more about uninhabited types, see https://doc.rust-lang.org/nomicon/exotic-sizes.html#empty-types note: the lint level is defined here diff --git a/tests/ui/rfcs/rfc-2008-non-exhaustive/enum_same_crate_empty_match.stderr b/tests/ui/rfcs/rfc-2008-non-exhaustive/enum_same_crate_empty_match.stderr index dfd7f9d6300..45a0ca01a56 100644 --- a/tests/ui/rfcs/rfc-2008-non-exhaustive/enum_same_crate_empty_match.stderr +++ b/tests/ui/rfcs/rfc-2008-non-exhaustive/enum_same_crate_empty_match.stderr @@ -2,7 +2,10 @@ error: unreachable pattern --> $DIR/enum_same_crate_empty_match.rs:28:9 | LL | _ => {} - | ^ matches no values because `EmptyNonExhaustiveEnum` is uninhabited + | ^------ + | | + | matches no values because `EmptyNonExhaustiveEnum` is uninhabited + | help: remove the match arm | = note: to learn more about uninhabited types, see https://doc.rust-lang.org/nomicon/exotic-sizes.html#empty-types note: the lint level is defined here diff --git a/tests/ui/rfcs/rfc-2008-non-exhaustive/uninhabited/patterns.stderr b/tests/ui/rfcs/rfc-2008-non-exhaustive/uninhabited/patterns.stderr index 83300049ea9..1bb07fd0671 100644 --- a/tests/ui/rfcs/rfc-2008-non-exhaustive/uninhabited/patterns.stderr +++ b/tests/ui/rfcs/rfc-2008-non-exhaustive/uninhabited/patterns.stderr @@ -2,7 +2,10 @@ error: unreachable pattern --> $DIR/patterns.rs:42:9 | LL | Some(_x) => (), - | ^^^^^^^^ matches no values because `UninhabitedVariants` is uninhabited + | ^^^^^^^^------- + | | + | matches no values because `UninhabitedVariants` is uninhabited + | help: remove the match arm | = note: to learn more about uninhabited types, see https://doc.rust-lang.org/nomicon/exotic-sizes.html#empty-types note: the lint level is defined here diff --git a/tests/ui/rfcs/rfc-2008-non-exhaustive/uninhabited/patterns_same_crate.stderr b/tests/ui/rfcs/rfc-2008-non-exhaustive/uninhabited/patterns_same_crate.stderr index 4b107b03645..bd70a7b4091 100644 --- a/tests/ui/rfcs/rfc-2008-non-exhaustive/uninhabited/patterns_same_crate.stderr +++ b/tests/ui/rfcs/rfc-2008-non-exhaustive/uninhabited/patterns_same_crate.stderr @@ -2,7 +2,10 @@ error: unreachable pattern --> $DIR/patterns_same_crate.rs:53:9 | LL | Some(_x) => (), - | ^^^^^^^^ matches no values because `UninhabitedEnum` is uninhabited + | ^^^^^^^^------- + | | + | matches no values because `UninhabitedEnum` is uninhabited + | help: remove the match arm | = note: to learn more about uninhabited types, see https://doc.rust-lang.org/nomicon/exotic-sizes.html#empty-types note: the lint level is defined here @@ -15,7 +18,10 @@ error: unreachable pattern --> $DIR/patterns_same_crate.rs:58:9 | LL | Some(_x) => (), - | ^^^^^^^^ matches no values because `UninhabitedVariants` is uninhabited + | ^^^^^^^^------- + | | + | matches no values because `UninhabitedVariants` is uninhabited + | help: remove the match arm | = note: to learn more about uninhabited types, see https://doc.rust-lang.org/nomicon/exotic-sizes.html#empty-types diff --git a/tests/ui/rfcs/rfc-2632-const-trait-impl/const-drop-fail-2.rs b/tests/ui/rfcs/rfc-2632-const-trait-impl/const-drop-fail-2.rs index cd5fa609947..7b57e0405af 100644 --- a/tests/ui/rfcs/rfc-2632-const-trait-impl/const-drop-fail-2.rs +++ b/tests/ui/rfcs/rfc-2632-const-trait-impl/const-drop-fail-2.rs @@ -1,6 +1,5 @@ //@ known-bug: #110395 #![feature(const_trait_impl)] -#![feature(const_mut_refs)] // #![cfg_attr(precise, feature(const_precise_live_drops))] use std::marker::{Destruct, PhantomData}; diff --git a/tests/ui/rfcs/rfc-2632-const-trait-impl/const-drop-fail-2.stderr b/tests/ui/rfcs/rfc-2632-const-trait-impl/const-drop-fail-2.stderr index 1d56d015dfc..faf24c6d911 100644 --- a/tests/ui/rfcs/rfc-2632-const-trait-impl/const-drop-fail-2.stderr +++ b/tests/ui/rfcs/rfc-2632-const-trait-impl/const-drop-fail-2.stderr @@ -1,5 +1,5 @@ error: const `impl` for trait `Drop` which is not marked with `#[const_trait]` - --> $DIR/const-drop-fail-2.rs:40:25 + --> $DIR/const-drop-fail-2.rs:39:25 | LL | impl const Drop for ConstDropImplWithNonConstBounds { | ^^^^ @@ -8,13 +8,13 @@ LL | impl const Drop for ConstDropImplWithNonConstBounds { = note: adding a non-const method body in the future would be a breaking change error: `~const` can only be applied to `#[const_trait]` traits - --> $DIR/const-drop-fail-2.rs:21:26 + --> $DIR/const-drop-fail-2.rs:20:26 | LL | const fn check(_: T) {} | ^^^^^^^^ error[E0493]: destructor of `T` cannot be evaluated at compile-time - --> $DIR/const-drop-fail-2.rs:21:36 + --> $DIR/const-drop-fail-2.rs:20:36 | LL | const fn check(_: T) {} | ^ - value is dropped here @@ -22,7 +22,7 @@ LL | const fn check(_: T) {} | the destructor for this type cannot be evaluated in constant functions error[E0015]: cannot call non-const fn `::a` in constant functions - --> $DIR/const-drop-fail-2.rs:42:9 + --> $DIR/const-drop-fail-2.rs:41:9 | LL | T::a(); | ^^^^^^ diff --git a/tests/ui/rfcs/rfc-2632-const-trait-impl/const-drop-fail.precise.stderr b/tests/ui/rfcs/rfc-2632-const-trait-impl/const-drop-fail.precise.stderr index b251d84a967..3d400bf0158 100644 --- a/tests/ui/rfcs/rfc-2632-const-trait-impl/const-drop-fail.precise.stderr +++ b/tests/ui/rfcs/rfc-2632-const-trait-impl/const-drop-fail.precise.stderr @@ -1,5 +1,5 @@ error: const `impl` for trait `Drop` which is not marked with `#[const_trait]` - --> $DIR/const-drop-fail.rs:20:12 + --> $DIR/const-drop-fail.rs:19:12 | LL | impl const Drop for ConstImplWithDropGlue { | ^^^^ @@ -8,13 +8,13 @@ LL | impl const Drop for ConstImplWithDropGlue { = note: adding a non-const method body in the future would be a breaking change error: `~const` can only be applied to `#[const_trait]` traits - --> $DIR/const-drop-fail.rs:24:26 + --> $DIR/const-drop-fail.rs:23:26 | LL | const fn check(_: T) {} | ^^^^^^^^ error[E0493]: destructor of `T` cannot be evaluated at compile-time - --> $DIR/const-drop-fail.rs:24:36 + --> $DIR/const-drop-fail.rs:23:36 | LL | const fn check(_: T) {} | ^ the destructor for this type cannot be evaluated in constant functions @@ -27,12 +27,12 @@ error[E0080]: evaluation of constant value failed note: inside `std::ptr::drop_in_place:: - shim(Some(NonTrivialDrop))` --> $SRC_DIR/core/src/ptr/mod.rs:LL:COL note: inside `check::` - --> $DIR/const-drop-fail.rs:24:43 + --> $DIR/const-drop-fail.rs:23:43 | LL | const fn check(_: T) {} | ^ note: inside `_` - --> $DIR/const-drop-fail.rs:28:23 + --> $DIR/const-drop-fail.rs:27:23 | LL | const _: () = check($exp); | ^^^^^^^^^^^ @@ -54,12 +54,12 @@ note: inside `std::ptr::drop_in_place:: - shim(Some(NonTrivialDr note: inside `std::ptr::drop_in_place:: - shim(Some(ConstImplWithDropGlue))` --> $SRC_DIR/core/src/ptr/mod.rs:LL:COL note: inside `check::` - --> $DIR/const-drop-fail.rs:24:43 + --> $DIR/const-drop-fail.rs:23:43 | LL | const fn check(_: T) {} | ^ note: inside `_` - --> $DIR/const-drop-fail.rs:28:23 + --> $DIR/const-drop-fail.rs:27:23 | LL | const _: () = check($exp); | ^^^^^^^^^^^ diff --git a/tests/ui/rfcs/rfc-2632-const-trait-impl/const-drop-fail.rs b/tests/ui/rfcs/rfc-2632-const-trait-impl/const-drop-fail.rs index a9640816b89..5a98c32e838 100644 --- a/tests/ui/rfcs/rfc-2632-const-trait-impl/const-drop-fail.rs +++ b/tests/ui/rfcs/rfc-2632-const-trait-impl/const-drop-fail.rs @@ -2,7 +2,6 @@ //@ revisions: stock precise #![feature(const_trait_impl)] -#![feature(const_mut_refs)] #![cfg_attr(precise, feature(const_precise_live_drops))] use std::marker::{Destruct, PhantomData}; diff --git a/tests/ui/rfcs/rfc-2632-const-trait-impl/const-drop-fail.stock.stderr b/tests/ui/rfcs/rfc-2632-const-trait-impl/const-drop-fail.stock.stderr index 912700f2a83..fd0f6d02684 100644 --- a/tests/ui/rfcs/rfc-2632-const-trait-impl/const-drop-fail.stock.stderr +++ b/tests/ui/rfcs/rfc-2632-const-trait-impl/const-drop-fail.stock.stderr @@ -1,5 +1,5 @@ error: const `impl` for trait `Drop` which is not marked with `#[const_trait]` - --> $DIR/const-drop-fail.rs:20:12 + --> $DIR/const-drop-fail.rs:19:12 | LL | impl const Drop for ConstImplWithDropGlue { | ^^^^ @@ -8,13 +8,13 @@ LL | impl const Drop for ConstImplWithDropGlue { = note: adding a non-const method body in the future would be a breaking change error: `~const` can only be applied to `#[const_trait]` traits - --> $DIR/const-drop-fail.rs:24:26 + --> $DIR/const-drop-fail.rs:23:26 | LL | const fn check(_: T) {} | ^^^^^^^^ error[E0493]: destructor of `T` cannot be evaluated at compile-time - --> $DIR/const-drop-fail.rs:24:36 + --> $DIR/const-drop-fail.rs:23:36 | LL | const fn check(_: T) {} | ^ - value is dropped here diff --git a/tests/ui/rfcs/rfc-2632-const-trait-impl/const-drop.precise.stderr b/tests/ui/rfcs/rfc-2632-const-trait-impl/const-drop.precise.stderr index b451555ec3c..dd3ea5d241d 100644 --- a/tests/ui/rfcs/rfc-2632-const-trait-impl/const-drop.precise.stderr +++ b/tests/ui/rfcs/rfc-2632-const-trait-impl/const-drop.precise.stderr @@ -1,5 +1,5 @@ error: const `impl` for trait `Drop` which is not marked with `#[const_trait]` - --> $DIR/const-drop.rs:13:16 + --> $DIR/const-drop.rs:12:16 | LL | impl<'a> const Drop for S<'a> { | ^^^^ @@ -8,7 +8,7 @@ LL | impl<'a> const Drop for S<'a> { = note: adding a non-const method body in the future would be a breaking change error: const `impl` for trait `Drop` which is not marked with `#[const_trait]` - --> $DIR/const-drop.rs:47:16 + --> $DIR/const-drop.rs:46:16 | LL | impl const Drop for ConstDrop { | ^^^^ @@ -17,7 +17,7 @@ LL | impl const Drop for ConstDrop { = note: adding a non-const method body in the future would be a breaking change error: const `impl` for trait `Drop` which is not marked with `#[const_trait]` - --> $DIR/const-drop.rs:68:37 + --> $DIR/const-drop.rs:67:37 | LL | impl const Drop for ConstDropWithBound { | ^^^^ @@ -26,7 +26,7 @@ LL | impl const Drop for ConstDropWithBound { = note: adding a non-const method body in the future would be a breaking change error: const `impl` for trait `Drop` which is not marked with `#[const_trait]` - --> $DIR/const-drop.rs:76:30 + --> $DIR/const-drop.rs:75:30 | LL | impl const Drop for ConstDropWithNonconstBound { | ^^^^ @@ -35,13 +35,13 @@ LL | impl const Drop for ConstDropWithNonconstBound { = note: adding a non-const method body in the future would be a breaking change error: `~const` can only be applied to `#[const_trait]` traits - --> $DIR/const-drop.rs:19:22 + --> $DIR/const-drop.rs:18:22 | LL | const fn a(_: T) {} | ^^^^^^^^ error[E0049]: associated function `foo` has 1 const parameter but its trait declaration has 0 const parameters - --> $DIR/const-drop.rs:54:5 + --> $DIR/const-drop.rs:53:5 | LL | #[const_trait] | ^^^^^^^^^^^^^^ found 1 const parameter @@ -50,7 +50,7 @@ LL | fn foo(); | - expected 0 const parameters error[E0049]: associated function `foo` has 1 const parameter but its trait declaration has 0 const parameters - --> $DIR/const-drop.rs:54:5 + --> $DIR/const-drop.rs:53:5 | LL | #[const_trait] | ^^^^^^^^^^^^^^ found 1 const parameter @@ -61,13 +61,13 @@ LL | fn foo(); = note: duplicate diagnostic emitted due to `-Z deduplicate-diagnostics=no` error[E0493]: destructor of `T` cannot be evaluated at compile-time - --> $DIR/const-drop.rs:19:32 + --> $DIR/const-drop.rs:18:32 | LL | const fn a(_: T) {} | ^ the destructor for this type cannot be evaluated in constant functions error[E0015]: cannot call non-const fn `::foo` in constant functions - --> $DIR/const-drop.rs:70:13 + --> $DIR/const-drop.rs:69:13 | LL | T::foo(); | ^^^^^^^^ diff --git a/tests/ui/rfcs/rfc-2632-const-trait-impl/const-drop.rs b/tests/ui/rfcs/rfc-2632-const-trait-impl/const-drop.rs index 4ab1704a9fb..5bd81fb3ab6 100644 --- a/tests/ui/rfcs/rfc-2632-const-trait-impl/const-drop.rs +++ b/tests/ui/rfcs/rfc-2632-const-trait-impl/const-drop.rs @@ -2,7 +2,6 @@ //@ known-bug: #110395 //@ revisions: stock precise #![feature(const_trait_impl)] -#![feature(const_mut_refs)] #![feature(never_type)] #![cfg_attr(precise, feature(const_precise_live_drops))] diff --git a/tests/ui/rfcs/rfc-2632-const-trait-impl/const-drop.stock.stderr b/tests/ui/rfcs/rfc-2632-const-trait-impl/const-drop.stock.stderr index 296614f7fd0..aa59e1c8dc4 100644 --- a/tests/ui/rfcs/rfc-2632-const-trait-impl/const-drop.stock.stderr +++ b/tests/ui/rfcs/rfc-2632-const-trait-impl/const-drop.stock.stderr @@ -1,5 +1,5 @@ error: const `impl` for trait `Drop` which is not marked with `#[const_trait]` - --> $DIR/const-drop.rs:13:16 + --> $DIR/const-drop.rs:12:16 | LL | impl<'a> const Drop for S<'a> { | ^^^^ @@ -8,7 +8,7 @@ LL | impl<'a> const Drop for S<'a> { = note: adding a non-const method body in the future would be a breaking change error: const `impl` for trait `Drop` which is not marked with `#[const_trait]` - --> $DIR/const-drop.rs:47:16 + --> $DIR/const-drop.rs:46:16 | LL | impl const Drop for ConstDrop { | ^^^^ @@ -17,7 +17,7 @@ LL | impl const Drop for ConstDrop { = note: adding a non-const method body in the future would be a breaking change error: const `impl` for trait `Drop` which is not marked with `#[const_trait]` - --> $DIR/const-drop.rs:68:37 + --> $DIR/const-drop.rs:67:37 | LL | impl const Drop for ConstDropWithBound { | ^^^^ @@ -26,7 +26,7 @@ LL | impl const Drop for ConstDropWithBound { = note: adding a non-const method body in the future would be a breaking change error: const `impl` for trait `Drop` which is not marked with `#[const_trait]` - --> $DIR/const-drop.rs:76:30 + --> $DIR/const-drop.rs:75:30 | LL | impl const Drop for ConstDropWithNonconstBound { | ^^^^ @@ -35,13 +35,13 @@ LL | impl const Drop for ConstDropWithNonconstBound { = note: adding a non-const method body in the future would be a breaking change error: `~const` can only be applied to `#[const_trait]` traits - --> $DIR/const-drop.rs:19:22 + --> $DIR/const-drop.rs:18:22 | LL | const fn a(_: T) {} | ^^^^^^^^ error[E0049]: associated function `foo` has 1 const parameter but its trait declaration has 0 const parameters - --> $DIR/const-drop.rs:54:5 + --> $DIR/const-drop.rs:53:5 | LL | #[const_trait] | ^^^^^^^^^^^^^^ found 1 const parameter @@ -50,7 +50,7 @@ LL | fn foo(); | - expected 0 const parameters error[E0049]: associated function `foo` has 1 const parameter but its trait declaration has 0 const parameters - --> $DIR/const-drop.rs:54:5 + --> $DIR/const-drop.rs:53:5 | LL | #[const_trait] | ^^^^^^^^^^^^^^ found 1 const parameter @@ -61,7 +61,7 @@ LL | fn foo(); = note: duplicate diagnostic emitted due to `-Z deduplicate-diagnostics=no` error[E0493]: destructor of `T` cannot be evaluated at compile-time - --> $DIR/const-drop.rs:19:32 + --> $DIR/const-drop.rs:18:32 | LL | const fn a(_: T) {} | ^ - value is dropped here @@ -69,7 +69,7 @@ LL | const fn a(_: T) {} | the destructor for this type cannot be evaluated in constant functions error[E0015]: cannot call non-const fn `::foo` in constant functions - --> $DIR/const-drop.rs:70:13 + --> $DIR/const-drop.rs:69:13 | LL | T::foo(); | ^^^^^^^^ diff --git a/tests/ui/rfcs/rfc-2632-const-trait-impl/effects/minicore.rs b/tests/ui/rfcs/rfc-2632-const-trait-impl/effects/minicore.rs index 3c6d4757fea..1c3c66bc3ce 100644 --- a/tests/ui/rfcs/rfc-2632-const-trait-impl/effects/minicore.rs +++ b/tests/ui/rfcs/rfc-2632-const-trait-impl/effects/minicore.rs @@ -9,7 +9,7 @@ #![crate_type = "lib"] #![feature(no_core, lang_items, unboxed_closures, auto_traits, intrinsics, rustc_attrs, staged_api)] #![feature(fundamental, marker_trait_attr)] -#![feature(const_trait_impl, effects, const_mut_refs)] +#![feature(const_trait_impl, effects)] #![allow(internal_features, incomplete_features)] #![no_std] #![no_core] diff --git a/tests/ui/rfcs/rfc-2632-const-trait-impl/issue-100222.rs b/tests/ui/rfcs/rfc-2632-const-trait-impl/issue-100222.rs index 47f9fc664ce..13c469d656c 100644 --- a/tests/ui/rfcs/rfc-2632-const-trait-impl/issue-100222.rs +++ b/tests/ui/rfcs/rfc-2632-const-trait-impl/issue-100222.rs @@ -3,7 +3,7 @@ //@ check-pass #![allow(incomplete_features)] -#![feature(const_trait_impl, effects, associated_type_defaults, const_mut_refs)] +#![feature(const_trait_impl, effects, associated_type_defaults)] #[cfg_attr(any(yn, yy), const_trait)] pub trait Index { diff --git a/tests/ui/self/arbitrary-self-from-method-substs-ice.rs b/tests/ui/self/arbitrary-self-from-method-substs-ice.rs index 8bf9f97e0b9..a544c8ea0d1 100644 --- a/tests/ui/self/arbitrary-self-from-method-substs-ice.rs +++ b/tests/ui/self/arbitrary-self-from-method-substs-ice.rs @@ -11,8 +11,7 @@ impl Foo { //~^ ERROR: `R` cannot be used as the type of `self` //~| ERROR destructor of `R` cannot be evaluated at compile-time self.0 - //~^ ERROR cannot borrow here, since the borrowed element may contain interior mutability - //~| ERROR cannot call non-const fn `::deref` in constant function + //~^ ERROR cannot call non-const fn `::deref` in constant function } } diff --git a/tests/ui/self/arbitrary-self-from-method-substs-ice.stderr b/tests/ui/self/arbitrary-self-from-method-substs-ice.stderr index 9e3851f9a6e..505b0a173fa 100644 --- a/tests/ui/self/arbitrary-self-from-method-substs-ice.stderr +++ b/tests/ui/self/arbitrary-self-from-method-substs-ice.stderr @@ -1,13 +1,3 @@ -error[E0658]: cannot borrow here, since the borrowed element may contain interior mutability - --> $DIR/arbitrary-self-from-method-substs-ice.rs:13:9 - | -LL | self.0 - | ^^^^ - | - = note: see issue #80384 for more information - = help: add `#![feature(const_refs_to_cell)]` to the crate attributes to enable - = note: this compiler was built on YYYY-MM-DD; consider upgrading it if it is out of date - error[E0015]: cannot call non-const fn `::deref` in constant functions --> $DIR/arbitrary-self-from-method-substs-ice.rs:13:9 | @@ -40,7 +30,7 @@ LL | const fn get>(self: R) -> u32 { = note: this compiler was built on YYYY-MM-DD; consider upgrading it if it is out of date = help: consider changing to `self`, `&self`, `&mut self`, `self: Box`, `self: Rc`, `self: Arc`, or `self: Pin

` (where P is one of the previous types except `Self`) -error: aborting due to 4 previous errors +error: aborting due to 3 previous errors Some errors have detailed explanations: E0015, E0493, E0658. For more information about an error, try `rustc --explain E0015`. diff --git a/tests/ui/simd/intrinsic/generic-elements-pass.rs b/tests/ui/simd/intrinsic/generic-elements-pass.rs index b159387ab62..7b1bda4fbcd 100644 --- a/tests/ui/simd/intrinsic/generic-elements-pass.rs +++ b/tests/ui/simd/intrinsic/generic-elements-pass.rs @@ -23,6 +23,9 @@ extern "rust-intrinsic" { fn simd_shuffle(x: T, y: T, idx: I) -> U; } +#[repr(simd)] +struct SimdShuffleIdx([u32; LEN]); + macro_rules! all_eq { ($a: expr, $b: expr) => {{ let a = $a; @@ -30,9 +33,8 @@ macro_rules! all_eq { // type inference works better with the concrete type on the // left, but humans work better with the expected on the // right. - assert!(b == a, - "{:?} != {:?}", a, b); - }} + assert!(b == a, "{:?} != {:?}", a, b); + }}; } fn main() { @@ -79,20 +81,34 @@ fn main() { let y4 = i32x4([140, 141, 142, 143]); let y8 = i32x8([180, 181, 182, 183, 184, 185, 186, 187]); unsafe { - all_eq!(simd_shuffle(x2, y2, const { [3u32, 0] }), i32x2([121, 20])); - all_eq!(simd_shuffle(x2, y2, const { [3u32, 0, 1, 2] }), i32x4([121, 20, 21, 120])); - all_eq!(simd_shuffle(x2, y2, const { [3u32, 0, 1, 2, 1, 2, 3, 0] }), - i32x8([121, 20, 21, 120, 21, 120, 121, 20])); + all_eq!(simd_shuffle(x2, y2, const { SimdShuffleIdx([3u32, 0]) }), i32x2([121, 20])); + all_eq!( + simd_shuffle(x2, y2, const { SimdShuffleIdx([3u32, 0, 1, 2]) }), + i32x4([121, 20, 21, 120]) + ); + all_eq!( + simd_shuffle(x2, y2, const { SimdShuffleIdx([3u32, 0, 1, 2, 1, 2, 3, 0]) }), + i32x8([121, 20, 21, 120, 21, 120, 121, 20]) + ); - all_eq!(simd_shuffle(x4, y4, const { [7u32, 2] }), i32x2([143, 42])); - all_eq!(simd_shuffle(x4, y4, const { [7u32, 2, 5, 0] }), i32x4([143, 42, 141, 40])); - all_eq!(simd_shuffle(x4, y4, const { [7u32, 2, 5, 0, 3, 6, 4, 1] }), - i32x8([143, 42, 141, 40, 43, 142, 140, 41])); + all_eq!(simd_shuffle(x4, y4, const { SimdShuffleIdx([7u32, 2]) }), i32x2([143, 42])); + all_eq!( + simd_shuffle(x4, y4, const { SimdShuffleIdx([7u32, 2, 5, 0]) }), + i32x4([143, 42, 141, 40]) + ); + all_eq!( + simd_shuffle(x4, y4, const { SimdShuffleIdx([7u32, 2, 5, 0, 3, 6, 4, 1]) }), + i32x8([143, 42, 141, 40, 43, 142, 140, 41]) + ); - all_eq!(simd_shuffle(x8, y8, const { [11u32, 5] }), i32x2([183, 85])); - all_eq!(simd_shuffle(x8, y8, const { [11u32, 5, 15, 0] }), i32x4([183, 85, 187, 80])); - all_eq!(simd_shuffle(x8, y8, const { [11u32, 5, 15, 0, 3, 8, 12, 1] }), - i32x8([183, 85, 187, 80, 83, 180, 184, 81])); + all_eq!(simd_shuffle(x8, y8, const { SimdShuffleIdx([11u32, 5]) }), i32x2([183, 85])); + all_eq!( + simd_shuffle(x8, y8, const { SimdShuffleIdx([11u32, 5, 15, 0]) }), + i32x4([183, 85, 187, 80]) + ); + all_eq!( + simd_shuffle(x8, y8, const { SimdShuffleIdx([11u32, 5, 15, 0, 3, 8, 12, 1]) }), + i32x8([183, 85, 187, 80, 83, 180, 184, 81]) + ); } - } diff --git a/tests/ui/simd/intrinsic/generic-elements.rs b/tests/ui/simd/intrinsic/generic-elements.rs index 4848fd1b803..5d784a25eab 100644 --- a/tests/ui/simd/intrinsic/generic-elements.rs +++ b/tests/ui/simd/intrinsic/generic-elements.rs @@ -37,6 +37,9 @@ extern "rust-intrinsic" { fn simd_shuffle_generic(x: T, y: T) -> U; } +#[repr(simd)] +struct SimdShuffleIdx([u32; LEN]); + fn main() { let x = i32x4([0, 0, 0, 0]); @@ -48,13 +51,13 @@ fn main() { simd_extract::<_, f32>(x, 0); //~^ ERROR expected return type `i32` (element of input `i32x4`), found `f32` - const IDX2: [u32; 2] = [0; 2]; + const IDX2: SimdShuffleIdx<2> = SimdShuffleIdx([0; 2]); simd_shuffle::(0, 0, IDX2); //~^ ERROR expected SIMD input type, found non-SIMD `i32` - const IDX4: [u32; 4] = [0; 4]; + const IDX4: SimdShuffleIdx<4> = SimdShuffleIdx([0; 4]); simd_shuffle::(0, 0, IDX4); //~^ ERROR expected SIMD input type, found non-SIMD `i32` - const IDX8: [u32; 8] = [0; 8]; + const IDX8: SimdShuffleIdx<8> = SimdShuffleIdx([0; 8]); simd_shuffle::(0, 0, IDX8); //~^ ERROR expected SIMD input type, found non-SIMD `i32` diff --git a/tests/ui/simd/intrinsic/generic-elements.stderr b/tests/ui/simd/intrinsic/generic-elements.stderr index 0788a7c17f9..fd726d75326 100644 --- a/tests/ui/simd/intrinsic/generic-elements.stderr +++ b/tests/ui/simd/intrinsic/generic-elements.stderr @@ -1,125 +1,125 @@ error[E0511]: invalid monomorphization of `simd_insert` intrinsic: expected SIMD input type, found non-SIMD `i32` - --> $DIR/generic-elements.rs:44:9 + --> $DIR/generic-elements.rs:47:9 | LL | simd_insert(0, 0, 0); | ^^^^^^^^^^^^^^^^^^^^ error[E0511]: invalid monomorphization of `simd_insert` intrinsic: expected inserted type `i32` (element of input `i32x4`), found `f64` - --> $DIR/generic-elements.rs:46:9 + --> $DIR/generic-elements.rs:49:9 | LL | simd_insert(x, 0, 1.0); | ^^^^^^^^^^^^^^^^^^^^^^ error[E0511]: invalid monomorphization of `simd_extract` intrinsic: expected return type `i32` (element of input `i32x4`), found `f32` - --> $DIR/generic-elements.rs:48:9 + --> $DIR/generic-elements.rs:51:9 | LL | simd_extract::<_, f32>(x, 0); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ error[E0511]: invalid monomorphization of `simd_shuffle` intrinsic: expected SIMD input type, found non-SIMD `i32` - --> $DIR/generic-elements.rs:52:9 + --> $DIR/generic-elements.rs:55:9 | LL | simd_shuffle::(0, 0, IDX2); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ error[E0511]: invalid monomorphization of `simd_shuffle` intrinsic: expected SIMD input type, found non-SIMD `i32` - --> $DIR/generic-elements.rs:55:9 + --> $DIR/generic-elements.rs:58:9 | LL | simd_shuffle::(0, 0, IDX4); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ error[E0511]: invalid monomorphization of `simd_shuffle` intrinsic: expected SIMD input type, found non-SIMD `i32` - --> $DIR/generic-elements.rs:58:9 + --> $DIR/generic-elements.rs:61:9 | LL | simd_shuffle::(0, 0, IDX8); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ error[E0511]: invalid monomorphization of `simd_shuffle` intrinsic: expected return element type `i32` (element of input `i32x4`), found `f32x2` with element type `f32` - --> $DIR/generic-elements.rs:61:9 + --> $DIR/generic-elements.rs:64:9 | LL | simd_shuffle::<_, _, f32x2>(x, x, IDX2); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ error[E0511]: invalid monomorphization of `simd_shuffle` intrinsic: expected return element type `i32` (element of input `i32x4`), found `f32x4` with element type `f32` - --> $DIR/generic-elements.rs:63:9 + --> $DIR/generic-elements.rs:66:9 | LL | simd_shuffle::<_, _, f32x4>(x, x, IDX4); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ error[E0511]: invalid monomorphization of `simd_shuffle` intrinsic: expected return element type `i32` (element of input `i32x4`), found `f32x8` with element type `f32` - --> $DIR/generic-elements.rs:65:9 + --> $DIR/generic-elements.rs:68:9 | LL | simd_shuffle::<_, _, f32x8>(x, x, IDX8); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ error[E0511]: invalid monomorphization of `simd_shuffle` intrinsic: expected return type of length 2, found `i32x8` with length 8 - --> $DIR/generic-elements.rs:68:9 + --> $DIR/generic-elements.rs:71:9 | LL | simd_shuffle::<_, _, i32x8>(x, x, IDX2); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ error[E0511]: invalid monomorphization of `simd_shuffle` intrinsic: expected return type of length 4, found `i32x8` with length 8 - --> $DIR/generic-elements.rs:70:9 + --> $DIR/generic-elements.rs:73:9 | LL | simd_shuffle::<_, _, i32x8>(x, x, IDX4); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ error[E0511]: invalid monomorphization of `simd_shuffle` intrinsic: expected return type of length 8, found `i32x2` with length 2 - --> $DIR/generic-elements.rs:72:9 + --> $DIR/generic-elements.rs:75:9 | LL | simd_shuffle::<_, _, i32x2>(x, x, IDX8); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ error[E0511]: invalid monomorphization of `simd_shuffle_generic` intrinsic: expected SIMD input type, found non-SIMD `i32` - --> $DIR/generic-elements.rs:76:9 + --> $DIR/generic-elements.rs:79:9 | LL | simd_shuffle_generic::(0, 0); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ error[E0511]: invalid monomorphization of `simd_shuffle_generic` intrinsic: expected SIMD input type, found non-SIMD `i32` - --> $DIR/generic-elements.rs:79:9 + --> $DIR/generic-elements.rs:82:9 | LL | simd_shuffle_generic::(0, 0); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ error[E0511]: invalid monomorphization of `simd_shuffle_generic` intrinsic: expected SIMD input type, found non-SIMD `i32` - --> $DIR/generic-elements.rs:82:9 + --> $DIR/generic-elements.rs:85:9 | LL | simd_shuffle_generic::(0, 0); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ error[E0511]: invalid monomorphization of `simd_shuffle_generic` intrinsic: expected return element type `i32` (element of input `i32x4`), found `f32x2` with element type `f32` - --> $DIR/generic-elements.rs:85:9 + --> $DIR/generic-elements.rs:88:9 | LL | simd_shuffle_generic::<_, f32x2, I2>(x, x); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ error[E0511]: invalid monomorphization of `simd_shuffle_generic` intrinsic: expected return element type `i32` (element of input `i32x4`), found `f32x4` with element type `f32` - --> $DIR/generic-elements.rs:87:9 + --> $DIR/generic-elements.rs:90:9 | LL | simd_shuffle_generic::<_, f32x4, I4>(x, x); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ error[E0511]: invalid monomorphization of `simd_shuffle_generic` intrinsic: expected return element type `i32` (element of input `i32x4`), found `f32x8` with element type `f32` - --> $DIR/generic-elements.rs:89:9 + --> $DIR/generic-elements.rs:92:9 | LL | simd_shuffle_generic::<_, f32x8, I8>(x, x); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ error[E0511]: invalid monomorphization of `simd_shuffle_generic` intrinsic: expected return type of length 2, found `i32x8` with length 8 - --> $DIR/generic-elements.rs:92:9 + --> $DIR/generic-elements.rs:95:9 | LL | simd_shuffle_generic::<_, i32x8, I2>(x, x); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ error[E0511]: invalid monomorphization of `simd_shuffle_generic` intrinsic: expected return type of length 4, found `i32x8` with length 8 - --> $DIR/generic-elements.rs:94:9 + --> $DIR/generic-elements.rs:97:9 | LL | simd_shuffle_generic::<_, i32x8, I4>(x, x); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ error[E0511]: invalid monomorphization of `simd_shuffle_generic` intrinsic: expected return type of length 8, found `i32x2` with length 2 - --> $DIR/generic-elements.rs:96:9 + --> $DIR/generic-elements.rs:99:9 | LL | simd_shuffle_generic::<_, i32x2, I8>(x, x); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ diff --git a/tests/ui/simd/intrinsic/generic-shuffle.rs b/tests/ui/simd/intrinsic/generic-shuffle.rs index c0888f67784..2752718d99d 100644 --- a/tests/ui/simd/intrinsic/generic-shuffle.rs +++ b/tests/ui/simd/intrinsic/generic-shuffle.rs @@ -14,13 +14,16 @@ extern "rust-intrinsic" { } fn main() { - const I: [u32; 2] = [0; 2]; - const I2: [f32; 2] = [0.; 2]; + const I: Simd = Simd([0; 2]); + const I2: Simd = Simd([0.; 2]); let v = Simd::([0; 4]); unsafe { let _: Simd = simd_shuffle(v, v, I); + let _: Simd = simd_shuffle(v, v, const { [0u32; 2] }); + //~^ ERROR invalid monomorphization of `simd_shuffle` intrinsic + let _: Simd = simd_shuffle(v, v, I); //~^ ERROR invalid monomorphization of `simd_shuffle` intrinsic diff --git a/tests/ui/simd/intrinsic/generic-shuffle.stderr b/tests/ui/simd/intrinsic/generic-shuffle.stderr index 81e641612ce..7e6d51a5f65 100644 --- a/tests/ui/simd/intrinsic/generic-shuffle.stderr +++ b/tests/ui/simd/intrinsic/generic-shuffle.stderr @@ -1,21 +1,27 @@ -error[E0511]: invalid monomorphization of `simd_shuffle` intrinsic: expected return type of length 2, found `Simd` with length 4 +error[E0511]: invalid monomorphization of `simd_shuffle` intrinsic: simd_shuffle index must be a SIMD vector of `u32`, got `[u32; 2]` --> $DIR/generic-shuffle.rs:24:31 | +LL | let _: Simd = simd_shuffle(v, v, const { [0u32; 2] }); + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +error[E0511]: invalid monomorphization of `simd_shuffle` intrinsic: expected return type of length 2, found `Simd` with length 4 + --> $DIR/generic-shuffle.rs:27:31 + | LL | let _: Simd = simd_shuffle(v, v, I); | ^^^^^^^^^^^^^^^^^^^^^ error[E0511]: invalid monomorphization of `simd_shuffle` intrinsic: expected return element type `u32` (element of input `Simd`), found `Simd` with element type `f32` - --> $DIR/generic-shuffle.rs:27:31 + --> $DIR/generic-shuffle.rs:30:31 | LL | let _: Simd = simd_shuffle(v, v, I); | ^^^^^^^^^^^^^^^^^^^^^ -error[E0511]: invalid monomorphization of `simd_shuffle` intrinsic: simd_shuffle index must be an array of `u32`, got `[f32; 2]` - --> $DIR/generic-shuffle.rs:30:31 +error[E0511]: invalid monomorphization of `simd_shuffle` intrinsic: simd_shuffle index must be a SIMD vector of `u32`, got `Simd` + --> $DIR/generic-shuffle.rs:33:31 | LL | let _: Simd = simd_shuffle(v, v, I2); | ^^^^^^^^^^^^^^^^^^^^^^ -error: aborting due to 3 previous errors +error: aborting due to 4 previous errors For more information about this error, try `rustc --explain E0511`. diff --git a/tests/ui/simd/intrinsic/inlining-issue67557-ice.rs b/tests/ui/simd/intrinsic/inlining-issue67557-ice.rs index a64a7c0b48a..d9239ef5801 100644 --- a/tests/ui/simd/intrinsic/inlining-issue67557-ice.rs +++ b/tests/ui/simd/intrinsic/inlining-issue67557-ice.rs @@ -13,6 +13,9 @@ extern "rust-intrinsic" { #[derive(Debug, PartialEq)] struct Simd2([u8; 2]); +#[repr(simd)] +struct SimdShuffleIdx([u32; LEN]); + fn main() { unsafe { let _: Simd2 = inline_me(); @@ -21,6 +24,6 @@ fn main() { #[inline(always)] unsafe fn inline_me() -> Simd2 { - const IDX: [u32; 2] = [0, 3]; + const IDX: SimdShuffleIdx<2> = SimdShuffleIdx([0, 3]); simd_shuffle(Simd2([10, 11]), Simd2([12, 13]), IDX) } diff --git a/tests/ui/simd/intrinsic/inlining-issue67557.rs b/tests/ui/simd/intrinsic/inlining-issue67557.rs index cb80d65d468..23dd5075f96 100644 --- a/tests/ui/simd/intrinsic/inlining-issue67557.rs +++ b/tests/ui/simd/intrinsic/inlining-issue67557.rs @@ -13,9 +13,12 @@ extern "rust-intrinsic" { #[derive(Debug, PartialEq)] struct Simd2([u8; 2]); +#[repr(simd)] +struct SimdShuffleIdx([u32; LEN]); + fn main() { unsafe { - const IDX: [u32; 2] = [0, 1]; + const IDX: SimdShuffleIdx<2> = SimdShuffleIdx([0, 1]); let p_res: Simd2 = simd_shuffle(Simd2([10, 11]), Simd2([12, 13]), IDX); let a_res: Simd2 = inline_me(); @@ -37,6 +40,6 @@ fn assert_10_13(x: Simd2) { #[inline(always)] unsafe fn inline_me() -> Simd2 { - const IDX: [u32; 2] = [0, 3]; + const IDX: SimdShuffleIdx<2> = SimdShuffleIdx([0, 3]); simd_shuffle(Simd2([10, 11]), Simd2([12, 13]), IDX) } diff --git a/tests/ui/simd/monomorphize-shuffle-index.generic.stderr b/tests/ui/simd/monomorphize-shuffle-index.generic.stderr index c4cfca7be1d..2d1fa1f8da2 100644 --- a/tests/ui/simd/monomorphize-shuffle-index.generic.stderr +++ b/tests/ui/simd/monomorphize-shuffle-index.generic.stderr @@ -1,8 +1,8 @@ error: overly complex generic constant --> $DIR/monomorphize-shuffle-index.rs:29:45 | -LL | return simd_shuffle_generic::<_, _, { &Self::I }>(a, b); - | ^^--------^^ +LL | return simd_shuffle_generic::<_, _, { &Self::I.0 }>(a, b); + | ^^----------^^ | | | pointer casts are not allowed in generic constants | diff --git a/tests/ui/simd/monomorphize-shuffle-index.rs b/tests/ui/simd/monomorphize-shuffle-index.rs index 30c345cb904..140cf6fbe96 100644 --- a/tests/ui/simd/monomorphize-shuffle-index.rs +++ b/tests/ui/simd/monomorphize-shuffle-index.rs @@ -16,8 +16,8 @@ extern "rust-intrinsic" { struct Simd([T; N]); trait Shuffle { - const I: [u32; N]; - const J: &'static [u32] = &Self::I; + const I: Simd; + const J: &'static [u32] = &Self::I.0; unsafe fn shuffle(&self, a: Simd, b: Simd) -> Simd where @@ -26,7 +26,7 @@ trait Shuffle { #[cfg(old)] return simd_shuffle(a, b, Self::I); #[cfg(generic)] - return simd_shuffle_generic::<_, _, { &Self::I }>(a, b); + return simd_shuffle_generic::<_, _, { &Self::I.0 }>(a, b); //[generic]~^ overly complex generic constant #[cfg(generic_with_fn)] return simd_shuffle_generic::<_, _, { Self::J }>(a, b); @@ -38,12 +38,12 @@ struct Thing; fn main() { struct I1; impl Shuffle<4> for I1 { - const I: [u32; 4] = [0, 2, 4, 6]; + const I: Simd = Simd([0, 2, 4, 6]); } struct I2; impl Shuffle<2> for I2 { - const I: [u32; 2] = [1, 5]; + const I: Simd = Simd([1, 5]); } let a = Simd::([0, 1, 2, 3]); diff --git a/tests/ui/simd/not-out-of-bounds.rs b/tests/ui/simd/not-out-of-bounds.rs index 36d7a5865bc..4bd2a69edbf 100644 --- a/tests/ui/simd/not-out-of-bounds.rs +++ b/tests/ui/simd/not-out-of-bounds.rs @@ -30,6 +30,9 @@ struct u8x64([u8; 64]); use std::intrinsics::simd::*; +#[repr(simd)] +struct SimdShuffleIdx([u32; LEN]); + // Test vectors by lane size. Since LLVM does not distinguish between a shuffle // over two f32s and a shuffle over two u64s, or any other such combination, // it is not necessary to test every possible vector, only lane counts. @@ -37,26 +40,26 @@ macro_rules! test_shuffle_lanes { ($n:literal, $x:ident, $y:ident) => { unsafe { let shuffle: $x = { - const ARR: [u32; $n] = { + const IDX: SimdShuffleIdx<$n> = SimdShuffleIdx({ let mut arr = [0; $n]; arr[0] = $n * 2; arr - }; + }); let mut n: u8 = $n; let vals = [0; $n].map(|_| { n = n - 1; n }); let vec1 = $x(vals); let vec2 = $x(vals); - $y(vec1, vec2, ARR) + $y(vec1, vec2, IDX) }; } } } -//~^^^^^ ERROR: invalid monomorphization of `simd_shuffle` intrinsic -//~| ERROR: invalid monomorphization of `simd_shuffle` intrinsic -//~| ERROR: invalid monomorphization of `simd_shuffle` intrinsic -//~| ERROR: invalid monomorphization of `simd_shuffle` intrinsic -//~| ERROR: invalid monomorphization of `simd_shuffle` intrinsic -//~| ERROR: invalid monomorphization of `simd_shuffle` intrinsic +//~^^^^^ ERROR: invalid monomorphization of `simd_shuffle` intrinsic: SIMD index #0 is out of bounds +//~| ERROR: invalid monomorphization of `simd_shuffle` intrinsic: SIMD index #0 is out of bounds +//~| ERROR: invalid monomorphization of `simd_shuffle` intrinsic: SIMD index #0 is out of bounds +//~| ERROR: invalid monomorphization of `simd_shuffle` intrinsic: SIMD index #0 is out of bounds +//~| ERROR: invalid monomorphization of `simd_shuffle` intrinsic: SIMD index #0 is out of bounds +//~| ERROR: invalid monomorphization of `simd_shuffle` intrinsic: SIMD index #0 is out of bounds // Because the test is mostly embedded in a macro, all the errors have the same origin point. // And unfortunately, standard comments, as in the UI test harness, disappear in macros! @@ -69,15 +72,15 @@ fn main() { test_shuffle_lanes!(64, u8x64, simd_shuffle); let v = u8x2([0, 0]); - const I: [u32; 2] = [4, 4]; + const I: SimdShuffleIdx<2> = SimdShuffleIdx([4, 4]); unsafe { let _: u8x2 = simd_shuffle(v, v, I); - //~^ ERROR invalid monomorphization of `simd_shuffle` intrinsic + //~^ ERROR invalid monomorphization of `simd_shuffle` intrinsic: SIMD index #0 is out of bounds } // also check insert/extract unsafe { - simd_insert(v, 2, 0); //~ ERROR invalid monomorphization of `simd_insert` intrinsic - let _val: u8 = simd_extract(v, 2); //~ ERROR invalid monomorphization of `simd_extract` intrinsic + simd_insert(v, 2, 0u8); //~ ERROR invalid monomorphization of `simd_insert` intrinsic: SIMD index #1 is out of bounds + let _val: u8 = simd_extract(v, 2); //~ ERROR invalid monomorphization of `simd_extract` intrinsic: SIMD index #1 is out of bounds } } diff --git a/tests/ui/simd/not-out-of-bounds.stderr b/tests/ui/simd/not-out-of-bounds.stderr index 5682935c1f1..4b6bda93e45 100644 --- a/tests/ui/simd/not-out-of-bounds.stderr +++ b/tests/ui/simd/not-out-of-bounds.stderr @@ -1,7 +1,7 @@ error[E0511]: invalid monomorphization of `simd_shuffle` intrinsic: SIMD index #0 is out of bounds (limit 4) - --> $DIR/not-out-of-bounds.rs:49:21 + --> $DIR/not-out-of-bounds.rs:52:21 | -LL | $y(vec1, vec2, ARR) +LL | $y(vec1, vec2, IDX) | ^^^^^^^^^^^^^^^^^^^ ... LL | test_shuffle_lanes!(2, u8x2, simd_shuffle); @@ -10,9 +10,9 @@ LL | test_shuffle_lanes!(2, u8x2, simd_shuffle); = note: this error originates in the macro `test_shuffle_lanes` (in Nightly builds, run with -Z macro-backtrace for more info) error[E0511]: invalid monomorphization of `simd_shuffle` intrinsic: SIMD index #0 is out of bounds (limit 8) - --> $DIR/not-out-of-bounds.rs:49:21 + --> $DIR/not-out-of-bounds.rs:52:21 | -LL | $y(vec1, vec2, ARR) +LL | $y(vec1, vec2, IDX) | ^^^^^^^^^^^^^^^^^^^ ... LL | test_shuffle_lanes!(4, u8x4, simd_shuffle); @@ -21,9 +21,9 @@ LL | test_shuffle_lanes!(4, u8x4, simd_shuffle); = note: this error originates in the macro `test_shuffle_lanes` (in Nightly builds, run with -Z macro-backtrace for more info) error[E0511]: invalid monomorphization of `simd_shuffle` intrinsic: SIMD index #0 is out of bounds (limit 16) - --> $DIR/not-out-of-bounds.rs:49:21 + --> $DIR/not-out-of-bounds.rs:52:21 | -LL | $y(vec1, vec2, ARR) +LL | $y(vec1, vec2, IDX) | ^^^^^^^^^^^^^^^^^^^ ... LL | test_shuffle_lanes!(8, u8x8, simd_shuffle); @@ -32,9 +32,9 @@ LL | test_shuffle_lanes!(8, u8x8, simd_shuffle); = note: this error originates in the macro `test_shuffle_lanes` (in Nightly builds, run with -Z macro-backtrace for more info) error[E0511]: invalid monomorphization of `simd_shuffle` intrinsic: SIMD index #0 is out of bounds (limit 32) - --> $DIR/not-out-of-bounds.rs:49:21 + --> $DIR/not-out-of-bounds.rs:52:21 | -LL | $y(vec1, vec2, ARR) +LL | $y(vec1, vec2, IDX) | ^^^^^^^^^^^^^^^^^^^ ... LL | test_shuffle_lanes!(16, u8x16, simd_shuffle); @@ -43,9 +43,9 @@ LL | test_shuffle_lanes!(16, u8x16, simd_shuffle); = note: this error originates in the macro `test_shuffle_lanes` (in Nightly builds, run with -Z macro-backtrace for more info) error[E0511]: invalid monomorphization of `simd_shuffle` intrinsic: SIMD index #0 is out of bounds (limit 64) - --> $DIR/not-out-of-bounds.rs:49:21 + --> $DIR/not-out-of-bounds.rs:52:21 | -LL | $y(vec1, vec2, ARR) +LL | $y(vec1, vec2, IDX) | ^^^^^^^^^^^^^^^^^^^ ... LL | test_shuffle_lanes!(32, u8x32, simd_shuffle); @@ -54,9 +54,9 @@ LL | test_shuffle_lanes!(32, u8x32, simd_shuffle); = note: this error originates in the macro `test_shuffle_lanes` (in Nightly builds, run with -Z macro-backtrace for more info) error[E0511]: invalid monomorphization of `simd_shuffle` intrinsic: SIMD index #0 is out of bounds (limit 128) - --> $DIR/not-out-of-bounds.rs:49:21 + --> $DIR/not-out-of-bounds.rs:52:21 | -LL | $y(vec1, vec2, ARR) +LL | $y(vec1, vec2, IDX) | ^^^^^^^^^^^^^^^^^^^ ... LL | test_shuffle_lanes!(64, u8x64, simd_shuffle); @@ -65,19 +65,19 @@ LL | test_shuffle_lanes!(64, u8x64, simd_shuffle); = note: this error originates in the macro `test_shuffle_lanes` (in Nightly builds, run with -Z macro-backtrace for more info) error[E0511]: invalid monomorphization of `simd_shuffle` intrinsic: SIMD index #0 is out of bounds (limit 4) - --> $DIR/not-out-of-bounds.rs:74:23 + --> $DIR/not-out-of-bounds.rs:77:23 | LL | let _: u8x2 = simd_shuffle(v, v, I); | ^^^^^^^^^^^^^^^^^^^^^ -error[E0511]: invalid monomorphization of `simd_insert` intrinsic: expected inserted type `u8` (element of input `u8x2`), found `i32` - --> $DIR/not-out-of-bounds.rs:80:9 +error[E0511]: invalid monomorphization of `simd_insert` intrinsic: SIMD index #1 is out of bounds (limit 2) + --> $DIR/not-out-of-bounds.rs:83:9 | -LL | simd_insert(v, 2, 0); - | ^^^^^^^^^^^^^^^^^^^^ +LL | simd_insert(v, 2, 0u8); + | ^^^^^^^^^^^^^^^^^^^^^^ error[E0511]: invalid monomorphization of `simd_extract` intrinsic: SIMD index #1 is out of bounds (limit 2) - --> $DIR/not-out-of-bounds.rs:81:24 + --> $DIR/not-out-of-bounds.rs:84:24 | LL | let _val: u8 = simd_extract(v, 2); | ^^^^^^^^^^^^^^^^^^ diff --git a/tests/ui/simd/shuffle.rs b/tests/ui/simd/shuffle.rs index dc0d688284e..96c0ed2118f 100644 --- a/tests/ui/simd/shuffle.rs +++ b/tests/ui/simd/shuffle.rs @@ -16,16 +16,13 @@ extern "rust-intrinsic" { #[repr(simd)] struct Simd([T; N]); -unsafe fn __shuffle_vector16(x: T, y: T) -> U { - simd_shuffle(x, y, IDX) -} -unsafe fn __shuffle_vector16_v2, T, U>(x: T, y: T) -> U { +unsafe fn __shuffle_vector16, T, U>(x: T, y: T) -> U { simd_shuffle(x, y, IDX) } fn main() { - const I1: [u32; 4] = [0, 2, 4, 6]; - const I2: [u32; 2] = [1, 5]; + const I1: Simd = Simd([0, 2, 4, 6]); + const I2: Simd = Simd([1, 5]); let a = Simd::([0, 1, 2, 3]); let b = Simd::([4, 5, 6, 7]); unsafe { @@ -35,16 +32,6 @@ fn main() { let y: Simd = simd_shuffle(a, b, I2); assert_eq!(y.0, [1, 5]); } - // Test that we can also use a SIMD vector instead of a normal array for the shuffle. - const I1_SIMD: Simd = Simd([0, 2, 4, 6]); - const I2_SIMD: Simd = Simd([1, 5]); - unsafe { - let x: Simd = simd_shuffle(a, b, I1_SIMD); - assert_eq!(x.0, [0, 2, 4, 6]); - - let y: Simd = simd_shuffle(a, b, I2_SIMD); - assert_eq!(y.0, [1, 5]); - } // Test that an indirection (via an unnamed constant) // through a const generic parameter also works. @@ -53,13 +40,6 @@ fn main() { let b = Simd::([16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31]); unsafe { __shuffle_vector16::< - { [1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16] }, - Simd, - Simd, - >(a, b); - } - unsafe { - __shuffle_vector16_v2::< { Simd([1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16]) }, Simd, Simd, diff --git a/tests/ui/static/raw-ref-deref-with-unsafe.rs b/tests/ui/static/raw-ref-deref-with-unsafe.rs index 4b8f72de5b7..0974948b3a0 100644 --- a/tests/ui/static/raw-ref-deref-with-unsafe.rs +++ b/tests/ui/static/raw-ref-deref-with-unsafe.rs @@ -1,5 +1,4 @@ //@ check-pass -#![feature(const_mut_refs)] use std::ptr; // This code should remain unsafe because of the two unsafe operations here, diff --git a/tests/ui/static/raw-ref-deref-without-unsafe.rs b/tests/ui/static/raw-ref-deref-without-unsafe.rs index f9bce4368c1..289e55b7638 100644 --- a/tests/ui/static/raw-ref-deref-without-unsafe.rs +++ b/tests/ui/static/raw-ref-deref-without-unsafe.rs @@ -1,5 +1,3 @@ -#![feature(const_mut_refs)] - use std::ptr; // This code should remain unsafe because of the two unsafe operations here, diff --git a/tests/ui/static/raw-ref-deref-without-unsafe.stderr b/tests/ui/static/raw-ref-deref-without-unsafe.stderr index ac4df8b410c..f034499bbb5 100644 --- a/tests/ui/static/raw-ref-deref-without-unsafe.stderr +++ b/tests/ui/static/raw-ref-deref-without-unsafe.stderr @@ -1,5 +1,5 @@ error[E0133]: dereference of raw pointer is unsafe and requires unsafe function or block - --> $DIR/raw-ref-deref-without-unsafe.rs:12:56 + --> $DIR/raw-ref-deref-without-unsafe.rs:10:56 | LL | static mut DEREF_BYTE_PTR: *mut u8 = ptr::addr_of_mut!(*BYTE_PTR); | ^^^^^^^^^ dereference of raw pointer @@ -7,7 +7,7 @@ LL | static mut DEREF_BYTE_PTR: *mut u8 = ptr::addr_of_mut!(*BYTE_PTR); = note: raw pointers may be null, dangling or unaligned; they can violate aliasing rules and cause data races: all of these are undefined behavior error[E0133]: use of mutable static is unsafe and requires unsafe function or block - --> $DIR/raw-ref-deref-without-unsafe.rs:12:57 + --> $DIR/raw-ref-deref-without-unsafe.rs:10:57 | LL | static mut DEREF_BYTE_PTR: *mut u8 = ptr::addr_of_mut!(*BYTE_PTR); | ^^^^^^^^ use of mutable static diff --git a/tests/ui/statics/mutable_memory_validation.rs b/tests/ui/statics/mutable_memory_validation.rs index 470229d5fa7..d16b787fef8 100644 --- a/tests/ui/statics/mutable_memory_validation.rs +++ b/tests/ui/statics/mutable_memory_validation.rs @@ -4,7 +4,6 @@ //@ normalize-stderr-test: "(the raw bytes of the constant) \(size: [0-9]*, align: [0-9]*\)" -> "$1 (size: $$SIZE, align: $$ALIGN)" //@ normalize-stderr-test: "([0-9a-f][0-9a-f] |╾─*A(LLOC)?[0-9]+(\+[a-z0-9]+)?()?─*╼ )+ *│.*" -> "HEX_DUMP" -#![feature(const_mut_refs)] #![feature(const_refs_to_static)] use std::cell::UnsafeCell; diff --git a/tests/ui/statics/mutable_memory_validation.stderr b/tests/ui/statics/mutable_memory_validation.stderr index f21269235e9..60d13564679 100644 --- a/tests/ui/statics/mutable_memory_validation.stderr +++ b/tests/ui/statics/mutable_memory_validation.stderr @@ -1,5 +1,5 @@ error[E0080]: it is undefined behavior to use this value - --> $DIR/mutable_memory_validation.rs:16:1 + --> $DIR/mutable_memory_validation.rs:15:1 | LL | const MUH: Meh = Meh { x: unsafe { &mut *(&READONLY as *const _ as *mut _) } }; | ^^^^^^^^^^^^^^ constructing invalid value at .x.: encountered `UnsafeCell` in read-only memory diff --git a/tests/ui/statics/nested_thread_local.rs b/tests/ui/statics/nested_thread_local.rs index a512016335a..2590cc579cd 100644 --- a/tests/ui/statics/nested_thread_local.rs +++ b/tests/ui/statics/nested_thread_local.rs @@ -1,6 +1,5 @@ // Check that we forbid nested statics in `thread_local` statics. -#![feature(const_refs_to_cell)] #![feature(thread_local)] #[thread_local] diff --git a/tests/ui/statics/nested_thread_local.stderr b/tests/ui/statics/nested_thread_local.stderr index 30c742626fa..b078c286965 100644 --- a/tests/ui/statics/nested_thread_local.stderr +++ b/tests/ui/statics/nested_thread_local.stderr @@ -1,5 +1,5 @@ error: #[thread_local] does not support implicit nested statics, please create explicit static items and refer to them instead - --> $DIR/nested_thread_local.rs:7:1 + --> $DIR/nested_thread_local.rs:6:1 | LL | static mut FOO: &u32 = { | ^^^^^^^^^^^^^^^^^^^^ diff --git a/tests/ui/suggestions/deref-path-method.stderr b/tests/ui/suggestions/deref-path-method.stderr index b27d9aef066..bfcc2307fd7 100644 --- a/tests/ui/suggestions/deref-path-method.stderr +++ b/tests/ui/suggestions/deref-path-method.stderr @@ -9,7 +9,7 @@ note: if you're trying to build a new `Vec<_, _>` consider using one of the foll Vec::::with_capacity Vec::::try_with_capacity Vec::::from_raw_parts - and 4 others + and 6 others --> $SRC_DIR/alloc/src/vec/mod.rs:LL:COL help: the function `contains` is implemented on `[_]` | diff --git a/tests/ui/thread-local/thread-local-static.rs b/tests/ui/thread-local/thread-local-static.rs index 05df0471b14..af30f538366 100644 --- a/tests/ui/thread-local/thread-local-static.rs +++ b/tests/ui/thread-local/thread-local-static.rs @@ -7,10 +7,8 @@ #[thread_local] static mut STATIC_VAR_2: [u32; 8] = [4; 8]; const fn g(x: &mut [u32; 8]) { - //~^ ERROR mutable references are not allowed std::mem::swap(x, &mut STATIC_VAR_2) //~^ ERROR thread-local statics cannot be accessed - //~| ERROR mutable references are not allowed //~| ERROR use of mutable static is unsafe } diff --git a/tests/ui/thread-local/thread-local-static.stderr b/tests/ui/thread-local/thread-local-static.stderr index a6499fd15ec..3bc1aec00c1 100644 --- a/tests/ui/thread-local/thread-local-static.stderr +++ b/tests/ui/thread-local/thread-local-static.stderr @@ -1,38 +1,18 @@ error[E0133]: use of mutable static is unsafe and requires unsafe function or block - --> $DIR/thread-local-static.rs:11:28 + --> $DIR/thread-local-static.rs:10:28 | LL | std::mem::swap(x, &mut STATIC_VAR_2) | ^^^^^^^^^^^^ use of mutable static | = note: mutable statics can be mutated by multiple threads: aliasing violations or data races will cause undefined behavior -error[E0658]: mutable references are not allowed in constant functions - --> $DIR/thread-local-static.rs:9:12 - | -LL | const fn g(x: &mut [u32; 8]) { - | ^ - | - = note: see issue #57349 for more information - = help: add `#![feature(const_mut_refs)]` to the crate attributes to enable - = note: this compiler was built on YYYY-MM-DD; consider upgrading it if it is out of date - error[E0625]: thread-local statics cannot be accessed at compile-time - --> $DIR/thread-local-static.rs:11:28 + --> $DIR/thread-local-static.rs:10:28 | LL | std::mem::swap(x, &mut STATIC_VAR_2) | ^^^^^^^^^^^^ -error[E0658]: mutable references are not allowed in constant functions - --> $DIR/thread-local-static.rs:11:23 - | -LL | std::mem::swap(x, &mut STATIC_VAR_2) - | ^^^^^^^^^^^^^^^^^ - | - = note: see issue #57349 for more information - = help: add `#![feature(const_mut_refs)]` to the crate attributes to enable - = note: this compiler was built on YYYY-MM-DD; consider upgrading it if it is out of date +error: aborting due to 2 previous errors -error: aborting due to 4 previous errors - -Some errors have detailed explanations: E0133, E0625, E0658. +Some errors have detailed explanations: E0133, E0625. For more information about an error, try `rustc --explain E0133`. diff --git a/tests/ui/transmutability/enums/niche_optimization.rs b/tests/ui/transmutability/enums/niche_optimization.rs index 802d1747568..2436be50027 100644 --- a/tests/ui/transmutability/enums/niche_optimization.rs +++ b/tests/ui/transmutability/enums/niche_optimization.rs @@ -154,3 +154,12 @@ fn no_niche() { assert::is_transmutable::>, OptionLike>(); assert::is_transmutable::>, OptionLike>(); } + +fn niche_fields() { + enum Kind { + A(bool, bool), + B(bool), + } + + assert::is_maybe_transmutable::(); +} diff --git a/tests/ui/ufcs/bad-builder.stderr b/tests/ui/ufcs/bad-builder.stderr index 9cfeb7a5d09..e466f94d0d8 100644 --- a/tests/ui/ufcs/bad-builder.stderr +++ b/tests/ui/ufcs/bad-builder.stderr @@ -9,7 +9,7 @@ note: if you're trying to build a new `Vec` consider using one of the followi Vec::::with_capacity Vec::::try_with_capacity Vec::::from_raw_parts - and 4 others + and 6 others --> $SRC_DIR/alloc/src/vec/mod.rs:LL:COL help: there is an associated function `new` with a similar name | diff --git a/tests/ui/uninhabited/uninhabited-patterns.stderr b/tests/ui/uninhabited/uninhabited-patterns.stderr index db0166ad5f2..7a872767d95 100644 --- a/tests/ui/uninhabited/uninhabited-patterns.stderr +++ b/tests/ui/uninhabited/uninhabited-patterns.stderr @@ -2,7 +2,10 @@ error: unreachable pattern --> $DIR/uninhabited-patterns.rs:30:9 | LL | Ok(box _) => (), - | ^^^^^^^^^ matches no values because `NotSoSecretlyEmpty` is uninhabited + | ^^^^^^^^^------- + | | + | matches no values because `NotSoSecretlyEmpty` is uninhabited + | help: remove the match arm | = note: to learn more about uninhabited types, see https://doc.rust-lang.org/nomicon/exotic-sizes.html#empty-types note: the lint level is defined here @@ -15,7 +18,10 @@ error: unreachable pattern --> $DIR/uninhabited-patterns.rs:39:9 | LL | Err(Ok(_y)) => (), - | ^^^^^^^^^^^ matches no values because `NotSoSecretlyEmpty` is uninhabited + | ^^^^^^^^^^^------- + | | + | matches no values because `NotSoSecretlyEmpty` is uninhabited + | help: remove the match arm | = note: to learn more about uninhabited types, see https://doc.rust-lang.org/nomicon/exotic-sizes.html#empty-types diff --git a/tests/ui/unsafe/ranged_ints2_const.rs b/tests/ui/unsafe/ranged_ints2_const.rs index b7178c2b52b..a9f5b2089c4 100644 --- a/tests/ui/unsafe/ranged_ints2_const.rs +++ b/tests/ui/unsafe/ranged_ints2_const.rs @@ -8,19 +8,19 @@ fn main() { const fn foo() -> NonZero { let mut x = unsafe { NonZero(1) }; - let y = &mut x.0; //~ ERROR mutable references + let y = &mut x.0; //~^ ERROR mutation of layout constrained field is unsafe unsafe { NonZero(1) } } const fn bar() -> NonZero { let mut x = unsafe { NonZero(1) }; - let y = unsafe { &mut x.0 }; //~ ERROR mutable references + let y = unsafe { &mut x.0 }; unsafe { NonZero(1) } } const fn boo() -> NonZero { let mut x = unsafe { NonZero(1) }; - unsafe { let y = &mut x.0; } //~ ERROR mutable references + unsafe { let y = &mut x.0; } unsafe { NonZero(1) } } diff --git a/tests/ui/unsafe/ranged_ints2_const.stderr b/tests/ui/unsafe/ranged_ints2_const.stderr index 2d25084314e..3373d627b5e 100644 --- a/tests/ui/unsafe/ranged_ints2_const.stderr +++ b/tests/ui/unsafe/ranged_ints2_const.stderr @@ -6,37 +6,6 @@ LL | let y = &mut x.0; | = note: mutating layout constrained fields cannot statically be checked for valid values -error[E0658]: mutable references are not allowed in constant functions - --> $DIR/ranged_ints2_const.rs:11:13 - | -LL | let y = &mut x.0; - | ^^^^^^^^ - | - = note: see issue #57349 for more information - = help: add `#![feature(const_mut_refs)]` to the crate attributes to enable - = note: this compiler was built on YYYY-MM-DD; consider upgrading it if it is out of date +error: aborting due to 1 previous error -error[E0658]: mutable references are not allowed in constant functions - --> $DIR/ranged_ints2_const.rs:18:22 - | -LL | let y = unsafe { &mut x.0 }; - | ^^^^^^^^ - | - = note: see issue #57349 for more information - = help: add `#![feature(const_mut_refs)]` to the crate attributes to enable - = note: this compiler was built on YYYY-MM-DD; consider upgrading it if it is out of date - -error[E0658]: mutable references are not allowed in constant functions - --> $DIR/ranged_ints2_const.rs:24:22 - | -LL | unsafe { let y = &mut x.0; } - | ^^^^^^^^ - | - = note: see issue #57349 for more information - = help: add `#![feature(const_mut_refs)]` to the crate attributes to enable - = note: this compiler was built on YYYY-MM-DD; consider upgrading it if it is out of date - -error: aborting due to 4 previous errors - -Some errors have detailed explanations: E0133, E0658. -For more information about an error, try `rustc --explain E0133`. +For more information about this error, try `rustc --explain E0133`. diff --git a/tests/ui/unsafe/ranged_ints3_const.rs b/tests/ui/unsafe/ranged_ints3_const.rs index c069ae7da02..91e84f7ffbd 100644 --- a/tests/ui/unsafe/ranged_ints3_const.rs +++ b/tests/ui/unsafe/ranged_ints3_const.rs @@ -9,13 +9,13 @@ fn main() {} const fn foo() -> NonZero> { let mut x = unsafe { NonZero(Cell::new(1)) }; - let y = &x.0; //~ ERROR the borrowed element may contain interior mutability + let y = &x.0; //~^ ERROR borrow of layout constrained field with interior mutability unsafe { NonZero(Cell::new(1)) } } const fn bar() -> NonZero> { let mut x = unsafe { NonZero(Cell::new(1)) }; - let y = unsafe { &x.0 }; //~ ERROR the borrowed element may contain interior mutability + let y = unsafe { &x.0 }; unsafe { NonZero(Cell::new(1)) } } diff --git a/tests/ui/unsafe/ranged_ints3_const.stderr b/tests/ui/unsafe/ranged_ints3_const.stderr index c388a66f631..a72ab1a3b74 100644 --- a/tests/ui/unsafe/ranged_ints3_const.stderr +++ b/tests/ui/unsafe/ranged_ints3_const.stderr @@ -6,27 +6,6 @@ LL | let y = &x.0; | = note: references to fields of layout constrained fields lose the constraints. Coupled with interior mutability, the field can be changed to invalid values -error[E0658]: cannot borrow here, since the borrowed element may contain interior mutability - --> $DIR/ranged_ints3_const.rs:12:13 - | -LL | let y = &x.0; - | ^^^^ - | - = note: see issue #80384 for more information - = help: add `#![feature(const_refs_to_cell)]` to the crate attributes to enable - = note: this compiler was built on YYYY-MM-DD; consider upgrading it if it is out of date +error: aborting due to 1 previous error -error[E0658]: cannot borrow here, since the borrowed element may contain interior mutability - --> $DIR/ranged_ints3_const.rs:19:22 - | -LL | let y = unsafe { &x.0 }; - | ^^^^ - | - = note: see issue #80384 for more information - = help: add `#![feature(const_refs_to_cell)]` to the crate attributes to enable - = note: this compiler was built on YYYY-MM-DD; consider upgrading it if it is out of date - -error: aborting due to 3 previous errors - -Some errors have detailed explanations: E0133, E0658. -For more information about an error, try `rustc --explain E0133`. +For more information about this error, try `rustc --explain E0133`.