diff --git a/compiler/rustc_attr_parsing/src/attributes/unroll.rs b/compiler/rustc_attr_parsing/src/attributes/unroll.rs index 3438fc044ec55..5a49feca2a1ea 100644 --- a/compiler/rustc_attr_parsing/src/attributes/unroll.rs +++ b/compiler/rustc_attr_parsing/src/attributes/unroll.rs @@ -6,7 +6,8 @@ use super::prelude::*; pub(crate) struct UnrollParser; impl SingleAttributeParser for UnrollParser { - const PATH: &[Symbol] = &[sym::unroll]; + // FIXME(#159429): temporarily renamed to mitigate `#[unroll]` nameres ambiguity. + const PATH: &[Symbol] = &[sym::rustc_unroll]; const ALLOWED_TARGETS: AllowedTargets<'_> = AllowedTargets::AllowList(&[ Allow(Target::Loop), Allow(Target::ForLoop), diff --git a/compiler/rustc_borrowck/src/dataflow.rs b/compiler/rustc_borrowck/src/dataflow.rs index 5bf692eaa7205..5bfe5ee64f050 100644 --- a/compiler/rustc_borrowck/src/dataflow.rs +++ b/compiler/rustc_borrowck/src/dataflow.rs @@ -2,9 +2,7 @@ use std::fmt; use rustc_data_structures::fx::FxIndexMap; use rustc_index::bit_set::{DenseBitSet, MixedBitSet}; -use rustc_middle::mir::{ - self, BasicBlock, Body, CallReturnPlaces, Location, Place, TerminatorEdges, -}; +use rustc_middle::mir::{self, BasicBlock, Body, CallReturnPlaces, Location, Place}; use rustc_middle::ty::{RegionVid, TyCtxt}; use rustc_mir_dataflow::fmt::DebugWithContext; use rustc_mir_dataflow::impls::{ @@ -76,19 +74,15 @@ impl<'a, 'tcx> Analysis<'tcx> for Borrowck<'a, 'tcx> { self.ever_inits.apply_early_terminator_effect(&mut state.ever_inits, term, loc); } - fn apply_primary_terminator_effect<'mir>( + fn apply_primary_terminator_effect( &self, state: &mut Self::Domain, - term: &'mir mir::Terminator<'tcx>, + term: &mir::Terminator<'tcx>, loc: Location, - ) -> TerminatorEdges<'mir, 'tcx> { + ) { self.borrows.apply_primary_terminator_effect(&mut state.borrows, term, loc); self.uninits.apply_primary_terminator_effect(&mut state.uninits, term, loc); self.ever_inits.apply_primary_terminator_effect(&mut state.ever_inits, term, loc); - - // This return value doesn't matter. It's only used by `iterate_to_fixpoint`, which this - // analysis doesn't use. - TerminatorEdges::None } fn apply_call_return_effect( @@ -598,12 +592,12 @@ impl<'tcx> rustc_mir_dataflow::Analysis<'tcx> for Borrows<'_, 'tcx> { self.kill_loans_out_of_scope_at_location(state, location); } - fn apply_primary_terminator_effect<'mir>( + fn apply_primary_terminator_effect( &self, state: &mut Self::Domain, - terminator: &'mir mir::Terminator<'tcx>, + terminator: &mir::Terminator<'tcx>, _location: Location, - ) -> TerminatorEdges<'mir, 'tcx> { + ) { if let mir::TerminatorKind::InlineAsm { operands, .. } = &terminator.kind { for op in operands { if let mir::InlineAsmOperand::Out { place: Some(place), .. } @@ -613,7 +607,6 @@ impl<'tcx> rustc_mir_dataflow::Analysis<'tcx> for Borrows<'_, 'tcx> { } } } - terminator.edges() } } diff --git a/compiler/rustc_const_eval/src/check_consts/resolver.rs b/compiler/rustc_const_eval/src/check_consts/resolver.rs index a230f797b56fd..29b6e26d950d5 100644 --- a/compiler/rustc_const_eval/src/check_consts/resolver.rs +++ b/compiler/rustc_const_eval/src/check_consts/resolver.rs @@ -8,7 +8,7 @@ use std::marker::PhantomData; use rustc_index::bit_set::MixedBitSet; use rustc_middle::mir::visit::Visitor; use rustc_middle::mir::{ - self, BasicBlock, CallReturnPlaces, Local, Location, Statement, StatementKind, TerminatorEdges, + self, BasicBlock, CallReturnPlaces, Local, Location, Statement, StatementKind, }; use rustc_mir_dataflow::fmt::DebugWithContext; use rustc_mir_dataflow::{Analysis, JoinSemiLattice}; @@ -351,14 +351,13 @@ where self.transfer_function(state).visit_statement(statement, location); } - fn apply_primary_terminator_effect<'mir>( + fn apply_primary_terminator_effect( &self, state: &mut Self::Domain, - terminator: &'mir mir::Terminator<'tcx>, + terminator: &mir::Terminator<'tcx>, location: Location, - ) -> TerminatorEdges<'mir, 'tcx> { + ) { self.transfer_function(state).visit_terminator(terminator, location); - terminator.edges() } fn apply_call_return_effect( diff --git a/compiler/rustc_feature/src/builtin_attrs.rs b/compiler/rustc_feature/src/builtin_attrs.rs index 72b51ad204b9d..bc6f87a2a7f17 100644 --- a/compiler/rustc_feature/src/builtin_attrs.rs +++ b/compiler/rustc_feature/src/builtin_attrs.rs @@ -217,10 +217,12 @@ pub static BUILTIN_ATTRIBUTES: &[Symbol] = &[ // - https://github.com/rust-lang/rust/issues/153629 sym::rustc_splat, - // The `#[unroll]` attribute. + // The `#[rustc_unroll]` attribute. // // - https://github.com/rust-lang/rust/pull/156816 - sym::unroll, + // + // FIXME(#159429): temporarily renamed to mitigate `#[unroll]` nameres ambiguity + sym::rustc_unroll, // `#[instrument_fn = "on|off"]` to insert or inhibit instrumentation function // calls inside a function, usually around the prologue. diff --git a/compiler/rustc_hir/src/attrs/data_structures.rs b/compiler/rustc_hir/src/attrs/data_structures.rs index 530483e87329c..94241e6a31eb0 100644 --- a/compiler/rustc_hir/src/attrs/data_structures.rs +++ b/compiler/rustc_hir/src/attrs/data_structures.rs @@ -1706,7 +1706,8 @@ pub enum AttributeKind { limit: Limit, }, - /// Represents `#[unroll]` + /// Represents `#[rustc_unroll]` + // FIXME(#159429): temporarily renamed from `#[unroll]` to mitigate nameres ambiguity Unroll(UnrollAttr), /// Represents `#[unstable_feature_bound]`. diff --git a/compiler/rustc_mir_dataflow/src/framework/direction.rs b/compiler/rustc_mir_dataflow/src/framework/direction.rs index 68c8e03de8022..7b577c2b9df4c 100644 --- a/compiler/rustc_mir_dataflow/src/framework/direction.rs +++ b/compiler/rustc_mir_dataflow/src/framework/direction.rs @@ -194,7 +194,9 @@ impl Direction for Forward { let terminator = block_data.terminator(); let location = Location { block, statement_index: block_data.statements.len() }; analysis.apply_early_terminator_effect(state, terminator, location); - let edges = analysis.apply_primary_terminator_effect(state, terminator, location); + // Edges are obtained *before* calling `apply_primary_terminator_effect`. + let edges = analysis.get_terminator_edges(state, terminator, location); + analysis.apply_primary_terminator_effect(state, terminator, location); let exit_state = state; match edges { diff --git a/compiler/rustc_mir_dataflow/src/framework/mod.rs b/compiler/rustc_mir_dataflow/src/framework/mod.rs index 8f58846152747..b767ed6005346 100644 --- a/compiler/rustc_mir_dataflow/src/framework/mod.rs +++ b/compiler/rustc_mir_dataflow/src/framework/mod.rs @@ -196,19 +196,30 @@ pub trait Analysis<'tcx> { ) { } + /// Gets the terminator edges. Used by forward analyses only. Called *before* + /// `apply_primary_terminator_effect` is applied; this might seem strange but in practice + /// `MaybeInitializedPlaces` needs that ordering and other analyses work with either ordering. + fn get_terminator_edges<'mir>( + &self, + _state: &Self::Domain, + terminator: &'mir mir::Terminator<'tcx>, + _location: Location, + ) -> TerminatorEdges<'mir, 'tcx> { + terminator.edges() + } + /// Updates the current dataflow state with the effect of evaluating a terminator. /// /// The effect of a successful return from a `Call` terminator should **not** be accounted for /// in this function. That should go in `apply_call_return_effect`. For example, in the /// `InitializedPlaces` analyses, the return place for a function call is not marked as /// initialized here. - fn apply_primary_terminator_effect<'mir>( + fn apply_primary_terminator_effect( &self, _state: &mut Self::Domain, - terminator: &'mir mir::Terminator<'tcx>, + _terminator: &mir::Terminator<'tcx>, _location: Location, - ) -> TerminatorEdges<'mir, 'tcx> { - terminator.edges() + ) { } /* Edge-specific effects */ diff --git a/compiler/rustc_mir_dataflow/src/framework/tests.rs b/compiler/rustc_mir_dataflow/src/framework/tests.rs index 86ea3a34ae0ea..ee6330bfe1c2c 100644 --- a/compiler/rustc_mir_dataflow/src/framework/tests.rs +++ b/compiler/rustc_mir_dataflow/src/framework/tests.rs @@ -197,15 +197,14 @@ impl<'tcx, D: Direction> Analysis<'tcx> for MockAnalysis<'tcx, D> { assert!(state.insert(idx)); } - fn apply_primary_terminator_effect<'mir>( + fn apply_primary_terminator_effect( &self, state: &mut Self::Domain, - terminator: &'mir mir::Terminator<'tcx>, + _terminator: &mir::Terminator<'tcx>, location: Location, - ) -> TerminatorEdges<'mir, 'tcx> { + ) { let idx = self.effect(Effect::Primary.at_index(location.statement_index)); assert!(state.insert(idx)); - terminator.edges() } } diff --git a/compiler/rustc_mir_dataflow/src/impls/borrowed_locals.rs b/compiler/rustc_mir_dataflow/src/impls/borrowed_locals.rs index 9ec68f5260c05..c5b69c563b2fe 100644 --- a/compiler/rustc_mir_dataflow/src/impls/borrowed_locals.rs +++ b/compiler/rustc_mir_dataflow/src/impls/borrowed_locals.rs @@ -41,14 +41,13 @@ impl<'tcx> Analysis<'tcx> for MaybeBorrowedLocals { Self::transfer_function(state).visit_statement(statement, location); } - fn apply_primary_terminator_effect<'mir>( + fn apply_primary_terminator_effect( &self, state: &mut Self::Domain, - terminator: &'mir Terminator<'tcx>, + terminator: &Terminator<'tcx>, location: Location, - ) -> TerminatorEdges<'mir, 'tcx> { + ) { Self::transfer_function(state).visit_terminator(terminator, location); - terminator.edges() } } diff --git a/compiler/rustc_mir_dataflow/src/impls/initialized.rs b/compiler/rustc_mir_dataflow/src/impls/initialized.rs index 543c833326021..1b2c58c7e514c 100644 --- a/compiler/rustc_mir_dataflow/src/impls/initialized.rs +++ b/compiler/rustc_mir_dataflow/src/impls/initialized.rs @@ -391,14 +391,15 @@ impl<'tcx> Analysis<'tcx> for MaybeInitializedPlaces<'_, 'tcx> { } } - fn apply_primary_terminator_effect<'mir>( + fn get_terminator_edges<'mir>( &self, - state: &mut Self::Domain, + state: &Self::Domain, terminator: &'mir mir::Terminator<'tcx>, - location: Location, + _location: Location, ) -> TerminatorEdges<'mir, 'tcx> { - // Note: `edges` must be computed first because `drop_flag_effects_for_location` can change - // the result of `is_unwind_dead`. + // Note: this relies on `get_terminator_edges` being called before + // `apply_primary_terminator_effect` because the result of `is_unwind_dead` is affected by + // the `drop_flag_effects_for_location` in `apply_primary_terminator_effect`. let mut edges = terminator.edges(); if self.skip_unreachable_unwind && let mir::TerminatorKind::Drop { target, unwind, place, replace: _, drop: _ } = @@ -408,10 +409,18 @@ impl<'tcx> Analysis<'tcx> for MaybeInitializedPlaces<'_, 'tcx> { { edges = TerminatorEdges::Single(target); } + edges + } + + fn apply_primary_terminator_effect( + &self, + state: &mut Self::Domain, + _terminator: &mir::Terminator<'tcx>, + location: Location, + ) { drop_flag_effects_for_location(self.body, self.move_data, location, |path, s| { Self::update_bits(state, path, s) }); - edges } fn apply_call_return_effect( @@ -514,15 +523,12 @@ impl<'tcx> Analysis<'tcx> for MaybeUninitializedPlaces<'_, 'tcx> { // mutable borrow occurs. Places cannot become uninitialized through a mutable reference. } - fn apply_primary_terminator_effect<'mir>( + fn get_terminator_edges<'mir>( &self, - state: &mut Self::Domain, + _state: &Self::Domain, terminator: &'mir mir::Terminator<'tcx>, location: Location, ) -> TerminatorEdges<'mir, 'tcx> { - drop_flag_effects_for_location(self.body, self.move_data, location, |path, s| { - Self::update_bits(state, path, s) - }); if self.skip_unreachable_unwind.contains(location.block) { let mir::TerminatorKind::Drop { target, unwind, .. } = terminator.kind else { bug!() }; assert_matches!(unwind, mir::UnwindAction::Cleanup(_)); @@ -532,6 +538,17 @@ impl<'tcx> Analysis<'tcx> for MaybeUninitializedPlaces<'_, 'tcx> { } } + fn apply_primary_terminator_effect( + &self, + state: &mut Self::Domain, + _terminator: &mir::Terminator<'tcx>, + location: Location, + ) { + drop_flag_effects_for_location(self.body, self.move_data, location, |path, s| { + Self::update_bits(state, path, s) + }); + } + fn apply_call_return_effect( &self, state: &mut Self::Domain, @@ -633,13 +650,13 @@ impl<'tcx> Analysis<'tcx> for EverInitializedPlaces<'_, 'tcx> { } } - #[instrument(skip(self, state, terminator), level = "debug")] - fn apply_primary_terminator_effect<'mir>( + #[instrument(skip(self, state, _terminator), level = "debug")] + fn apply_primary_terminator_effect( &self, state: &mut Self::Domain, - terminator: &'mir mir::Terminator<'tcx>, + _terminator: &mir::Terminator<'tcx>, location: Location, - ) -> TerminatorEdges<'mir, 'tcx> { + ) { let move_data = self.move_data(); let init_loc_map = &move_data.init_loc_map; @@ -652,7 +669,6 @@ impl<'tcx> Analysis<'tcx> for EverInitializedPlaces<'_, 'tcx> { None } })); - terminator.edges() } fn apply_call_return_effect( diff --git a/compiler/rustc_mir_dataflow/src/impls/liveness.rs b/compiler/rustc_mir_dataflow/src/impls/liveness.rs index b690e86b747d5..da2ea948366db 100644 --- a/compiler/rustc_mir_dataflow/src/impls/liveness.rs +++ b/compiler/rustc_mir_dataflow/src/impls/liveness.rs @@ -1,8 +1,6 @@ use rustc_index::bit_set::DenseBitSet; use rustc_middle::mir::visit::{MutatingUseContext, NonMutatingUseContext, PlaceContext, Visitor}; -use rustc_middle::mir::{ - self, CallReturnPlaces, Local, Location, Place, StatementKind, TerminatorEdges, -}; +use rustc_middle::mir::{self, CallReturnPlaces, Local, Location, Place, StatementKind}; use crate::{Analysis, Backward, GenKill}; @@ -55,14 +53,13 @@ impl<'tcx> Analysis<'tcx> for MaybeLiveLocals { TransferFunction(state).visit_statement(statement, location); } - fn apply_primary_terminator_effect<'mir>( + fn apply_primary_terminator_effect( &self, state: &mut Self::Domain, - terminator: &'mir mir::Terminator<'tcx>, + terminator: &mir::Terminator<'tcx>, location: Location, - ) -> TerminatorEdges<'mir, 'tcx> { + ) { TransferFunction(state).visit_terminator(terminator, location); - terminator.edges() } fn apply_call_return_effect( @@ -301,14 +298,13 @@ impl<'a, 'tcx> Analysis<'tcx> for MaybeTransitiveLiveLocals<'a> { TransferFunction(state).visit_statement(statement, location); } - fn apply_primary_terminator_effect<'mir>( + fn apply_primary_terminator_effect( &self, state: &mut Self::Domain, - terminator: &'mir mir::Terminator<'tcx>, + terminator: &mir::Terminator<'tcx>, location: Location, - ) -> TerminatorEdges<'mir, 'tcx> { + ) { TransferFunction(state).visit_terminator(terminator, location); - terminator.edges() } fn apply_call_return_effect( diff --git a/compiler/rustc_mir_dataflow/src/impls/storage_liveness.rs b/compiler/rustc_mir_dataflow/src/impls/storage_liveness.rs index 494fb4098cfc1..558bf0a5603fa 100644 --- a/compiler/rustc_mir_dataflow/src/impls/storage_liveness.rs +++ b/compiler/rustc_mir_dataflow/src/impls/storage_liveness.rs @@ -295,12 +295,12 @@ impl<'tcx> Analysis<'tcx> for MaybeRequiresStorage { } } - fn apply_primary_terminator_effect<'t>( + fn apply_primary_terminator_effect( &self, state: &mut Self::Domain, - terminator: &'t Terminator<'tcx>, + terminator: &Terminator<'tcx>, loc: Location, - ) -> TerminatorEdges<'t, 'tcx> { + ) { match terminator.kind { // For call terminators the destination requires storage for the call // and after the call returns successfully, but not after a panic. @@ -333,7 +333,6 @@ impl<'tcx> Analysis<'tcx> for MaybeRequiresStorage { } self.check_for_move(state, loc); - terminator.edges() } fn apply_call_return_effect( diff --git a/compiler/rustc_mir_transform/src/dataflow_const_prop.rs b/compiler/rustc_mir_transform/src/dataflow_const_prop.rs index 7f2e5c05eb5d3..4e00bf1bf6559 100644 --- a/compiler/rustc_mir_transform/src/dataflow_const_prop.rs +++ b/compiler/rustc_mir_transform/src/dataflow_const_prop.rs @@ -122,19 +122,34 @@ impl<'tcx> Analysis<'tcx> for ConstAnalysis<'_, 'tcx> { } } - fn apply_primary_terminator_effect<'mir>( + fn get_terminator_edges<'mir>( &self, - state: &mut Self::Domain, + state: &Self::Domain, terminator: &'mir Terminator<'tcx>, _location: Location, ) -> TerminatorEdges<'mir, 'tcx> { if state.is_reachable() { - self.handle_terminator(terminator, state) + if let TerminatorKind::SwitchInt { discr, targets } = &terminator.kind { + self.get_switch_int_edges(discr, targets, state) + } else { + terminator.edges() + } } else { TerminatorEdges::None } } + fn apply_primary_terminator_effect( + &self, + state: &mut Self::Domain, + terminator: &Terminator<'tcx>, + _location: Location, + ) { + if state.is_reachable() { + self.handle_terminator(terminator, state) + } + } + fn apply_call_return_effect( &self, state: &mut Self::Domain, @@ -204,16 +219,10 @@ impl<'a, 'tcx> ConstAnalysis<'a, 'tcx> { } } - fn handle_operand( - &self, - operand: &Operand<'tcx>, - state: &mut State>, - ) -> ValueOrPlace> { + fn handle_operand(&self, operand: &Operand<'tcx>) -> ValueOrPlace> { match operand { Operand::RuntimeChecks(_) => ValueOrPlace::TOP, - Operand::Constant(constant) => { - ValueOrPlace::Value(self.handle_constant(constant, state)) - } + Operand::Constant(constant) => ValueOrPlace::Value(self.handle_constant(constant)), Operand::Copy(place) | Operand::Move(place) => { // On move, we would ideally flood the place with bottom. But with the current // framework this is not possible (similar to `InterpCx::eval_operand`). @@ -228,7 +237,7 @@ impl<'a, 'tcx> ConstAnalysis<'a, 'tcx> { &self, terminator: &'mir Terminator<'tcx>, state: &mut State>, - ) -> TerminatorEdges<'mir, 'tcx> { + ) { match &terminator.kind { TerminatorKind::Call { .. } | TerminatorKind::InlineAsm { .. } => { // Effect is applied by `handle_call_return`. @@ -240,14 +249,12 @@ impl<'a, 'tcx> ConstAnalysis<'a, 'tcx> { // They would have an effect, but are not allowed in this phase. bug!("encountered disallowed terminator"); } - TerminatorKind::SwitchInt { discr, targets } => { - return self.handle_switch_int(discr, targets, state); - } TerminatorKind::TailCall { .. } => { // FIXME(explicit_tail_calls): determine if we need to do something here (probably // not) } - TerminatorKind::Goto { .. } + TerminatorKind::SwitchInt { .. } + | TerminatorKind::Goto { .. } | TerminatorKind::UnwindResume | TerminatorKind::UnwindTerminate(_) | TerminatorKind::Return @@ -259,7 +266,6 @@ impl<'a, 'tcx> ConstAnalysis<'a, 'tcx> { // These terminators have no effect on the analysis. } } - terminator.edges() } fn handle_call_return( @@ -376,7 +382,7 @@ impl<'a, 'tcx> ConstAnalysis<'a, 'tcx> { operand, _, ) => { - let pointer = self.handle_operand(operand, state); + let pointer = self.handle_operand(operand); state.assign(target.as_ref(), pointer, &self.map); if let Some(target_len) = self.map.find_len(target.as_ref()) @@ -461,7 +467,7 @@ impl<'a, 'tcx> ConstAnalysis<'a, 'tcx> { } } Rvalue::Discriminant(place) => state.get_discr(place.as_ref(), &self.map), - Rvalue::Use(operand, _) => return self.handle_operand(operand, state), + Rvalue::Use(operand, _) => return self.handle_operand(operand), Rvalue::CopyForDeref(_) => bug!("`CopyForDeref` in runtime MIR"), Rvalue::Ref(..) | Rvalue::Reborrow(..) | Rvalue::RawPtr(..) => { // We don't track such places. @@ -480,24 +486,20 @@ impl<'a, 'tcx> ConstAnalysis<'a, 'tcx> { ValueOrPlace::Value(val) } - fn handle_constant( - &self, - constant: &ConstOperand<'tcx>, - _state: &mut State>, - ) -> FlatSet { + fn handle_constant(&self, constant: &ConstOperand<'tcx>) -> FlatSet { constant .const_ .try_eval_scalar(self.tcx, self.typing_env) .map_or(FlatSet::Top, FlatSet::Elem) } - fn handle_switch_int<'mir>( + fn get_switch_int_edges<'mir>( &self, discr: &'mir Operand<'tcx>, targets: &'mir SwitchTargets, - state: &mut State>, + state: &State>, ) -> TerminatorEdges<'mir, 'tcx> { - let value = match self.handle_operand(discr, state) { + let value = match self.handle_operand(discr) { ValueOrPlace::Value(value) => value, ValueOrPlace::Place(place) => state.get_idx(place, &self.map), }; @@ -676,7 +678,7 @@ impl<'a, 'tcx> ConstAnalysis<'a, 'tcx> { op: &Operand<'tcx>, state: &mut State>, ) -> FlatSet> { - let value = match self.handle_operand(op, state) { + let value = match self.handle_operand(op) { ValueOrPlace::Value(value) => value, ValueOrPlace::Place(place) => state.get_idx(place, &self.map), }; diff --git a/compiler/rustc_mir_transform/src/liveness.rs b/compiler/rustc_mir_transform/src/liveness.rs index 32951ea0162a6..c895819a9f8cc 100644 --- a/compiler/rustc_mir_transform/src/liveness.rs +++ b/compiler/rustc_mir_transform/src/liveness.rs @@ -1342,14 +1342,13 @@ impl<'tcx> Analysis<'tcx> for MaybeLivePlaces<'_, 'tcx> { self.transfer_function(trans).visit_statement(statement, location); } - fn apply_primary_terminator_effect<'mir>( + fn apply_primary_terminator_effect( &self, trans: &mut Self::Domain, - terminator: &'mir Terminator<'tcx>, + terminator: &Terminator<'tcx>, location: Location, - ) -> TerminatorEdges<'mir, 'tcx> { + ) { self.transfer_function(trans).visit_terminator(terminator, location); - terminator.edges() } fn apply_call_return_effect( diff --git a/compiler/rustc_span/src/symbol.rs b/compiler/rustc_span/src/symbol.rs index ff1d4253c4414..a346a5216128b 100644 --- a/compiler/rustc_span/src/symbol.rs +++ b/compiler/rustc_span/src/symbol.rs @@ -1872,6 +1872,8 @@ symbols! { rustc_test_marker, rustc_then_this_would_need, rustc_trivial_field_reads, + // FIXME(#159429): temporary rename to avoid `#[unroll]` nameres ambiguity + rustc_unroll, rustdoc, rustdoc_internals, rustdoc_missing_doc_code_examples, @@ -2254,7 +2256,6 @@ symbols! { unreachable_display, unreachable_macro, unrestricted_attribute_tokens, - unroll, unsafe_attributes, unsafe_binders, unsafe_block_in_unsafe_fn, diff --git a/library/core/src/fmt/mod.rs b/library/core/src/fmt/mod.rs index e5d3ccb027b70..a5896f3f863cf 100644 --- a/library/core/src/fmt/mod.rs +++ b/library/core/src/fmt/mod.rs @@ -1611,7 +1611,7 @@ pub trait UpperExp: PointeeSized { /// /// let mut output = String::new(); /// fmt::write(&mut output, format_args!("Hello {}!", "world")) -/// .expect("Error occurred while trying to write in String"); +/// .expect("Writing to a `String` should not fail"); /// assert_eq!(output, "Hello world!"); /// ``` /// @@ -1622,7 +1622,7 @@ pub trait UpperExp: PointeeSized { /// /// let mut output = String::new(); /// write!(&mut output, "Hello {}!", "world") -/// .expect("Error occurred while trying to write in String"); +/// .expect("Writing to a `String` should not fail"); /// assert_eq!(output, "Hello world!"); /// ``` /// diff --git a/src/ci/docker/scripts/stage_2_test_set1.sh b/src/ci/docker/scripts/stage_2_test_set1.sh index e7930513c0d62..62b3c2c051a40 100755 --- a/src/ci/docker/scripts/stage_2_test_set1.sh +++ b/src/ci/docker/scripts/stage_2_test_set1.sh @@ -4,6 +4,8 @@ set -ex # Run a subset of tests. Used to run tests in parallel in multiple jobs. +# NOTE: keep in sync with `aarch64-apple*-{1,2}` jobs. + # When this job partition is run as part of PR CI, skip tidy to allow revealing more failures. The # dedicated `tidy` job failing won't block other PR CI jobs from completing, and so tidy failures # shouldn't inhibit revealing other failures in PR CI jobs. diff --git a/src/ci/docker/scripts/stage_2_test_set2.sh b/src/ci/docker/scripts/stage_2_test_set2.sh index 5963924cce529..c0cdc31011378 100755 --- a/src/ci/docker/scripts/stage_2_test_set2.sh +++ b/src/ci/docker/scripts/stage_2_test_set2.sh @@ -4,6 +4,8 @@ set -ex # Run a subset of tests. Used to run tests in parallel in multiple jobs. +# NOTE: keep in sync with `aarch64-apple*-{1,2}` jobs. + # When this job partition is run as part of PR CI, skip tidy to allow revealing more failures. The # dedicated `tidy` job failing won't block other PR CI jobs from completing, and so tidy failures # shouldn't inhibit revealing other failures in PR CI jobs. diff --git a/src/ci/github-actions/jobs.yml b/src/ci/github-actions/jobs.yml index 5e1ef98906d00..20e52b6b52297 100644 --- a/src/ci/github-actions/jobs.yml +++ b/src/ci/github-actions/jobs.yml @@ -586,11 +586,41 @@ auto: CODEGEN_BACKENDS: llvm,cranelift <<: *job-macos-15 - - name: aarch64-apple + - name: aarch64-apple-1 env: - SCRIPT: > - ./x.py --stage 2 test --host=aarch64-apple-darwin --target=aarch64-apple-darwin && - ./x.py --stage 2 test --host=aarch64-apple-darwin --target=aarch64-apple-darwin src/tools/cargo + # NOTE: keep in sync with `src/ci/docker/scripts/stage_2_test_set1.sh` + SCRIPT: >- + ./x.py --stage 2 test + --host=aarch64-apple-darwin + --target=aarch64-apple-darwin + --skip compiler + --skip src + RUST_CONFIGURE_ARGS: >- + --enable-sanitizers + --enable-profiler + --set build.allocator=jemalloc + DEVELOPER_DIR: /Applications/Xcode_26.2.app/Contents/Developer + # Aarch64 tooling only needs to support macOS 11.0 and up as nothing else + # supports the hardware, so only need to test it there. + MACOSX_DEPLOYMENT_TARGET: 11.0 + MACOSX_STD_DEPLOYMENT_TARGET: 11.0 + <<: *job-macos-15 + + - name: aarch64-apple-2 + env: + # NOTE: keep in sync with `src/ci/docker/scripts/stage_2_test_set2.sh`, + # union `src/tools/cargo` specifically. + SCRIPT: >- + ./x.py --stage 2 test + --host=aarch64-apple-darwin + --target=aarch64-apple-darwin + --skip tests + --skip library + --skip tidyselftest + && ./x.py --stage 2 test + --host=aarch64-apple-darwin + --target=aarch64-apple-darwin + src/tools/cargo RUST_CONFIGURE_ARGS: >- --enable-sanitizers --enable-profiler @@ -607,12 +637,43 @@ auto: # previous attempts have timed out multiple times. Remove/revert this job if # this hangs or times out, or if it becomes the slowest Merge CI job, and let # T-infra know. - - name: aarch64-apple-macos-26 + - name: aarch64-apple-macos-26-1 doc_url: https://github.com/rust-lang/rust/issues/157687 env: - SCRIPT: > - ./x.py --stage 2 test --host=aarch64-apple-darwin --target=aarch64-apple-darwin && - ./x.py --stage 2 test --host=aarch64-apple-darwin --target=aarch64-apple-darwin src/tools/cargo + # NOTE: keep in sync with `src/ci/docker/scripts/stage_2_test_set1.sh` + SCRIPT: >- + ./x.py --stage 2 test + --host=aarch64-apple-darwin + --target=aarch64-apple-darwin + --skip compiler + --skip src + RUST_CONFIGURE_ARGS: >- + --enable-sanitizers + --enable-profiler + --set rust.jemalloc + DEVELOPER_DIR: /Applications/Xcode_26.2.app/Contents/Developer + # Aarch64 tooling only needs to support macOS 11.0 and up as nothing else + # supports the hardware, so only need to test it there. + MACOSX_DEPLOYMENT_TARGET: 11.0 + MACOSX_STD_DEPLOYMENT_TARGET: 11.0 + <<: *job-macos-26 + + - name: aarch64-apple-macos-26-2 + doc_url: https://github.com/rust-lang/rust/issues/157687 + env: + # NOTE: keep in sync with `src/ci/docker/scripts/stage_2_test_set2.sh`, + # union `src/tools/cargo` specifically. + SCRIPT: >- + ./x.py --stage 2 test + --host=aarch64-apple-darwin + --target=aarch64-apple-darwin + --skip tests + --skip library + --skip tidyselftest + && ./x.py --stage 2 test + --host=aarch64-apple-darwin + --target=aarch64-apple-darwin + src/tools/cargo RUST_CONFIGURE_ARGS: >- --enable-sanitizers --enable-profiler diff --git a/src/doc/unstable-book/src/language-features/loop-hints.md b/src/doc/unstable-book/src/language-features/loop-hints.md index c02411d30c668..b82a7b367095a 100644 --- a/src/doc/unstable-book/src/language-features/loop-hints.md +++ b/src/doc/unstable-book/src/language-features/loop-hints.md @@ -6,18 +6,22 @@ The tracking issue for this feature is: [#156874] ------ + + Loop unrolling can be a powerful optimization but like inlining, it is sometimes useful to manually provide hints to optimizations. -`#[unroll]` will encourage unrolling of a loop. +`#[rustc_unroll]` will encourage unrolling of a loop. -`#[unroll(full)]` is a stronger hint and can cause optimizations to completely ignore the code +`#[rustc_unroll(full)]` is a stronger hint and can cause optimizations to completely ignore the code side growth from repeating a loop body. -`#[unroll(never)]` is a strong hint to not unroll the loop at all. Note that other loop +`#[rustc_unroll(never)]` is a strong hint to not unroll the loop at all. Note that other loop optimizations may still be applied. -`#[unroll(N)]` is a hint to unroll `N` iterations of the loop. +`#[rustc_unroll(N)]` is a hint to unroll `N` iterations of the loop. In all cases these are just hints and may be ignored. But unlike function inlining hints, loops tend to be heavily modified during compilation, which can make obeying hints challenging. diff --git a/tests/codegen-llvm/loop-attrs/unroll-for-metadata.rs b/tests/codegen-llvm/loop-attrs/unroll-for-metadata.rs index 64113fbeb3247..60f9b6da6c9fe 100644 --- a/tests/codegen-llvm/loop-attrs/unroll-for-metadata.rs +++ b/tests/codegen-llvm/loop-attrs/unroll-for-metadata.rs @@ -15,7 +15,7 @@ unsafe extern "C" { pub fn unroll_hint() { // CHECK-LABEL: @unroll_hint // CHECK: !llvm.loop ![[HINT:[0-9]+]] - #[unroll] + #[rustc_unroll] for _ in 0..10 { unsafe { maybe_has_side_effect() } } @@ -25,7 +25,7 @@ pub fn unroll_hint() { pub fn unroll_full() { // CHECK-LABEL: @unroll_full // CHECK: !llvm.loop ![[FULL:[0-9]+]] - #[unroll(full)] + #[rustc_unroll(full)] for _ in 0..10 { unsafe { maybe_has_side_effect() } } @@ -35,7 +35,7 @@ pub fn unroll_full() { pub fn unroll_never() { // CHECK-LABEL: @unroll_never // CHECK: !llvm.loop ![[DISABLE:[0-9]+]] - #[unroll(never)] + #[rustc_unroll(never)] for _ in 0..10 { unsafe { maybe_has_side_effect() } } @@ -45,7 +45,7 @@ pub fn unroll_never() { pub fn unroll_count() { // CHECK-LABEL: @unroll_count // CHECK: !llvm.loop ![[COUNT:[0-9]+]] - #[unroll(5)] + #[rustc_unroll(5)] for _ in 0..10 { unsafe { maybe_has_side_effect() } } diff --git a/tests/codegen-llvm/loop-attrs/unroll-for-works.rs b/tests/codegen-llvm/loop-attrs/unroll-for-works.rs index b2f8b58c93573..0aa8d805c4f68 100644 --- a/tests/codegen-llvm/loop-attrs/unroll-for-works.rs +++ b/tests/codegen-llvm/loop-attrs/unroll-for-works.rs @@ -11,7 +11,7 @@ unsafe extern "C" { pub fn unroll_full() { // CHECK-LABEL: @unroll_full // CHECK-COUNT-512: tail call void @maybe_has_side_effect() - #[unroll(full)] + #[rustc_unroll(full)] for _ in 0..512 { unsafe { maybe_has_side_effect() } } @@ -22,7 +22,7 @@ pub fn unroll_never() { // CHECK-LABEL: @unroll_never // CHECK: tail call void @maybe_has_side_effect() // CHECK-NOT: tail call void @maybe_has_side_effect() - #[unroll(never)] + #[rustc_unroll(never)] for _ in 0..3 { unsafe { maybe_has_side_effect() } } @@ -32,7 +32,7 @@ pub fn unroll_never() { pub fn unroll_count() { // CHECK-LABEL: @unroll_count // CHECK-COUNT-5: tail call void @maybe_has_side_effect() - #[unroll(5)] + #[rustc_unroll(5)] for _ in 0..10 { unsafe { maybe_has_side_effect() } } diff --git a/tests/codegen-llvm/loop-attrs/unroll-loop-metadata.rs b/tests/codegen-llvm/loop-attrs/unroll-loop-metadata.rs index 2b2b0779cf49e..7b715d1ac1e32 100644 --- a/tests/codegen-llvm/loop-attrs/unroll-loop-metadata.rs +++ b/tests/codegen-llvm/loop-attrs/unroll-loop-metadata.rs @@ -17,7 +17,7 @@ pub fn unroll_hint() { // CHECK-LABEL: @unroll_hint // CHECK: !llvm.loop ![[HINT:[0-9]+]] let mut i = 0; - #[unroll] + #[rustc_unroll] loop { unsafe { maybe_has_side_effect() } i += 1; @@ -35,7 +35,7 @@ pub fn unroll_full() { // CHECK-LABEL: @unroll_full // CHECK: !llvm.loop ![[FULL:[0-9]+]] let mut i = 0; - let _return = (#[unroll(full)] + let _return = (#[rustc_unroll(full)] loop { unsafe { maybe_has_side_effect() } i += 1; @@ -50,7 +50,7 @@ pub fn unroll_never() { // CHECK-LABEL: @unroll_never // CHECK: !llvm.loop ![[DISABLE:[0-9]+]] let mut i = 0; - let _return = (1 + #[unroll(never)] + let _return = (1 + #[rustc_unroll(never)] loop { unsafe { maybe_has_side_effect() } i += 1; @@ -65,7 +65,7 @@ pub fn unroll_count() { // CHECK-LABEL: @unroll_count // CHECK: !llvm.loop ![[COUNT:[0-9]+]] let mut i = 0; - #[unroll(5)] + #[rustc_unroll(5)] loop { unsafe { maybe_has_side_effect() } i += 1; diff --git a/tests/codegen-llvm/loop-attrs/unroll-while-metadata.rs b/tests/codegen-llvm/loop-attrs/unroll-while-metadata.rs index c40a4188334e8..1a100aae1e717 100644 --- a/tests/codegen-llvm/loop-attrs/unroll-while-metadata.rs +++ b/tests/codegen-llvm/loop-attrs/unroll-while-metadata.rs @@ -16,7 +16,7 @@ pub fn unroll_hint() { // CHECK-LABEL: @unroll_hint // CHECK: !llvm.loop ![[HINT:[0-9]+]] let mut i = 0; - #[unroll] + #[rustc_unroll] while i < 10 { unsafe { maybe_has_side_effect() } i += 1; @@ -28,7 +28,7 @@ pub fn unroll_full() { // CHECK-LABEL: @unroll_full // CHECK: !llvm.loop ![[FULL:[0-9]+]] let mut i = 0; - #[unroll(full)] + #[rustc_unroll(full)] while i < 10 { unsafe { maybe_has_side_effect() } i += 1; @@ -40,7 +40,7 @@ pub fn unroll_never() { // CHECK-LABEL: @unroll_never // CHECK: !llvm.loop ![[DISABLE:[0-9]+]] let mut i = 0; - #[unroll(never)] + #[rustc_unroll(never)] while i < 10 { unsafe { maybe_has_side_effect() } i += 1; @@ -52,7 +52,7 @@ pub fn unroll_count() { // CHECK-LABEL: @unroll_count // CHECK: !llvm.loop ![[COUNT:[0-9]+]] let mut i = 0; - #[unroll(5)] + #[rustc_unroll(5)] while i < 10 { unsafe { maybe_has_side_effect() } i += 1; diff --git a/tests/ui/attributes/unroll/invalid-unroll.rs b/tests/ui/attributes/unroll/invalid-unroll.rs index 8696cefe818f7..13a14c2713fc1 100644 --- a/tests/ui/attributes/unroll/invalid-unroll.rs +++ b/tests/ui/attributes/unroll/invalid-unroll.rs @@ -2,18 +2,18 @@ #![crate_type = "lib"] pub fn main() { - #[unroll(please)] //~ ERROR malformed `unroll` attribute input + #[rustc_unroll(please)] //~ ERROR malformed `rustc_unroll` attribute input for _ in 0..10 {} - #[unroll("never")] //~ ERROR malformed `unroll` attribute input + #[rustc_unroll("never")] //~ ERROR malformed `rustc_unroll` attribute input for _ in 0..10 {} - #[unroll()] //~ ERROR malformed `unroll` attribute input + #[rustc_unroll()] //~ ERROR malformed `rustc_unroll` attribute input for _ in 0..10 {} - #[unroll(-1)] //~ ERROR expected a literal + #[rustc_unroll(-1)] //~ ERROR expected a literal for _ in 0..10 {} - #[unroll(1.5)] //~ ERROR malformed `unroll` attribute input + #[rustc_unroll(1.5)] //~ ERROR malformed `rustc_unroll` attribute input for _ in 0..10 {} } diff --git a/tests/ui/attributes/unroll/invalid-unroll.stderr b/tests/ui/attributes/unroll/invalid-unroll.stderr index 9d25fa2c42d66..ced0523bf99ea 100644 --- a/tests/ui/attributes/unroll/invalid-unroll.stderr +++ b/tests/ui/attributes/unroll/invalid-unroll.stderr @@ -1,46 +1,46 @@ -error[E0539]: malformed `unroll` attribute input +error[E0539]: malformed `rustc_unroll` attribute input --> $DIR/invalid-unroll.rs:5:7 | -LL | #[unroll(please)] - | ^^^^^^^------^ - | | - | valid arguments are `full` or `never` +LL | #[rustc_unroll(please)] + | ^^^^^^^^^^^^^------^ + | | + | valid arguments are `full` or `never` -error[E0539]: malformed `unroll` attribute input +error[E0539]: malformed `rustc_unroll` attribute input --> $DIR/invalid-unroll.rs:8:7 | -LL | #[unroll("never")] - | ^^^^^^^-------^ - | | - | valid arguments are `full` or `never` +LL | #[rustc_unroll("never")] + | ^^^^^^^^^^^^^-------^ + | | + | valid arguments are `full` or `never` -error[E0805]: malformed `unroll` attribute input +error[E0805]: malformed `rustc_unroll` attribute input --> $DIR/invalid-unroll.rs:11:7 | -LL | #[unroll()] - | ^^^^^^-- - | | - | expected an argument here +LL | #[rustc_unroll()] + | ^^^^^^^^^^^^-- + | | + | expected an argument here error: expected a literal (`1u8`, `1.0f32`, `"string"`, etc.) here, found expression - --> $DIR/invalid-unroll.rs:14:14 + --> $DIR/invalid-unroll.rs:14:20 | -LL | #[unroll(-1)] - | ^^ expressions are not allowed here +LL | #[rustc_unroll(-1)] + | ^^ expressions are not allowed here | help: negative numbers are not literals, try removing the `-` sign | -LL - #[unroll(-1)] -LL + #[unroll(1)] +LL - #[rustc_unroll(-1)] +LL + #[rustc_unroll(1)] | -error[E0539]: malformed `unroll` attribute input +error[E0539]: malformed `rustc_unroll` attribute input --> $DIR/invalid-unroll.rs:17:7 | -LL | #[unroll(1.5)] - | ^^^^^^^---^ - | | - | valid arguments are `full` or `never` +LL | #[rustc_unroll(1.5)] + | ^^^^^^^^^^^^^---^ + | | + | valid arguments are `full` or `never` error: aborting due to 5 previous errors diff --git a/tests/ui/borrowck/alias-liveness/gat-static-unnormalized.rs b/tests/ui/borrowck/alias-liveness/gat-static-unnormalized.rs new file mode 100644 index 0000000000000..bb8dfc4553146 --- /dev/null +++ b/tests/ui/borrowck/alias-liveness/gat-static-unnormalized.rs @@ -0,0 +1,47 @@ +//@ revisions: old next +//@[next] compile-flags: -Znext-solver +//@ ignore-compare-mode-next-solver (explicit revisions) +//@ check-pass + +// Regression test for #158461. Outlives clauses from the parameter environment +// need to be normalized before alias liveness analysis can match them. + +trait Id { + type SelfType; +} + +impl Id for T { + type SelfType = T; +} + +trait Foo { + type Assoc<'a> + where + Self: 'a; + + fn assoc(&mut self) -> Self::Assoc<'_>; +} + +// The normalized `'static` bound allows this value's borrow to end immediately. +fn overlapping_mut(mut t: T) +where + T: Foo, + for<'a> as Id>::SelfType: 'static, +{ + let a = t.assoc(); + let b = t.assoc(); +} + +// This is a distinct liveness path: the owner can be moved while the projected +// value remains live. +fn live_past_borrow(mut t: T) +where + T: Foo, + for<'a> as Id>::SelfType: 'static, +{ + let x = t.assoc(); + drop(t); + drop(x); +} + +fn main() {} diff --git a/tests/ui/feature-gates/feature-gate-loop-hints.rs b/tests/ui/feature-gates/feature-gate-loop-hints.rs index 85a1f10ab0a63..480d9a95f08a9 100644 --- a/tests/ui/feature-gates/feature-gate-loop-hints.rs +++ b/tests/ui/feature-gates/feature-gate-loop-hints.rs @@ -1,4 +1,4 @@ fn main() { - #[unroll] //~ ERROR the `unroll` attribute is an experimental feature + #[rustc_unroll] //~ ERROR the `rustc_unroll` attribute is an experimental feature for _ in 0..10 {} } diff --git a/tests/ui/feature-gates/feature-gate-loop-hints.stderr b/tests/ui/feature-gates/feature-gate-loop-hints.stderr index 98279fe144126..56c3ec6812c9c 100644 --- a/tests/ui/feature-gates/feature-gate-loop-hints.stderr +++ b/tests/ui/feature-gates/feature-gate-loop-hints.stderr @@ -1,8 +1,8 @@ -error[E0658]: the `unroll` attribute is an experimental feature +error[E0658]: the `rustc_unroll` attribute is an experimental feature --> $DIR/feature-gate-loop-hints.rs:2:7 | -LL | #[unroll] - | ^^^^^^ +LL | #[rustc_unroll] + | ^^^^^^^^^^^^ | = note: see issue #156874 for more information = help: add `#![feature(loop_hints)]` to the crate attributes to enable diff --git a/tests/ui/feature-gates/feature-gate-rustc-attrs.stderr b/tests/ui/feature-gates/feature-gate-rustc-attrs.stderr index 629d25ec4f01c..884a02c5ec25d 100644 --- a/tests/ui/feature-gates/feature-gate-rustc-attrs.stderr +++ b/tests/ui/feature-gates/feature-gate-rustc-attrs.stderr @@ -33,6 +33,12 @@ error: cannot find attribute `rustc_unknown` in this scope | LL | #[rustc_unknown] | ^^^^^^^^^^^^^ + | +help: a built-in attribute with a similar name exists + | +LL - #[rustc_unknown] +LL + #[rustc_unroll] + | error[E0658]: use of an internal attribute --> $DIR/feature-gate-rustc-attrs.rs:20:3 diff --git a/tests/ui/nll/polonius/nll-legacy-unnecessary-error.legacy.stderr b/tests/ui/nll/polonius/nll-legacy-unnecessary-error.legacy.stderr new file mode 100644 index 0000000000000..79f32e55559cf --- /dev/null +++ b/tests/ui/nll/polonius/nll-legacy-unnecessary-error.legacy.stderr @@ -0,0 +1,14 @@ +error[E0506]: cannot assign to `z` because it is borrowed + --> $DIR/nll-legacy-unnecessary-error.rs:20:5 + | +LL | x.0 = &z; + | -- `z` is borrowed here +LL | z += 1; + | ^^^^^^ `z` is assigned to here but it was already borrowed +... +LL | dbg!(y.0); + | --- borrow later used here + +error: aborting due to 1 previous error + +For more information about this error, try `rustc --explain E0506`. diff --git a/tests/ui/nll/polonius/nll-legacy-unnecessary-error.nll.stderr b/tests/ui/nll/polonius/nll-legacy-unnecessary-error.nll.stderr new file mode 100644 index 0000000000000..79f32e55559cf --- /dev/null +++ b/tests/ui/nll/polonius/nll-legacy-unnecessary-error.nll.stderr @@ -0,0 +1,14 @@ +error[E0506]: cannot assign to `z` because it is borrowed + --> $DIR/nll-legacy-unnecessary-error.rs:20:5 + | +LL | x.0 = &z; + | -- `z` is borrowed here +LL | z += 1; + | ^^^^^^ `z` is assigned to here but it was already borrowed +... +LL | dbg!(y.0); + | --- borrow later used here + +error: aborting due to 1 previous error + +For more information about this error, try `rustc --explain E0506`. diff --git a/tests/ui/nll/polonius/nll-legacy-unnecessary-error.rs b/tests/ui/nll/polonius/nll-legacy-unnecessary-error.rs new file mode 100644 index 0000000000000..06a4f9b1a5640 --- /dev/null +++ b/tests/ui/nll/polonius/nll-legacy-unnecessary-error.rs @@ -0,0 +1,25 @@ +// NLLs and legacy polonius emit an unnecessary error here, unlike the alpha. It's not clear +// *exactly* why the datalog implementation rejects this, but it looks like it propagates the loan +// from 'x to 'y very eagerly, even though x is dead before the assignment. The loan would thus be +// live and invalidated by the assignment, AKA an error. + +//@ ignore-compare-mode-polonius (explicit revisions) +//@ revisions: nll polonius legacy +//@ [nll] compile-flags: -Z polonius=off +//@ [polonius] check-pass +//@ [polonius] compile-flags: -Z polonius=next +//@ [legacy] compile-flags: -Z polonius=legacy + +fn main() { + let mut x: (&u32,) = (&1,); + let mut y: (&u32,) = (&2,); + let mut z = 3; + + y.0 = x.0; + x.0 = &z; + z += 1; + //[nll]~^ ERROR: cannot assign to `z` because it is borrowed + //[legacy]~^^ ERROR: cannot assign to `z` because it is borrowed + + dbg!(y.0); +} diff --git a/tests/ui/parser/recover/array-type-no-semi-turbofish-81097.rs b/tests/ui/parser/recover/array-type-no-semi-turbofish-81097.rs new file mode 100644 index 0000000000000..e0088837fac8e --- /dev/null +++ b/tests/ui/parser/recover/array-type-no-semi-turbofish-81097.rs @@ -0,0 +1,6 @@ +//! Regression test for . + +fn main() { + drop::<[(), 0]>([]); + //~^ ERROR expected `;` or `]`, found `,` +} diff --git a/tests/ui/parser/recover/array-type-no-semi-turbofish-81097.stderr b/tests/ui/parser/recover/array-type-no-semi-turbofish-81097.stderr new file mode 100644 index 0000000000000..17dc812c8e6ec --- /dev/null +++ b/tests/ui/parser/recover/array-type-no-semi-turbofish-81097.stderr @@ -0,0 +1,14 @@ +error: expected `;` or `]`, found `,` + --> $DIR/array-type-no-semi-turbofish-81097.rs:4:15 + | +LL | drop::<[(), 0]>([]); + | ^ expected `;` or `]` + | +help: you might have meant to use `;` as the separator + | +LL - drop::<[(), 0]>([]); +LL + drop::<[(); 0]>([]); + | + +error: aborting due to 1 previous error + diff --git a/tests/ui/traits/next-solver/generalize/eagerly-normalizing-aliases.rs b/tests/ui/traits/next-solver/generalize/eagerly-normalizing-aliases.rs new file mode 100644 index 0000000000000..2d5ae9d21010f --- /dev/null +++ b/tests/ui/traits/next-solver/generalize/eagerly-normalizing-aliases.rs @@ -0,0 +1,31 @@ +//@ revisions: old next +//@[next] compile-flags: -Znext-solver +//@ ignore-compare-mode-next-solver (explicit revisions) +//@ check-pass + +// Regression test for trait-system-refactor-initiative#262. + +trait View {} + +trait HasAssoc { + type Assoc; +} + +struct StableVec(T); + +impl View for StableVec {} + +fn assert_view(f: F) -> F { + f +} + +fn store() -> StableVec +where + T: HasAssoc, + StableVec: View, +{ + let x = todo!(); + assert_view(x) +} + +fn main() {} diff --git a/tests/ui/traits/next-solver/opaques/recursive-hidden-type-canonicalization.rs b/tests/ui/traits/next-solver/opaques/recursive-hidden-type-canonicalization.rs new file mode 100644 index 0000000000000..f93410550bdcf --- /dev/null +++ b/tests/ui/traits/next-solver/opaques/recursive-hidden-type-canonicalization.rs @@ -0,0 +1,28 @@ +//@ compile-flags: -Znext-solver + +// Regression test for trait-system-refactor-initiative#267. This recursively +// changing opaque type used to overflow the stack while instantiating a +// canonical response. + +trait Distribution {} + +impl Distribution<(A, B)> for u32 +where + u32: Distribution, + u32: Distribution, +{ +} + +fn require_distribution, T>(_: *mut T) {} + +fn random_paulis() -> Option<*mut impl Sized> { + if false { + let r = random_paulis().unwrap(); + //~^ ERROR type annotations needed + require_distribution::(r); + } + + None +} + +fn main() {} diff --git a/tests/ui/traits/next-solver/opaques/recursive-hidden-type-canonicalization.stderr b/tests/ui/traits/next-solver/opaques/recursive-hidden-type-canonicalization.stderr new file mode 100644 index 0000000000000..b3b173def6a01 --- /dev/null +++ b/tests/ui/traits/next-solver/opaques/recursive-hidden-type-canonicalization.stderr @@ -0,0 +1,14 @@ +error[E0282]: type annotations needed for `*mut _` + --> $DIR/recursive-hidden-type-canonicalization.rs:20:13 + | +LL | let r = random_paulis().unwrap(); + | ^ + | +help: consider giving `r` an explicit type, where the placeholder `_` is specified + | +LL | let r: *mut _ = random_paulis().unwrap(); + | ++++++++ + +error: aborting due to 1 previous error + +For more information about this error, try `rustc --explain E0282`. diff --git a/tests/ui/traits/next-solver/opaques/stalled-goal-rerun.rs b/tests/ui/traits/next-solver/opaques/stalled-goal-rerun.rs new file mode 100644 index 0000000000000..8402d695749cd --- /dev/null +++ b/tests/ui/traits/next-solver/opaques/stalled-goal-rerun.rs @@ -0,0 +1,33 @@ +//@ compile-flags: -Znext-solver +//@ check-pass + +// Regression test for trait-system-refactor-initiative#267. This used to hang +// because a fast-path goal was not rerun after the opaque type storage changed. + +trait Distribution {} + +impl Distribution<()> for u32 {} + +impl Distribution<(A, B)> for u32 +where + u32: Distribution, + u32: Distribution, +{ +} + +trait Trait { + type Item; +} + +impl Trait for Option +where + u32: Distribution, +{ + type Item = T; +} + +fn random_paulis() -> impl Trait { + None +} + +fn main() {}