From 45c7ddfea6ba9980a1c6f4f9bd9c821e56af035e Mon Sep 17 00:00:00 2001 From: Sebastian Urban Date: Wed, 18 Dec 2024 11:33:15 +0100 Subject: [PATCH 01/13] Implement Condvar::wait_timeout for targets without threads This always falls back to sleeping since there is no way to notify a condvar on a target without threads. --- library/std/src/sys/sync/condvar/no_threads.rs | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/library/std/src/sys/sync/condvar/no_threads.rs b/library/std/src/sys/sync/condvar/no_threads.rs index 88ce39305e1ae..18d97d4b17ab0 100644 --- a/library/std/src/sys/sync/condvar/no_threads.rs +++ b/library/std/src/sys/sync/condvar/no_threads.rs @@ -1,4 +1,5 @@ use crate::sys::sync::Mutex; +use crate::thread::sleep; use crate::time::Duration; pub struct Condvar {} @@ -19,7 +20,8 @@ impl Condvar { panic!("condvar wait not supported") } - pub unsafe fn wait_timeout(&self, _mutex: &Mutex, _dur: Duration) -> bool { - panic!("condvar wait not supported"); + pub unsafe fn wait_timeout(&self, _mutex: &Mutex, dur: Duration) -> bool { + sleep(dur); + false } } From eb7da164081edb3e6119d20ea3855eaf56624aee Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?R=C3=A9my=20Rakic?= Date: Mon, 30 Dec 2024 10:02:28 +0000 Subject: [PATCH 02/13] move typeck constraints conversion to its own module --- compiler/rustc_borrowck/src/polonius/mod.rs | 42 ++----------------- .../src/polonius/typeck_constraints.rs | 41 ++++++++++++++++++ 2 files changed, 44 insertions(+), 39 deletions(-) create mode 100644 compiler/rustc_borrowck/src/polonius/typeck_constraints.rs diff --git a/compiler/rustc_borrowck/src/polonius/mod.rs b/compiler/rustc_borrowck/src/polonius/mod.rs index a853ff266a119..6ac111410d649 100644 --- a/compiler/rustc_borrowck/src/polonius/mod.rs +++ b/compiler/rustc_borrowck/src/polonius/mod.rs @@ -37,21 +37,20 @@ mod constraints; mod dump; pub(crate) mod legacy; mod liveness_constraints; +mod typeck_constraints; use std::collections::BTreeMap; use rustc_index::bit_set::SparseBitMatrix; -use rustc_middle::mir::{Body, Location}; +use rustc_middle::mir::Body; use rustc_middle::ty::RegionVid; use rustc_mir_dataflow::points::PointIndex; pub(crate) use self::constraints::*; pub(crate) use self::dump::dump_polonius_mir; use self::liveness_constraints::create_liveness_constraints; +use self::typeck_constraints::convert_typeck_constraints; use crate::RegionInferenceContext; -use crate::constraints::OutlivesConstraint; -use crate::region_infer::values::LivenessValues; -use crate::type_check::Locations; /// This struct holds the data needed to create the Polonius localized constraints. pub(crate) struct PoloniusContext { @@ -117,38 +116,3 @@ impl PoloniusContext { localized_outlives_constraints } } - -/// Propagate loans throughout the subset graph at a given point (with some subtleties around the -/// location where effects start to be visible). -fn convert_typeck_constraints<'tcx>( - body: &Body<'tcx>, - liveness: &LivenessValues, - outlives_constraints: impl Iterator>, - localized_outlives_constraints: &mut LocalizedOutlivesConstraintSet, -) { - for outlives_constraint in outlives_constraints { - match outlives_constraint.locations { - Locations::All(_) => { - // For now, turn logical constraints holding at all points into physical edges at - // every point in the graph. - // FIXME: encode this into *traversal* instead. - for (block, bb) in body.basic_blocks.iter_enumerated() { - let statement_count = bb.statements.len(); - for statement_index in 0..=statement_count { - let current_location = Location { block, statement_index }; - let current_point = liveness.point_from_location(current_location); - - localized_outlives_constraints.push(LocalizedOutlivesConstraint { - source: outlives_constraint.sup, - from: current_point, - target: outlives_constraint.sub, - to: current_point, - }); - } - } - } - - _ => {} - } - } -} diff --git a/compiler/rustc_borrowck/src/polonius/typeck_constraints.rs b/compiler/rustc_borrowck/src/polonius/typeck_constraints.rs new file mode 100644 index 0000000000000..3487c454a74f9 --- /dev/null +++ b/compiler/rustc_borrowck/src/polonius/typeck_constraints.rs @@ -0,0 +1,41 @@ +use rustc_middle::mir::{Body, Location}; + +use super::{LocalizedOutlivesConstraint, LocalizedOutlivesConstraintSet}; +use crate::constraints::OutlivesConstraint; +use crate::region_infer::values::LivenessValues; +use crate::type_check::Locations; + +/// Propagate loans throughout the subset graph at a given point (with some subtleties around the +/// location where effects start to be visible). +pub(super) fn convert_typeck_constraints<'tcx>( + body: &Body<'tcx>, + liveness: &LivenessValues, + outlives_constraints: impl Iterator>, + localized_outlives_constraints: &mut LocalizedOutlivesConstraintSet, +) { + for outlives_constraint in outlives_constraints { + match outlives_constraint.locations { + Locations::All(_) => { + // For now, turn logical constraints holding at all points into physical edges at + // every point in the graph. + // FIXME: encode this into *traversal* instead. + for (block, bb) in body.basic_blocks.iter_enumerated() { + let statement_count = bb.statements.len(); + for statement_index in 0..=statement_count { + let current_location = Location { block, statement_index }; + let current_point = liveness.point_from_location(current_location); + + localized_outlives_constraints.push(LocalizedOutlivesConstraint { + source: outlives_constraint.sup, + from: current_point, + target: outlives_constraint.sub, + to: current_point, + }); + } + } + } + + _ => {} + } + } +} From 46154b2253f8f6be9e39cd95a304036a6d895d95 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?R=C3=A9my=20Rakic?= Date: Mon, 30 Dec 2024 10:16:51 +0000 Subject: [PATCH 03/13] localize typeck constraints it's still partially a skeleton, but works well enough for almost all tests to pass --- compiler/rustc_borrowck/src/nll.rs | 6 +- compiler/rustc_borrowck/src/polonius/mod.rs | 5 +- .../src/polonius/typeck_constraints.rs | 194 +++++++++++++++++- 3 files changed, 199 insertions(+), 6 deletions(-) diff --git a/compiler/rustc_borrowck/src/nll.rs b/compiler/rustc_borrowck/src/nll.rs index 968b6d383c1b4..7ae1df9522fb8 100644 --- a/compiler/rustc_borrowck/src/nll.rs +++ b/compiler/rustc_borrowck/src/nll.rs @@ -142,9 +142,9 @@ pub(crate) fn compute_regions<'a, 'tcx>( // If requested for `-Zpolonius=next`, convert NLL constraints to localized outlives // constraints. - let localized_outlives_constraints = polonius_context - .as_mut() - .map(|polonius_context| polonius_context.create_localized_constraints(&mut regioncx, body)); + let localized_outlives_constraints = polonius_context.as_mut().map(|polonius_context| { + polonius_context.create_localized_constraints(infcx.tcx, ®ioncx, body) + }); // If requested: dump NLL facts, and run legacy polonius analysis. let polonius_output = all_facts.as_ref().and_then(|all_facts| { diff --git a/compiler/rustc_borrowck/src/polonius/mod.rs b/compiler/rustc_borrowck/src/polonius/mod.rs index 6ac111410d649..7d0f9397021be 100644 --- a/compiler/rustc_borrowck/src/polonius/mod.rs +++ b/compiler/rustc_borrowck/src/polonius/mod.rs @@ -43,7 +43,7 @@ use std::collections::BTreeMap; use rustc_index::bit_set::SparseBitMatrix; use rustc_middle::mir::Body; -use rustc_middle::ty::RegionVid; +use rustc_middle::ty::{RegionVid, TyCtxt}; use rustc_mir_dataflow::points::PointIndex; pub(crate) use self::constraints::*; @@ -87,14 +87,17 @@ impl PoloniusContext { /// - encoding liveness constraints pub(crate) fn create_localized_constraints<'tcx>( &self, + tcx: TyCtxt<'tcx>, regioncx: &RegionInferenceContext<'tcx>, body: &Body<'tcx>, ) -> LocalizedOutlivesConstraintSet { let mut localized_outlives_constraints = LocalizedOutlivesConstraintSet::default(); convert_typeck_constraints( + tcx, body, regioncx.liveness_constraints(), regioncx.outlives_constraints(), + regioncx.universal_regions(), &mut localized_outlives_constraints, ); diff --git a/compiler/rustc_borrowck/src/polonius/typeck_constraints.rs b/compiler/rustc_borrowck/src/polonius/typeck_constraints.rs index 3487c454a74f9..c04661fbbc1a9 100644 --- a/compiler/rustc_borrowck/src/polonius/typeck_constraints.rs +++ b/compiler/rustc_borrowck/src/polonius/typeck_constraints.rs @@ -1,16 +1,22 @@ -use rustc_middle::mir::{Body, Location}; +use rustc_data_structures::fx::FxHashSet; +use rustc_middle::mir::{Body, Location, Statement, StatementKind, Terminator, TerminatorKind}; +use rustc_middle::ty::{TyCtxt, TypeVisitable}; +use rustc_mir_dataflow::points::PointIndex; use super::{LocalizedOutlivesConstraint, LocalizedOutlivesConstraintSet}; use crate::constraints::OutlivesConstraint; use crate::region_infer::values::LivenessValues; use crate::type_check::Locations; +use crate::universal_regions::UniversalRegions; /// Propagate loans throughout the subset graph at a given point (with some subtleties around the /// location where effects start to be visible). pub(super) fn convert_typeck_constraints<'tcx>( + tcx: TyCtxt<'tcx>, body: &Body<'tcx>, liveness: &LivenessValues, outlives_constraints: impl Iterator>, + universal_regions: &UniversalRegions<'tcx>, localized_outlives_constraints: &mut LocalizedOutlivesConstraintSet, ) { for outlives_constraint in outlives_constraints { @@ -35,7 +41,191 @@ pub(super) fn convert_typeck_constraints<'tcx>( } } - _ => {} + Locations::Single(location) => { + // This constraint is marked as holding at one location, we localize it to that + // location or its successor, depending on the corresponding MIR + // statement/terminator. Unfortunately, they all show up from typeck as coming "on + // entry", so for now we modify them to take effects that should apply "on exit" + // into account. + // + // FIXME: this approach is subtle, complicated, and hard to test, so we should track + // this information better in MIR typeck instead, for example with a new `Locations` + // variant that contains which node is crossing over between entry and exit. + let point = liveness.point_from_location(location); + let (from, to) = if let Some(stmt) = + body[location.block].statements.get(location.statement_index) + { + localize_statement_constraint( + tcx, + body, + stmt, + liveness, + &outlives_constraint, + location, + point, + universal_regions, + ) + } else { + assert_eq!(location.statement_index, body[location.block].statements.len()); + let terminator = body[location.block].terminator(); + localize_terminator_constraint( + tcx, + body, + terminator, + liveness, + &outlives_constraint, + point, + universal_regions, + ) + }; + localized_outlives_constraints.push(LocalizedOutlivesConstraint { + source: outlives_constraint.sup, + from, + target: outlives_constraint.sub, + to, + }); + } + } + } +} + +/// For a given outlives constraint arising from a MIR statement, computes the CFG `from`-`to` +/// intra-block nodes to localize the constraint. +fn localize_statement_constraint<'tcx>( + tcx: TyCtxt<'tcx>, + body: &Body<'tcx>, + stmt: &Statement<'tcx>, + liveness: &LivenessValues, + outlives_constraint: &OutlivesConstraint<'tcx>, + current_location: Location, + current_point: PointIndex, + universal_regions: &UniversalRegions<'tcx>, +) -> (PointIndex, PointIndex) { + match &stmt.kind { + StatementKind::Assign(box (lhs, rhs)) => { + // To create localized outlives constraints without midpoints, we rely on the property + // that no input regions from the RHS of the assignment will flow into themselves: they + // should not appear in the output regions in the LHS. We believe this to be true by + // construction of the MIR, via temporaries, and assert it here. + // + // We think we don't need midpoints because: + // - every LHS Place has a unique set of regions that don't appear elsewhere + // - this implies that for them to be part of the RHS, the same Place must be read and + // written + // - and that should be impossible in MIR + // + // When we have a more complete implementation in the future, tested with crater, etc, + // we can relax this to a debug assert instead, or remove it. + assert!( + { + let mut lhs_regions = FxHashSet::default(); + tcx.for_each_free_region(lhs, |region| { + let region = universal_regions.to_region_vid(region); + lhs_regions.insert(region); + }); + + let mut rhs_regions = FxHashSet::default(); + tcx.for_each_free_region(rhs, |region| { + let region = universal_regions.to_region_vid(region); + rhs_regions.insert(region); + }); + + // The intersection between LHS and RHS regions should be empty. + lhs_regions.is_disjoint(&rhs_regions) + }, + "there should be no common regions between the LHS and RHS of an assignment" + ); + + // As mentioned earlier, we should be tracking these better upstream but: we want to + // relate the types on entry to the type of the place on exit. That is, outlives + // constraints on the RHS are on entry, and outlives constraints to/from the LHS are on + // exit (i.e. on entry to the successor location). + let lhs_ty = body.local_decls[lhs.local].ty; + let successor_location = Location { + block: current_location.block, + statement_index: current_location.statement_index + 1, + }; + let successor_point = liveness.point_from_location(successor_location); + compute_constraint_direction( + tcx, + outlives_constraint, + &lhs_ty, + current_point, + successor_point, + universal_regions, + ) + } + _ => { + // For the other cases, we localize an outlives constraint to where it arises. + (current_point, current_point) } } } + +/// For a given outlives constraint arising from a MIR terminator, computes the CFG `from`-`to` +/// inter-block nodes to localize the constraint. +fn localize_terminator_constraint<'tcx>( + tcx: TyCtxt<'tcx>, + body: &Body<'tcx>, + terminator: &Terminator<'tcx>, + liveness: &LivenessValues, + outlives_constraint: &OutlivesConstraint<'tcx>, + current_point: PointIndex, + universal_regions: &UniversalRegions<'tcx>, +) -> (PointIndex, PointIndex) { + // FIXME: check if other terminators need the same handling as `Call`s, in particular + // Assert/Yield/Drop. A handful of tests are failing with Drop related issues, as well as some + // coroutine tests, and that may be why. + match &terminator.kind { + // FIXME: also handle diverging calls. + TerminatorKind::Call { destination, target: Some(target), .. } => { + // Calls are similar to assignments, and thus follow the same pattern. If there is a + // target for the call we also relate what flows into the destination here to entry to + // that successor. + let destination_ty = destination.ty(&body.local_decls, tcx); + let successor_location = Location { block: *target, statement_index: 0 }; + let successor_point = liveness.point_from_location(successor_location); + compute_constraint_direction( + tcx, + outlives_constraint, + &destination_ty, + current_point, + successor_point, + universal_regions, + ) + } + _ => { + // Typeck constraints guide loans between regions at the current point, so we do that in + // the general case, and liveness will take care of making them flow to the terminator's + // successors. + (current_point, current_point) + } + } +} + +/// For a given constraint, returns the `from`-`to` edge according to whether the constraint flows +/// to or from a free region in the given `value`, some kind of result for an effectful operation, +/// like the LHS of an assignment. +fn compute_constraint_direction<'tcx>( + tcx: TyCtxt<'tcx>, + outlives_constraint: &OutlivesConstraint<'tcx>, + value: &impl TypeVisitable>, + current_point: PointIndex, + successor_point: PointIndex, + universal_regions: &UniversalRegions<'tcx>, +) -> (PointIndex, PointIndex) { + let mut to = current_point; + let mut from = current_point; + tcx.for_each_free_region(value, |region| { + let region = universal_regions.to_region_vid(region); + if region == outlives_constraint.sub { + // This constraint flows into the result, its effects start becoming visible on exit. + to = successor_point; + } else if region == outlives_constraint.sup { + // This constraint flows from the result, its effects start becoming visible on exit. + from = successor_point; + } + }); + + (from, to) +} From 56e7575ddd00ad4754493c66891810bf9095cd65 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?R=C3=A9my=20Rakic?= Date: Mon, 30 Dec 2024 11:05:15 +0000 Subject: [PATCH 04/13] move `find_assignments` to its only use site this is to remove the entire `util` module --- .../src/diagnostics/mutability_errors.rs | 36 +++++++++++++++++-- 1 file changed, 34 insertions(+), 2 deletions(-) diff --git a/compiler/rustc_borrowck/src/diagnostics/mutability_errors.rs b/compiler/rustc_borrowck/src/diagnostics/mutability_errors.rs index c690789b587f6..ad887b7e5eef2 100644 --- a/compiler/rustc_borrowck/src/diagnostics/mutability_errors.rs +++ b/compiler/rustc_borrowck/src/diagnostics/mutability_errors.rs @@ -10,6 +10,7 @@ use rustc_hir::intravisit::Visitor; use rustc_hir::{self as hir, BindingMode, ByRef, Node}; use rustc_middle::bug; use rustc_middle::hir::place::PlaceBase; +use rustc_middle::mir::visit::PlaceContext; use rustc_middle::mir::{ self, BindingForm, Local, LocalDecl, LocalInfo, LocalKind, Location, Mutability, Place, PlaceRef, ProjectionElem, @@ -22,7 +23,6 @@ use rustc_trait_selection::traits; use tracing::debug; use crate::diagnostics::BorrowedContentSource; -use crate::util::FindAssignments; use crate::{MirBorrowckCtxt, session_diagnostics}; #[derive(Copy, Clone, Debug, Eq, PartialEq)] @@ -1084,6 +1084,38 @@ impl<'infcx, 'tcx> MirBorrowckCtxt<'_, 'infcx, 'tcx> { } } + /// Finds all statements that assign directly to local (i.e., X = ...) and returns their + /// locations. + fn find_assignments(&self, local: Local) -> Vec { + use rustc_middle::mir::visit::Visitor; + + struct FindLocalAssignmentVisitor { + needle: Local, + locations: Vec, + } + + impl<'tcx> Visitor<'tcx> for FindLocalAssignmentVisitor { + fn visit_local( + &mut self, + local: Local, + place_context: PlaceContext, + location: Location, + ) { + if self.needle != local { + return; + } + + if place_context.is_place_assignment() { + self.locations.push(location); + } + } + } + + let mut visitor = FindLocalAssignmentVisitor { needle: local, locations: vec![] }; + visitor.visit_body(self.body); + visitor.locations + } + fn suggest_make_local_mut(&self, err: &mut Diag<'_>, local: Local, name: Symbol) { let local_decl = &self.body.local_decls[local]; @@ -1117,7 +1149,7 @@ impl<'infcx, 'tcx> MirBorrowckCtxt<'_, 'infcx, 'tcx> { })) => { // check if the RHS is from desugaring let opt_assignment_rhs_span = - self.body.find_assignments(local).first().map(|&location| { + self.find_assignments(local).first().map(|&location| { if let Some(mir::Statement { source_info: _, kind: From ff1aaa52ff5deadcb94995978b894aba3b7c8a37 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?R=C3=A9my=20Rakic?= Date: Mon, 30 Dec 2024 11:06:54 +0000 Subject: [PATCH 05/13] remove empty `util` module --- compiler/rustc_borrowck/src/lib.rs | 1 - .../rustc_borrowck/src/util/collect_writes.rs | 35 ------------------- compiler/rustc_borrowck/src/util/mod.rs | 3 -- 3 files changed, 39 deletions(-) delete mode 100644 compiler/rustc_borrowck/src/util/collect_writes.rs delete mode 100644 compiler/rustc_borrowck/src/util/mod.rs diff --git a/compiler/rustc_borrowck/src/lib.rs b/compiler/rustc_borrowck/src/lib.rs index b061a450c83f7..61934eba8467b 100644 --- a/compiler/rustc_borrowck/src/lib.rs +++ b/compiler/rustc_borrowck/src/lib.rs @@ -81,7 +81,6 @@ mod session_diagnostics; mod type_check; mod universal_regions; mod used_muts; -mod util; /// A public API provided for the Rust compiler consumers. pub mod consumers; diff --git a/compiler/rustc_borrowck/src/util/collect_writes.rs b/compiler/rustc_borrowck/src/util/collect_writes.rs deleted file mode 100644 index 55f1073176aef..0000000000000 --- a/compiler/rustc_borrowck/src/util/collect_writes.rs +++ /dev/null @@ -1,35 +0,0 @@ -use rustc_middle::mir::visit::{PlaceContext, Visitor}; -use rustc_middle::mir::{Body, Local, Location}; - -pub(crate) trait FindAssignments { - // Finds all statements that assign directly to local (i.e., X = ...) - // and returns their locations. - fn find_assignments(&self, local: Local) -> Vec; -} - -impl<'tcx> FindAssignments for Body<'tcx> { - fn find_assignments(&self, local: Local) -> Vec { - let mut visitor = FindLocalAssignmentVisitor { needle: local, locations: vec![] }; - visitor.visit_body(self); - visitor.locations - } -} - -// The Visitor walks the MIR to return the assignment statements corresponding -// to a Local. -struct FindLocalAssignmentVisitor { - needle: Local, - locations: Vec, -} - -impl<'tcx> Visitor<'tcx> for FindLocalAssignmentVisitor { - fn visit_local(&mut self, local: Local, place_context: PlaceContext, location: Location) { - if self.needle != local { - return; - } - - if place_context.is_place_assignment() { - self.locations.push(location); - } - } -} diff --git a/compiler/rustc_borrowck/src/util/mod.rs b/compiler/rustc_borrowck/src/util/mod.rs deleted file mode 100644 index 5f2960b768b29..0000000000000 --- a/compiler/rustc_borrowck/src/util/mod.rs +++ /dev/null @@ -1,3 +0,0 @@ -mod collect_writes; - -pub(crate) use collect_writes::FindAssignments; From 79d761d93c57ac8cc01ae053770f86752402b445 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?R=C3=A9my=20Rakic?= Date: Mon, 30 Dec 2024 11:12:53 +0000 Subject: [PATCH 06/13] remove `allow_two_phase_borrow` it's been simplified over the years, but now it's no longer useful. - document its replacement in `BorrowKind` - use that everywhere instead --- compiler/rustc_borrowck/src/borrow_set.rs | 3 +-- compiler/rustc_borrowck/src/lib.rs | 4 ++-- compiler/rustc_borrowck/src/path_utils.rs | 9 +-------- .../src/polonius/legacy/loan_invalidations.rs | 4 ++-- compiler/rustc_middle/src/mir/statement.rs | 2 ++ 5 files changed, 8 insertions(+), 14 deletions(-) diff --git a/compiler/rustc_borrowck/src/borrow_set.rs b/compiler/rustc_borrowck/src/borrow_set.rs index ff838fbbb8868..a29833464fb86 100644 --- a/compiler/rustc_borrowck/src/borrow_set.rs +++ b/compiler/rustc_borrowck/src/borrow_set.rs @@ -11,7 +11,6 @@ use rustc_mir_dataflow::move_paths::MoveData; use tracing::debug; use crate::BorrowIndex; -use crate::path_utils::allow_two_phase_borrow; use crate::place_ext::PlaceExt; pub struct BorrowSet<'tcx> { @@ -350,7 +349,7 @@ impl<'a, 'tcx> GatherBorrows<'a, 'tcx> { start_location, assigned_place, borrow_index, ); - if !allow_two_phase_borrow(kind) { + if !kind.allows_two_phase_borrow() { debug!(" -> {:?}", start_location); return; } diff --git a/compiler/rustc_borrowck/src/lib.rs b/compiler/rustc_borrowck/src/lib.rs index 61934eba8467b..3a81c2660b13e 100644 --- a/compiler/rustc_borrowck/src/lib.rs +++ b/compiler/rustc_borrowck/src/lib.rs @@ -1076,7 +1076,7 @@ impl<'a, 'tcx> MirBorrowckCtxt<'a, '_, 'tcx> { (Read(kind), BorrowKind::Mut { .. }) => { // Reading from mere reservations of mutable-borrows is OK. if !is_active(this.dominators(), borrow, location) { - assert!(allow_two_phase_borrow(borrow.kind)); + assert!(borrow.kind.allows_two_phase_borrow()); return Control::Continue; } @@ -1184,7 +1184,7 @@ impl<'a, 'tcx> MirBorrowckCtxt<'a, '_, 'tcx> { } BorrowKind::Mut { .. } => { let wk = WriteKind::MutableBorrow(bk); - if allow_two_phase_borrow(bk) { + if bk.allows_two_phase_borrow() { (Deep, Reservation(wk)) } else { (Deep, Write(wk)) diff --git a/compiler/rustc_borrowck/src/path_utils.rs b/compiler/rustc_borrowck/src/path_utils.rs index 12a37f56fcf96..257ff1fb3cded 100644 --- a/compiler/rustc_borrowck/src/path_utils.rs +++ b/compiler/rustc_borrowck/src/path_utils.rs @@ -1,19 +1,12 @@ use rustc_abi::FieldIdx; use rustc_data_structures::graph::dominators::Dominators; -use rustc_middle::mir::{BasicBlock, Body, BorrowKind, Location, Place, PlaceRef, ProjectionElem}; +use rustc_middle::mir::{BasicBlock, Body, Location, Place, PlaceRef, ProjectionElem}; use rustc_middle::ty::TyCtxt; use tracing::debug; use crate::borrow_set::{BorrowData, BorrowSet, TwoPhaseActivation}; use crate::{AccessDepth, BorrowIndex, places_conflict}; -/// Returns `true` if the borrow represented by `kind` is -/// allowed to be split into separate Reservation and -/// Activation phases. -pub(super) fn allow_two_phase_borrow(kind: BorrowKind) -> bool { - kind.allows_two_phase_borrow() -} - /// Control for the path borrow checking code #[derive(Copy, Clone, PartialEq, Eq, Debug)] pub(super) enum Control { diff --git a/compiler/rustc_borrowck/src/polonius/legacy/loan_invalidations.rs b/compiler/rustc_borrowck/src/polonius/legacy/loan_invalidations.rs index bb6d593d0d88e..1602f8cbd6175 100644 --- a/compiler/rustc_borrowck/src/polonius/legacy/loan_invalidations.rs +++ b/compiler/rustc_borrowck/src/polonius/legacy/loan_invalidations.rs @@ -260,7 +260,7 @@ impl<'a, 'tcx> LoanInvalidationsGenerator<'a, 'tcx> { } BorrowKind::Mut { .. } => { let wk = WriteKind::MutableBorrow(bk); - if allow_two_phase_borrow(bk) { + if bk.allows_two_phase_borrow() { (Deep, Reservation(wk)) } else { (Deep, Write(wk)) @@ -378,7 +378,7 @@ impl<'a, 'tcx> LoanInvalidationsGenerator<'a, 'tcx> { // Reading from mere reservations of mutable-borrows is OK. if !is_active(this.dominators, borrow, location) { // If the borrow isn't active yet, reads don't invalidate it - assert!(allow_two_phase_borrow(borrow.kind)); + assert!(borrow.kind.allows_two_phase_borrow()); return Control::Continue; } diff --git a/compiler/rustc_middle/src/mir/statement.rs b/compiler/rustc_middle/src/mir/statement.rs index da3fa9e324a4d..470a247d794ec 100644 --- a/compiler/rustc_middle/src/mir/statement.rs +++ b/compiler/rustc_middle/src/mir/statement.rs @@ -455,6 +455,8 @@ impl BorrowKind { } } + /// Returns whether borrows represented by this kind are allowed to be split into separate + /// Reservation and Activation phases. pub fn allows_two_phase_borrow(&self) -> bool { match *self { BorrowKind::Shared From 9d444c26c9e3cac3ceea14a6da1bc1d27d7075a0 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?R=C3=A9my=20Rakic?= Date: Mon, 30 Dec 2024 11:27:24 +0000 Subject: [PATCH 07/13] remove borrowck duplicate of `std::ops::ControlFlow` --- compiler/rustc_borrowck/src/lib.rs | 16 ++++++++-------- compiler/rustc_borrowck/src/path_utils.rs | 13 ++++--------- .../src/polonius/legacy/loan_invalidations.rs | 6 ++++-- 3 files changed, 16 insertions(+), 19 deletions(-) diff --git a/compiler/rustc_borrowck/src/lib.rs b/compiler/rustc_borrowck/src/lib.rs index 3a81c2660b13e..c97c3f3f87035 100644 --- a/compiler/rustc_borrowck/src/lib.rs +++ b/compiler/rustc_borrowck/src/lib.rs @@ -17,7 +17,7 @@ use std::cell::RefCell; use std::marker::PhantomData; -use std::ops::Deref; +use std::ops::{ControlFlow, Deref}; use rustc_abi::FieldIdx; use rustc_data_structures::fx::{FxIndexMap, FxIndexSet}; @@ -1053,31 +1053,31 @@ impl<'a, 'tcx> MirBorrowckCtxt<'a, '_, 'tcx> { rw, (borrow_index, borrow), ); - Control::Continue + ControlFlow::Continue(()) } (Read(_), BorrowKind::Shared | BorrowKind::Fake(_)) | ( Read(ReadKind::Borrow(BorrowKind::Fake(FakeBorrowKind::Shallow))), BorrowKind::Mut { .. }, - ) => Control::Continue, + ) => ControlFlow::Continue(()), (Reservation(_), BorrowKind::Fake(_) | BorrowKind::Shared) => { // This used to be a future compatibility warning (to be // disallowed on NLL). See rust-lang/rust#56254 - Control::Continue + ControlFlow::Continue(()) } (Write(WriteKind::Move), BorrowKind::Fake(FakeBorrowKind::Shallow)) => { // Handled by initialization checks. - Control::Continue + ControlFlow::Continue(()) } (Read(kind), BorrowKind::Mut { .. }) => { // Reading from mere reservations of mutable-borrows is OK. if !is_active(this.dominators(), borrow, location) { assert!(borrow.kind.allows_two_phase_borrow()); - return Control::Continue; + return ControlFlow::Continue(()); } error_reported = true; @@ -1093,7 +1093,7 @@ impl<'a, 'tcx> MirBorrowckCtxt<'a, '_, 'tcx> { this.buffer_error(err); } } - Control::Break + ControlFlow::Break(()) } (Reservation(kind) | Activation(kind, _) | Write(kind), _) => { @@ -1140,7 +1140,7 @@ impl<'a, 'tcx> MirBorrowckCtxt<'a, '_, 'tcx> { this.report_illegal_mutation_of_borrowed(location, place_span, borrow) } } - Control::Break + ControlFlow::Break(()) } }, ); diff --git a/compiler/rustc_borrowck/src/path_utils.rs b/compiler/rustc_borrowck/src/path_utils.rs index 257ff1fb3cded..2c94a32d369ce 100644 --- a/compiler/rustc_borrowck/src/path_utils.rs +++ b/compiler/rustc_borrowck/src/path_utils.rs @@ -1,3 +1,5 @@ +use std::ops::ControlFlow; + use rustc_abi::FieldIdx; use rustc_data_structures::graph::dominators::Dominators; use rustc_middle::mir::{BasicBlock, Body, Location, Place, PlaceRef, ProjectionElem}; @@ -7,13 +9,6 @@ use tracing::debug; use crate::borrow_set::{BorrowData, BorrowSet, TwoPhaseActivation}; use crate::{AccessDepth, BorrowIndex, places_conflict}; -/// Control for the path borrow checking code -#[derive(Copy, Clone, PartialEq, Eq, Debug)] -pub(super) enum Control { - Continue, - Break, -} - /// Encapsulates the idea of iterating over every borrow that involves a particular path pub(super) fn each_borrow_involving_path<'tcx, F, I, S>( s: &mut S, @@ -24,7 +19,7 @@ pub(super) fn each_borrow_involving_path<'tcx, F, I, S>( is_candidate: I, mut op: F, ) where - F: FnMut(&mut S, BorrowIndex, &BorrowData<'tcx>) -> Control, + F: FnMut(&mut S, BorrowIndex, &BorrowData<'tcx>) -> ControlFlow<()>, I: Fn(BorrowIndex) -> bool, { let (access, place) = access_place; @@ -55,7 +50,7 @@ pub(super) fn each_borrow_involving_path<'tcx, F, I, S>( i, borrowed, place, access ); let ctrl = op(s, i, borrowed); - if ctrl == Control::Break { + if matches!(ctrl, ControlFlow::Break(_)) { return; } } diff --git a/compiler/rustc_borrowck/src/polonius/legacy/loan_invalidations.rs b/compiler/rustc_borrowck/src/polonius/legacy/loan_invalidations.rs index 1602f8cbd6175..3c3b93cdc0d3b 100644 --- a/compiler/rustc_borrowck/src/polonius/legacy/loan_invalidations.rs +++ b/compiler/rustc_borrowck/src/polonius/legacy/loan_invalidations.rs @@ -1,3 +1,5 @@ +use std::ops::ControlFlow; + use rustc_data_structures::graph::dominators::Dominators; use rustc_middle::bug; use rustc_middle::mir::visit::Visitor; @@ -379,7 +381,7 @@ impl<'a, 'tcx> LoanInvalidationsGenerator<'a, 'tcx> { if !is_active(this.dominators, borrow, location) { // If the borrow isn't active yet, reads don't invalidate it assert!(borrow.kind.allows_two_phase_borrow()); - return Control::Continue; + return ControlFlow::Continue(()); } // Unique and mutable borrows are invalidated by reads from any @@ -395,7 +397,7 @@ impl<'a, 'tcx> LoanInvalidationsGenerator<'a, 'tcx> { this.emit_loan_invalidated_at(borrow_index, location); } } - Control::Continue + ControlFlow::Continue(()) }, ); } From 3af8dc4744fc0ccc4b895e6ae1ff8f464d9a6c6a Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E8=AE=B8=E6=9D=B0=E5=8F=8B=20Jieyou=20Xu=20=28Joe=29?= <39484203+jieyouxu@users.noreply.github.com> Date: Thu, 2 Jan 2025 23:42:45 +0800 Subject: [PATCH 08/13] triagebot: register `relnotes-interest-group` ping group --- triagebot.toml | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/triagebot.toml b/triagebot.toml index 5660eb999b789..e9ebb6b52189d 100644 --- a/triagebot.toml +++ b/triagebot.toml @@ -172,6 +172,12 @@ issues). """ label = "O-emscripten" +[ping.relnotes-interest-group] +message = """\ +Hi relnotes-interest-group, this PR adds release notes. Could you review this PR +if you have time? Thanks <3 +""" + [prioritize] label = "I-prioritize" From fc7ee238d1f6d365e9a51b22e734c181c1723c01 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?R=C3=A9my=20Rakic?= Date: Mon, 6 Jan 2025 14:20:54 +0000 Subject: [PATCH 09/13] address review comments push constraint creation to where the statement/terminator info is gathered --- .../src/polonius/typeck_constraints.rs | 52 +++++++++++-------- 1 file changed, 31 insertions(+), 21 deletions(-) diff --git a/compiler/rustc_borrowck/src/polonius/typeck_constraints.rs b/compiler/rustc_borrowck/src/polonius/typeck_constraints.rs index c04661fbbc1a9..8235b844886e0 100644 --- a/compiler/rustc_borrowck/src/polonius/typeck_constraints.rs +++ b/compiler/rustc_borrowck/src/polonius/typeck_constraints.rs @@ -52,7 +52,7 @@ pub(super) fn convert_typeck_constraints<'tcx>( // this information better in MIR typeck instead, for example with a new `Locations` // variant that contains which node is crossing over between entry and exit. let point = liveness.point_from_location(location); - let (from, to) = if let Some(stmt) = + let localized_constraint = if let Some(stmt) = body[location.block].statements.get(location.statement_index) { localize_statement_constraint( @@ -78,19 +78,14 @@ pub(super) fn convert_typeck_constraints<'tcx>( universal_regions, ) }; - localized_outlives_constraints.push(LocalizedOutlivesConstraint { - source: outlives_constraint.sup, - from, - target: outlives_constraint.sub, - to, - }); + localized_outlives_constraints.push(localized_constraint); } } } } -/// For a given outlives constraint arising from a MIR statement, computes the CFG `from`-`to` -/// intra-block nodes to localize the constraint. +/// For a given outlives constraint arising from a MIR statement, localize the constraint with the +/// needed CFG `from`-`to` intra-block nodes. fn localize_statement_constraint<'tcx>( tcx: TyCtxt<'tcx>, body: &Body<'tcx>, @@ -100,7 +95,7 @@ fn localize_statement_constraint<'tcx>( current_location: Location, current_point: PointIndex, universal_regions: &UniversalRegions<'tcx>, -) -> (PointIndex, PointIndex) { +) -> LocalizedOutlivesConstraint { match &stmt.kind { StatementKind::Assign(box (lhs, rhs)) => { // To create localized outlives constraints without midpoints, we rely on the property @@ -157,13 +152,18 @@ fn localize_statement_constraint<'tcx>( } _ => { // For the other cases, we localize an outlives constraint to where it arises. - (current_point, current_point) + LocalizedOutlivesConstraint { + source: outlives_constraint.sup, + from: current_point, + target: outlives_constraint.sub, + to: current_point, + } } } } -/// For a given outlives constraint arising from a MIR terminator, computes the CFG `from`-`to` -/// inter-block nodes to localize the constraint. +/// For a given outlives constraint arising from a MIR terminator, localize the constraint with the +/// needed CFG `from`-`to` inter-block nodes. fn localize_terminator_constraint<'tcx>( tcx: TyCtxt<'tcx>, body: &Body<'tcx>, @@ -172,7 +172,7 @@ fn localize_terminator_constraint<'tcx>( outlives_constraint: &OutlivesConstraint<'tcx>, current_point: PointIndex, universal_regions: &UniversalRegions<'tcx>, -) -> (PointIndex, PointIndex) { +) -> LocalizedOutlivesConstraint { // FIXME: check if other terminators need the same handling as `Call`s, in particular // Assert/Yield/Drop. A handful of tests are failing with Drop related issues, as well as some // coroutine tests, and that may be why. @@ -198,14 +198,19 @@ fn localize_terminator_constraint<'tcx>( // Typeck constraints guide loans between regions at the current point, so we do that in // the general case, and liveness will take care of making them flow to the terminator's // successors. - (current_point, current_point) + LocalizedOutlivesConstraint { + source: outlives_constraint.sup, + from: current_point, + target: outlives_constraint.sub, + to: current_point, + } } } } - -/// For a given constraint, returns the `from`-`to` edge according to whether the constraint flows -/// to or from a free region in the given `value`, some kind of result for an effectful operation, -/// like the LHS of an assignment. +/// For a given outlives constraint and CFG edge, returns the localized constraint with the +/// appropriate `from`-`to` direction. This is computed according to whether the constraint flows to +/// or from a free region in the given `value`, some kind of result for an effectful operation, like +/// the LHS of an assignment. fn compute_constraint_direction<'tcx>( tcx: TyCtxt<'tcx>, outlives_constraint: &OutlivesConstraint<'tcx>, @@ -213,7 +218,7 @@ fn compute_constraint_direction<'tcx>( current_point: PointIndex, successor_point: PointIndex, universal_regions: &UniversalRegions<'tcx>, -) -> (PointIndex, PointIndex) { +) -> LocalizedOutlivesConstraint { let mut to = current_point; let mut from = current_point; tcx.for_each_free_region(value, |region| { @@ -227,5 +232,10 @@ fn compute_constraint_direction<'tcx>( } }); - (from, to) + LocalizedOutlivesConstraint { + source: outlives_constraint.sup, + from, + target: outlives_constraint.sub, + to, + } } From 85a71ea0c781920a25cc5945f21f72c40334cc77 Mon Sep 17 00:00:00 2001 From: Kornel Date: Mon, 6 Jan 2025 23:39:53 +0000 Subject: [PATCH 10/13] More compelling env_clear() examples --- library/std/src/process.rs | 22 +++++++++++++++------- 1 file changed, 15 insertions(+), 7 deletions(-) diff --git a/library/std/src/process.rs b/library/std/src/process.rs index 929d2b57afe5c..c87d4d01f2950 100644 --- a/library/std/src/process.rs +++ b/library/std/src/process.rs @@ -868,13 +868,17 @@ impl Command { /// /// # Examples /// + /// Prevent any inherited `GIT_DIR` variable from changing the target of the `git` command, + /// while allowing all other variables, like `GIT_AUTHOR_NAME`. + /// /// ```no_run /// use std::process::Command; /// - /// Command::new("ls") - /// .env_remove("PATH") - /// .spawn() - /// .expect("ls command failed to start"); + /// Command::new("git") + /// .arg("commit") + /// .env_remove("GIT_DIR") + /// .spawn()?; + /// # std::io::Result::Ok(()) /// ``` #[stable(feature = "process", since = "1.0.0")] pub fn env_remove>(&mut self, key: K) -> &mut Command { @@ -896,13 +900,17 @@ impl Command { /// /// # Examples /// + /// The behavior of `sort` is affected by `LANG` and `LC_*` environment variables. + /// Clearing the environment makes `sort`'s behavior independent of the parent processes' language. + /// /// ```no_run /// use std::process::Command; /// - /// Command::new("ls") + /// Command::new("sort") + /// .arg("file.txt") /// .env_clear() - /// .spawn() - /// .expect("ls command failed to start"); + /// .spawn()?; + /// # std::io::Result::Ok(()) /// ``` #[stable(feature = "process", since = "1.0.0")] pub fn env_clear(&mut self) -> &mut Command { From af15e048b209e98d8dfc5122129b49cd40524a0a Mon Sep 17 00:00:00 2001 From: B I Mohammed Abbas Date: Tue, 7 Jan 2025 09:18:31 +0530 Subject: [PATCH 11/13] Reserve x18 register for aarch64 wrs vxworks target --- compiler/rustc_target/src/spec/targets/aarch64_wrs_vxworks.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/compiler/rustc_target/src/spec/targets/aarch64_wrs_vxworks.rs b/compiler/rustc_target/src/spec/targets/aarch64_wrs_vxworks.rs index d5e78d0307606..ac53cbaecceb1 100644 --- a/compiler/rustc_target/src/spec/targets/aarch64_wrs_vxworks.rs +++ b/compiler/rustc_target/src/spec/targets/aarch64_wrs_vxworks.rs @@ -13,7 +13,7 @@ pub(crate) fn target() -> Target { data_layout: "e-m:e-p270:32:32-p271:32:32-p272:64:64-i8:8:32-i16:16:32-i64:64-i128:128-n32:64-S128-Fn32".into(), arch: "aarch64".into(), options: TargetOptions { - features: "+v8a".into(), + features: "+v8a,+reserve-x18".into(), max_atomic_width: Some(128), stack_probes: StackProbeType::Inline, ..base::vxworks::opts() From 427abb69bf4c788504fa454fa03559e815c682df Mon Sep 17 00:00:00 2001 From: Ralf Jung Date: Tue, 7 Jan 2025 15:38:44 +0100 Subject: [PATCH 12/13] arm: add unstable soft-float target feature --- compiler/rustc_target/src/target_features.rs | 8 ++++++++ tests/ui/check-cfg/target_feature.stderr | 1 + 2 files changed, 9 insertions(+) diff --git a/compiler/rustc_target/src/target_features.rs b/compiler/rustc_target/src/target_features.rs index f594d20f9286f..9fd07c8634aa1 100644 --- a/compiler/rustc_target/src/target_features.rs +++ b/compiler/rustc_target/src/target_features.rs @@ -148,6 +148,11 @@ const ARM_FEATURES: &[(&str, Stability, ImpliedFeatures)] = &[ ("neon", Unstable(sym::arm_target_feature), &["vfp3"]), ("rclass", Unstable(sym::arm_target_feature), &[]), ("sha2", Unstable(sym::arm_target_feature), &["neon"]), + // This can be *disabled* on non-`hf` targets to enable the use + // of hardfloats while keeping the softfloat ABI. + // FIXME before stabilization: Should we expose this as a `hard-float` target feature instead of + // matching the odd negative feature LLVM uses? + ("soft-float", Unstable(sym::arm_target_feature), &[]), // This is needed for inline assembly, but shouldn't be stabilized as-is // since it should be enabled per-function using #[instruction_set], not // #[target_feature]. @@ -790,6 +795,9 @@ impl Target { match self.llvm_floatabi.unwrap() { FloatAbi::Soft => { // Nothing special required, will use soft-float ABI throughout. + // We can even allow `-soft-float` here; in fact that is useful as it lets + // people use FPU instructions with a softfloat ABI (corresponds to + // `-mfloat-abi=softfp` in GCC/clang). NOTHING } FloatAbi::Hard => { diff --git a/tests/ui/check-cfg/target_feature.stderr b/tests/ui/check-cfg/target_feature.stderr index 70fec8a350aa1..bf54d17f6ec8a 100644 --- a/tests/ui/check-cfg/target_feature.stderr +++ b/tests/ui/check-cfg/target_feature.stderr @@ -202,6 +202,7 @@ LL | cfg!(target_feature = "_UNEXPECTED_VALUE"); `sme-lutv2` `sme2` `sme2p1` +`soft-float` `spe` `ssbs` `sse` From b9d6e9e73ffb2eaba9242d14ef40ee2ec61584a0 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Matthias=20Kr=C3=BCger?= Date: Tue, 7 Jan 2025 21:36:37 +0100 Subject: [PATCH 13/13] warn about broken simd not only on structs but also enums and unions when we didn't opt in to it --- compiler/rustc_ast_passes/src/feature_gate.rs | 2 +- .../feature-gates/feature-gate-repr-simd.rs | 12 ++++- .../feature-gate-repr-simd.stderr | 44 +++++++++++++++++-- tests/ui/repr/issue-83505-repr-simd.rs | 2 + tests/ui/repr/issue-83505-repr-simd.stderr | 16 +++++-- 5 files changed, 67 insertions(+), 9 deletions(-) diff --git a/compiler/rustc_ast_passes/src/feature_gate.rs b/compiler/rustc_ast_passes/src/feature_gate.rs index 3fbf121018615..c8500098add1a 100644 --- a/compiler/rustc_ast_passes/src/feature_gate.rs +++ b/compiler/rustc_ast_passes/src/feature_gate.rs @@ -242,7 +242,7 @@ impl<'a> Visitor<'a> for PostExpansionVisitor<'a> { } } - ast::ItemKind::Struct(..) => { + ast::ItemKind::Struct(..) | ast::ItemKind::Enum(..) | ast::ItemKind::Union(..) => { for attr in attr::filter_by_name(&i.attrs, sym::repr) { for item in attr.meta_item_list().unwrap_or_else(ThinVec::new) { if item.has_name(sym::simd) { diff --git a/tests/ui/feature-gates/feature-gate-repr-simd.rs b/tests/ui/feature-gates/feature-gate-repr-simd.rs index 65ade97c7e1c3..091dc479ef3d4 100644 --- a/tests/ui/feature-gates/feature-gate-repr-simd.rs +++ b/tests/ui/feature-gates/feature-gate-repr-simd.rs @@ -1,9 +1,17 @@ -#[repr(simd)] //~ error: SIMD types are experimental +#[repr(simd)] //~ ERROR: SIMD types are experimental struct Foo([u64; 2]); #[repr(C)] //~ ERROR conflicting representation hints //~^ WARN this was previously accepted -#[repr(simd)] //~ error: SIMD types are experimental +#[repr(simd)] //~ ERROR: SIMD types are experimental struct Bar([u64; 2]); +#[repr(simd)] //~ ERROR: SIMD types are experimental +//~^ ERROR: attribute should be applied to a struct +union U {f: u32} + +#[repr(simd)] //~ ERROR: SIMD types are experimental +//~^ error: attribute should be applied to a struct +enum E { X } + fn main() {} diff --git a/tests/ui/feature-gates/feature-gate-repr-simd.stderr b/tests/ui/feature-gates/feature-gate-repr-simd.stderr index 5a0ceb2dd74fb..3bf8ec6170597 100644 --- a/tests/ui/feature-gates/feature-gate-repr-simd.stderr +++ b/tests/ui/feature-gates/feature-gate-repr-simd.stderr @@ -18,6 +18,26 @@ LL | #[repr(simd)] = help: add `#![feature(repr_simd)]` 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]: SIMD types are experimental and possibly buggy + --> $DIR/feature-gate-repr-simd.rs:9:1 + | +LL | #[repr(simd)] + | ^^^^^^^^^^^^^ + | + = note: see issue #27731 for more information + = help: add `#![feature(repr_simd)]` 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]: SIMD types are experimental and possibly buggy + --> $DIR/feature-gate-repr-simd.rs:13:1 + | +LL | #[repr(simd)] + | ^^^^^^^^^^^^^ + | + = note: see issue #27731 for more information + = help: add `#![feature(repr_simd)]` 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[E0566]: conflicting representation hints --> $DIR/feature-gate-repr-simd.rs:4:8 | @@ -31,10 +51,28 @@ LL | #[repr(simd)] = note: for more information, see issue #68585 = note: `#[deny(conflicting_repr_hints)]` on by default -error: aborting due to 3 previous errors +error[E0517]: attribute should be applied to a struct + --> $DIR/feature-gate-repr-simd.rs:9:8 + | +LL | #[repr(simd)] + | ^^^^ +LL | +LL | union U {f: u32} + | ---------------- not a struct + +error[E0517]: attribute should be applied to a struct + --> $DIR/feature-gate-repr-simd.rs:13:8 + | +LL | #[repr(simd)] + | ^^^^ +LL | +LL | enum E { X } + | ------------ not a struct + +error: aborting due to 7 previous errors -Some errors have detailed explanations: E0566, E0658. -For more information about an error, try `rustc --explain E0566`. +Some errors have detailed explanations: E0517, E0566, E0658. +For more information about an error, try `rustc --explain E0517`. Future incompatibility report: Future breakage diagnostic: error[E0566]: conflicting representation hints --> $DIR/feature-gate-repr-simd.rs:4:8 diff --git a/tests/ui/repr/issue-83505-repr-simd.rs b/tests/ui/repr/issue-83505-repr-simd.rs index 280b771d01539..bebbc636728fd 100644 --- a/tests/ui/repr/issue-83505-repr-simd.rs +++ b/tests/ui/repr/issue-83505-repr-simd.rs @@ -5,6 +5,8 @@ #[repr(simd)] //~^ ERROR: attribute should be applied to a struct [E0517] //~| ERROR: unsupported representation for zero-variant enum [E0084] +//~| ERROR: SIMD types are experimental and possibly buggy [E0658] + enum Es {} static CLs: Es; //~^ ERROR: free static item without body diff --git a/tests/ui/repr/issue-83505-repr-simd.stderr b/tests/ui/repr/issue-83505-repr-simd.stderr index df99baaf52293..44e154b4bb613 100644 --- a/tests/ui/repr/issue-83505-repr-simd.stderr +++ b/tests/ui/repr/issue-83505-repr-simd.stderr @@ -1,11 +1,21 @@ error: free static item without body - --> $DIR/issue-83505-repr-simd.rs:9:1 + --> $DIR/issue-83505-repr-simd.rs:11:1 | LL | static CLs: Es; | ^^^^^^^^^^^^^^- | | | help: provide a definition for the static: `= ;` +error[E0658]: SIMD types are experimental and possibly buggy + --> $DIR/issue-83505-repr-simd.rs:5:1 + | +LL | #[repr(simd)] + | ^^^^^^^^^^^^^ + | + = note: see issue #27731 for more information + = help: add `#![feature(repr_simd)]` 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[E0517]: attribute should be applied to a struct --> $DIR/issue-83505-repr-simd.rs:5:8 | @@ -24,7 +34,7 @@ LL | #[repr(simd)] LL | enum Es {} | ------- zero-variant enum -error: aborting due to 3 previous errors +error: aborting due to 4 previous errors -Some errors have detailed explanations: E0084, E0517. +Some errors have detailed explanations: E0084, E0517, E0658. For more information about an error, try `rustc --explain E0084`.