From d2cb1456597302c4bbd713dff444160b3a14f6bf Mon Sep 17 00:00:00 2001 From: danieljofficial Date: Mon, 4 May 2026 15:45:31 +0100 Subject: [PATCH 01/19] move type casting related tests into its dedicated folder --- .../issue-45730.rs => cast/ambiguous-raw-pointer-cast-errors.rs} | 0 .../ambiguous-raw-pointer-cast-errors.stderr} | 0 .../as-cast-unifies-raw-pointer-and-fn-type.rs} | 0 .../{issues/issue-36936.rs => cast/cast-not-treated-as-lvalue.rs} | 0 tests/ui/{issues/issue-30615.rs => cast/cast-ptr-to-fat-ptr.rs} | 0 .../issue-31511.rs => cast/invalid-thin-to-fat-pointer-cast.rs} | 0 .../invalid-thin-to-fat-pointer-cast.stderr} | 0 .../issue-43291.rs => cast/negative-integer-cast-to-pointer.rs} | 0 .../non-primitive-cast-self-to-dyn-index.rs} | 0 .../non-primitive-cast-self-to-dyn-index.stderr} | 0 .../issue-17336.rs => cast/raw-pointer-from-str-comparison.rs} | 0 11 files changed, 0 insertions(+), 0 deletions(-) rename tests/ui/{issues/issue-45730.rs => cast/ambiguous-raw-pointer-cast-errors.rs} (100%) rename tests/ui/{issues/issue-45730.stderr => cast/ambiguous-raw-pointer-cast-errors.stderr} (100%) rename tests/ui/{issues/issue-23699.rs => cast/as-cast-unifies-raw-pointer-and-fn-type.rs} (100%) rename tests/ui/{issues/issue-36936.rs => cast/cast-not-treated-as-lvalue.rs} (100%) rename tests/ui/{issues/issue-30615.rs => cast/cast-ptr-to-fat-ptr.rs} (100%) rename tests/ui/{issues/issue-31511.rs => cast/invalid-thin-to-fat-pointer-cast.rs} (100%) rename tests/ui/{issues/issue-31511.stderr => cast/invalid-thin-to-fat-pointer-cast.stderr} (100%) rename tests/ui/{issues/issue-43291.rs => cast/negative-integer-cast-to-pointer.rs} (100%) rename tests/ui/{issues/issue-22312.rs => cast/non-primitive-cast-self-to-dyn-index.rs} (100%) rename tests/ui/{issues/issue-22312.stderr => cast/non-primitive-cast-self-to-dyn-index.stderr} (100%) rename tests/ui/{issues/issue-17336.rs => cast/raw-pointer-from-str-comparison.rs} (100%) diff --git a/tests/ui/issues/issue-45730.rs b/tests/ui/cast/ambiguous-raw-pointer-cast-errors.rs similarity index 100% rename from tests/ui/issues/issue-45730.rs rename to tests/ui/cast/ambiguous-raw-pointer-cast-errors.rs diff --git a/tests/ui/issues/issue-45730.stderr b/tests/ui/cast/ambiguous-raw-pointer-cast-errors.stderr similarity index 100% rename from tests/ui/issues/issue-45730.stderr rename to tests/ui/cast/ambiguous-raw-pointer-cast-errors.stderr diff --git a/tests/ui/issues/issue-23699.rs b/tests/ui/cast/as-cast-unifies-raw-pointer-and-fn-type.rs similarity index 100% rename from tests/ui/issues/issue-23699.rs rename to tests/ui/cast/as-cast-unifies-raw-pointer-and-fn-type.rs diff --git a/tests/ui/issues/issue-36936.rs b/tests/ui/cast/cast-not-treated-as-lvalue.rs similarity index 100% rename from tests/ui/issues/issue-36936.rs rename to tests/ui/cast/cast-not-treated-as-lvalue.rs diff --git a/tests/ui/issues/issue-30615.rs b/tests/ui/cast/cast-ptr-to-fat-ptr.rs similarity index 100% rename from tests/ui/issues/issue-30615.rs rename to tests/ui/cast/cast-ptr-to-fat-ptr.rs diff --git a/tests/ui/issues/issue-31511.rs b/tests/ui/cast/invalid-thin-to-fat-pointer-cast.rs similarity index 100% rename from tests/ui/issues/issue-31511.rs rename to tests/ui/cast/invalid-thin-to-fat-pointer-cast.rs diff --git a/tests/ui/issues/issue-31511.stderr b/tests/ui/cast/invalid-thin-to-fat-pointer-cast.stderr similarity index 100% rename from tests/ui/issues/issue-31511.stderr rename to tests/ui/cast/invalid-thin-to-fat-pointer-cast.stderr diff --git a/tests/ui/issues/issue-43291.rs b/tests/ui/cast/negative-integer-cast-to-pointer.rs similarity index 100% rename from tests/ui/issues/issue-43291.rs rename to tests/ui/cast/negative-integer-cast-to-pointer.rs diff --git a/tests/ui/issues/issue-22312.rs b/tests/ui/cast/non-primitive-cast-self-to-dyn-index.rs similarity index 100% rename from tests/ui/issues/issue-22312.rs rename to tests/ui/cast/non-primitive-cast-self-to-dyn-index.rs diff --git a/tests/ui/issues/issue-22312.stderr b/tests/ui/cast/non-primitive-cast-self-to-dyn-index.stderr similarity index 100% rename from tests/ui/issues/issue-22312.stderr rename to tests/ui/cast/non-primitive-cast-self-to-dyn-index.stderr diff --git a/tests/ui/issues/issue-17336.rs b/tests/ui/cast/raw-pointer-from-str-comparison.rs similarity index 100% rename from tests/ui/issues/issue-17336.rs rename to tests/ui/cast/raw-pointer-from-str-comparison.rs From f95f3410826bba0b95076d7e026e0a5aafb227f7 Mon Sep 17 00:00:00 2001 From: Vadim Petrochenkov Date: Thu, 7 May 2026 18:56:45 +0300 Subject: [PATCH 02/19] Add a regression test for issue #156264 --- ...biguous-import-visibility-globglob-reexport.rs | 15 +++++++++++++++ ...ous-import-visibility-globglob-reexport.stderr | 11 +++++++++++ 2 files changed, 26 insertions(+) create mode 100644 tests/ui/imports/ambiguous-import-visibility-globglob-reexport.rs create mode 100644 tests/ui/imports/ambiguous-import-visibility-globglob-reexport.stderr diff --git a/tests/ui/imports/ambiguous-import-visibility-globglob-reexport.rs b/tests/ui/imports/ambiguous-import-visibility-globglob-reexport.rs new file mode 100644 index 0000000000000..136fd6de31750 --- /dev/null +++ b/tests/ui/imports/ambiguous-import-visibility-globglob-reexport.rs @@ -0,0 +1,15 @@ +// Regression test for issue #156264 + +mod m_pub { + pub struct S {} +} + +mod m_crate { + pub(crate) use crate::m_pub::S; +} + +pub(crate) use m_crate::*; +//~^ ERROR `S` is only public within the crate, and cannot be re-exported outside +pub use m_pub::*; + +fn main() {} diff --git a/tests/ui/imports/ambiguous-import-visibility-globglob-reexport.stderr b/tests/ui/imports/ambiguous-import-visibility-globglob-reexport.stderr new file mode 100644 index 0000000000000..be845fbe05c79 --- /dev/null +++ b/tests/ui/imports/ambiguous-import-visibility-globglob-reexport.stderr @@ -0,0 +1,11 @@ +error[E0365]: `S` is only public within the crate, and cannot be re-exported outside + --> $DIR/ambiguous-import-visibility-globglob-reexport.rs:11:16 + | +LL | pub(crate) use m_crate::*; + | ^^^^^^^^^^ re-export of crate public `S` + | + = note: consider declaring type or module `S` with `pub` + +error: aborting due to 1 previous error + +For more information about this error, try `rustc --explain E0365`. From 235fa6b34cc06a04660e64aae775933eb7ae490a Mon Sep 17 00:00:00 2001 From: Vadim Petrochenkov Date: Thu, 7 May 2026 19:18:22 +0300 Subject: [PATCH 03/19] resolve: Fix a false positive "cannot reexport" error for ambiguous glob sets --- compiler/rustc_resolve/src/imports.rs | 4 ++++ .../ambiguous-import-visibility-globglob-reexport.rs | 3 ++- ...biguous-import-visibility-globglob-reexport.stderr | 11 ----------- 3 files changed, 6 insertions(+), 12 deletions(-) delete mode 100644 tests/ui/imports/ambiguous-import-visibility-globglob-reexport.stderr diff --git a/compiler/rustc_resolve/src/imports.rs b/compiler/rustc_resolve/src/imports.rs index 1b9e5d2a2daa6..b36dd1ef31bb9 100644 --- a/compiler/rustc_resolve/src/imports.rs +++ b/compiler/rustc_resolve/src/imports.rs @@ -822,6 +822,10 @@ impl<'ra, 'tcx> Resolver<'ra, 'tcx> { for decl in [resolution.non_glob_decl, resolution.glob_decl] { if let Some(decl) = decl && let DeclKind::Import { source_decl, import } = decl.kind + // FIXME: Do not check visibility-ambiguous imports for now. To check them + // properly we need to preserve all imports in ambiguous glob sets and + // check them all individually. + && decl.ambiguity_vis_max.get().is_none() { // The source entity is too private to be reexported // with the given import declaration's visibility. diff --git a/tests/ui/imports/ambiguous-import-visibility-globglob-reexport.rs b/tests/ui/imports/ambiguous-import-visibility-globglob-reexport.rs index 136fd6de31750..25dd51141c936 100644 --- a/tests/ui/imports/ambiguous-import-visibility-globglob-reexport.rs +++ b/tests/ui/imports/ambiguous-import-visibility-globglob-reexport.rs @@ -1,5 +1,7 @@ // Regression test for issue #156264 +//@ check-pass + mod m_pub { pub struct S {} } @@ -9,7 +11,6 @@ mod m_crate { } pub(crate) use m_crate::*; -//~^ ERROR `S` is only public within the crate, and cannot be re-exported outside pub use m_pub::*; fn main() {} diff --git a/tests/ui/imports/ambiguous-import-visibility-globglob-reexport.stderr b/tests/ui/imports/ambiguous-import-visibility-globglob-reexport.stderr deleted file mode 100644 index be845fbe05c79..0000000000000 --- a/tests/ui/imports/ambiguous-import-visibility-globglob-reexport.stderr +++ /dev/null @@ -1,11 +0,0 @@ -error[E0365]: `S` is only public within the crate, and cannot be re-exported outside - --> $DIR/ambiguous-import-visibility-globglob-reexport.rs:11:16 - | -LL | pub(crate) use m_crate::*; - | ^^^^^^^^^^ re-export of crate public `S` - | - = note: consider declaring type or module `S` with `pub` - -error: aborting due to 1 previous error - -For more information about this error, try `rustc --explain E0365`. From 1d6a77f612579827704abb053f12409632d91f27 Mon Sep 17 00:00:00 2001 From: cyrgani Date: Thu, 7 May 2026 07:56:26 +0000 Subject: [PATCH 04/19] use `deref_patterns` in `rustc_borrowck` --- compiler/rustc_borrowck/src/dataflow.rs | 2 +- .../src/diagnostics/conflict_errors.rs | 14 +++++++------- .../src/diagnostics/explain_borrow.rs | 6 +++--- compiler/rustc_borrowck/src/diagnostics/mod.rs | 18 +++++++++--------- .../src/diagnostics/move_errors.rs | 2 +- .../src/diagnostics/mutability_errors.rs | 16 ++++++---------- compiler/rustc_borrowck/src/lib.rs | 12 ++++++------ .../src/polonius/legacy/loan_invalidations.rs | 10 +++++----- compiler/rustc_borrowck/src/type_check/mod.rs | 10 +++++----- compiler/rustc_borrowck/src/used_muts.rs | 2 +- 10 files changed, 44 insertions(+), 48 deletions(-) diff --git a/compiler/rustc_borrowck/src/dataflow.rs b/compiler/rustc_borrowck/src/dataflow.rs index ef167644f0a9d..42af99fc64d81 100644 --- a/compiler/rustc_borrowck/src/dataflow.rs +++ b/compiler/rustc_borrowck/src/dataflow.rs @@ -548,7 +548,7 @@ impl<'tcx> rustc_mir_dataflow::Analysis<'tcx> for Borrows<'_, 'tcx> { location: Location, ) { match &stmt.kind { - mir::StatementKind::Assign(box (lhs, rhs)) => { + mir::StatementKind::Assign((lhs, rhs)) => { if let mir::Rvalue::Ref(_, _, place) | mir::Rvalue::Reborrow(_, _, place) = rhs { if place.ignore_borrow( self.tcx, diff --git a/compiler/rustc_borrowck/src/diagnostics/conflict_errors.rs b/compiler/rustc_borrowck/src/diagnostics/conflict_errors.rs index c4fbe1b9e5d61..098c81d27de07 100644 --- a/compiler/rustc_borrowck/src/diagnostics/conflict_errors.rs +++ b/compiler/rustc_borrowck/src/diagnostics/conflict_errors.rs @@ -4009,12 +4009,12 @@ impl<'infcx, 'tcx> MirBorrowckCtxt<'_, 'infcx, 'tcx> { Some(LocalDecl { local_info: ClearCrossCrate::Set( - box LocalInfo::User(BindingForm::Var(VarBindingForm { + LocalInfo::User(BindingForm::Var(VarBindingForm { opt_match_place: None, .. })) - | box LocalInfo::StaticRef { .. } - | box LocalInfo::Boring, + | LocalInfo::StaticRef { .. } + | LocalInfo::Boring, ), .. }) @@ -4185,7 +4185,7 @@ impl<'infcx, 'tcx> MirBorrowckCtxt<'_, 'infcx, 'tcx> { impl<'tcx> Visitor<'tcx> for FakeReadCauseFinder<'tcx> { fn visit_statement(&mut self, statement: &Statement<'tcx>, _: Location) { match statement { - Statement { kind: StatementKind::FakeRead(box (cause, place)), .. } + Statement { kind: StatementKind::FakeRead((cause, place)), .. } if *place == self.place => { self.cause = Some(*cause); @@ -4243,7 +4243,7 @@ impl<'infcx, 'tcx> MirBorrowckCtxt<'_, 'infcx, 'tcx> { // and it'll make sense. let location = borrow.reserve_location; debug!("annotate_argument_and_return_for_borrow: location={:?}", location); - if let Some(Statement { kind: StatementKind::Assign(box (reservation, _)), .. }) = + if let Some(Statement { kind: StatementKind::Assign((reservation, _)), .. }) = &self.body[location.block].statements.get(location.statement_index) { debug!("annotate_argument_and_return_for_borrow: reservation={:?}", reservation); @@ -4261,7 +4261,7 @@ impl<'infcx, 'tcx> MirBorrowckCtxt<'_, 'infcx, 'tcx> { "annotate_argument_and_return_for_borrow: target={:?} stmt={:?}", target, stmt ); - if let StatementKind::Assign(box (place, rvalue)) = &stmt.kind + if let StatementKind::Assign((place, rvalue)) = &stmt.kind && let Some(assigned_to) = place.as_local() { debug!( @@ -4270,7 +4270,7 @@ impl<'infcx, 'tcx> MirBorrowckCtxt<'_, 'infcx, 'tcx> { assigned_to, rvalue ); // Check if our `target` was captured by a closure. - if let Rvalue::Aggregate(box AggregateKind::Closure(def_id, args), operands) = + if let Rvalue::Aggregate(AggregateKind::Closure(def_id, args), operands) = rvalue { let def_id = def_id.expect_local(); diff --git a/compiler/rustc_borrowck/src/diagnostics/explain_borrow.rs b/compiler/rustc_borrowck/src/diagnostics/explain_borrow.rs index 6a4f0038ba5d6..5d154cc7b9050 100644 --- a/compiler/rustc_borrowck/src/diagnostics/explain_borrow.rs +++ b/compiler/rustc_borrowck/src/diagnostics/explain_borrow.rs @@ -787,7 +787,7 @@ impl<'tcx> MirBorrowckCtxt<'_, '_, 'tcx> { let block = &self.body.basic_blocks[location.block]; let kind = if let Some(&Statement { - kind: StatementKind::FakeRead(box (FakeReadCause::ForLet(_), place)), + kind: StatementKind::FakeRead((FakeReadCause::ForLet(_), place)), .. }) = block.statements.get(location.statement_index) { @@ -849,7 +849,7 @@ impl<'tcx> MirBorrowckCtxt<'_, '_, 'tcx> { // will only ever have one item at any given time, but by using a vector, we can pop from // it which simplifies the termination logic. let mut queue = vec![location]; - let Some(Statement { kind: StatementKind::Assign(box (place, _)), .. }) = stmt else { + let Some(Statement { kind: StatementKind::Assign((place, _)), .. }) = stmt else { return false; }; let Some(mut target) = place.as_local() else { return false }; @@ -865,7 +865,7 @@ impl<'tcx> MirBorrowckCtxt<'_, '_, 'tcx> { debug!("was_captured_by_trait_object: stmt={:?}", stmt); // The only kind of statement that we care about is assignments... - if let StatementKind::Assign(box (place, rvalue)) = &stmt.kind { + if let StatementKind::Assign((place, rvalue)) = &stmt.kind { let Some(into) = place.local_or_deref_local() else { // Continue at the next location. queue.push(current_location.successor_within_block()); diff --git a/compiler/rustc_borrowck/src/diagnostics/mod.rs b/compiler/rustc_borrowck/src/diagnostics/mod.rs index 9245e5f05f4c1..248396ba9849b 100644 --- a/compiler/rustc_borrowck/src/diagnostics/mod.rs +++ b/compiler/rustc_borrowck/src/diagnostics/mod.rs @@ -243,7 +243,7 @@ impl<'infcx, 'tcx> MirBorrowckCtxt<'_, 'infcx, 'tcx> { let mut target = place.local_or_deref_local(); for stmt in &self.body[location.block].statements[location.statement_index..] { debug!("add_moved_or_invoked_closure_note: stmt={:?} target={:?}", stmt, target); - if let StatementKind::Assign(box (into, Rvalue::Use(from, _))) = &stmt.kind { + if let StatementKind::Assign((into, Rvalue::Use(from, _))) = &stmt.kind { debug!("add_fnonce_closure_note: into={:?} from={:?}", into, from); match from { Operand::Copy(place) | Operand::Move(place) @@ -260,7 +260,7 @@ impl<'infcx, 'tcx> MirBorrowckCtxt<'_, 'infcx, 'tcx> { let terminator = self.body[location.block].terminator(); debug!("add_moved_or_invoked_closure_note: terminator={:?}", terminator); if let TerminatorKind::Call { - func: Operand::Constant(box ConstOperand { const_, .. }), + func: Operand::Constant(ConstOperand { const_, .. }), args, .. } = &terminator.kind @@ -1030,7 +1030,7 @@ impl<'infcx, 'tcx> MirBorrowckCtxt<'_, 'infcx, 'tcx> { }; debug!("move_spans: moved_place={:?} location={:?} stmt={:?}", moved_place, location, stmt); - if let StatementKind::Assign(box (_, Rvalue::Aggregate(kind, places))) = &stmt.kind + if let StatementKind::Assign((_, Rvalue::Aggregate(kind, places))) = &stmt.kind && let AggregateKind::Closure(def_id, _) | AggregateKind::Coroutine(def_id, _) = **kind { debug!("move_spans: def_id={:?} places={:?}", def_id, places); @@ -1044,7 +1044,7 @@ impl<'infcx, 'tcx> MirBorrowckCtxt<'_, 'infcx, 'tcx> { // StatementKind::FakeRead only contains a def_id if they are introduced as a result // of pattern matching within a closure. - if let StatementKind::FakeRead(box (cause, place)) = stmt.kind { + if let StatementKind::FakeRead((cause, place)) = stmt.kind { match cause { FakeReadCause::ForMatchedPlace(Some(closure_def_id)) | FakeReadCause::ForLet(Some(closure_def_id)) => { @@ -1084,7 +1084,7 @@ impl<'infcx, 'tcx> MirBorrowckCtxt<'_, 'infcx, 'tcx> { // that has a `self` parameter. let target_temp = match stmt.kind { - StatementKind::Assign(box (temp, _)) if temp.as_local().is_some() => { + StatementKind::Assign((temp, _)) if temp.as_local().is_some() => { temp.as_local().unwrap() } _ => return normal_ret, @@ -1131,7 +1131,7 @@ impl<'infcx, 'tcx> MirBorrowckCtxt<'_, 'infcx, 'tcx> { use self::UseSpans::*; debug!("borrow_spans: use_span={:?} location={:?}", use_span, location); - let Some(Statement { kind: StatementKind::Assign(box (place, _)), .. }) = + let Some(Statement { kind: StatementKind::Assign((place, _)), .. }) = self.body[location.block].statements.get(location.statement_index) else { return OtherUse(use_span); @@ -1157,10 +1157,10 @@ impl<'infcx, 'tcx> MirBorrowckCtxt<'_, 'infcx, 'tcx> { self.body[location.block].statements[location.statement_index + 1..].iter(); for stmt in statements.chain(maybe_additional_statement) { - if let StatementKind::Assign(box (_, Rvalue::Aggregate(kind, places))) = &stmt.kind { + if let StatementKind::Assign((_, Rvalue::Aggregate(kind, places))) = &stmt.kind { let (&def_id, is_coroutine) = match kind { - box AggregateKind::Closure(def_id, _) => (def_id, false), - box AggregateKind::Coroutine(def_id, _) => (def_id, true), + AggregateKind::Closure(def_id, _) => (def_id, false), + AggregateKind::Coroutine(def_id, _) => (def_id, true), _ => continue, }; let def_id = def_id.expect_local(); diff --git a/compiler/rustc_borrowck/src/diagnostics/move_errors.rs b/compiler/rustc_borrowck/src/diagnostics/move_errors.rs index 3663ef28e4590..48e75719c0b16 100644 --- a/compiler/rustc_borrowck/src/diagnostics/move_errors.rs +++ b/compiler/rustc_borrowck/src/diagnostics/move_errors.rs @@ -122,7 +122,7 @@ impl<'infcx, 'tcx> MirBorrowckCtxt<'_, 'infcx, 'tcx> { // to a user variable is when initializing it. // If that ever stops being the case, then the ever initialized // flow could be used. - if let Some(StatementKind::Assign(box (place, Rvalue::Use(Operand::Move(move_from), _)))) = + if let Some(StatementKind::Assign((place, Rvalue::Use(Operand::Move(move_from), _)))) = self.body.basic_blocks[location.block] .statements .get(location.statement_index) diff --git a/compiler/rustc_borrowck/src/diagnostics/mutability_errors.rs b/compiler/rustc_borrowck/src/diagnostics/mutability_errors.rs index 00317b376e8cb..a4025f28a5511 100644 --- a/compiler/rustc_borrowck/src/diagnostics/mutability_errors.rs +++ b/compiler/rustc_borrowck/src/diagnostics/mutability_errors.rs @@ -315,7 +315,7 @@ impl<'infcx, 'tcx> MirBorrowckCtxt<'_, 'infcx, 'tcx> { if let Some(mir::Statement { source_info, kind: - mir::StatementKind::Assign(box ( + mir::StatementKind::Assign(( _, mir::Rvalue::Ref( _, @@ -1418,10 +1418,7 @@ impl<'infcx, 'tcx> MirBorrowckCtxt<'_, 'infcx, 'tcx> { if let Some(mir::Statement { source_info: _, kind: - mir::StatementKind::Assign(box ( - _, - mir::Rvalue::Use(mir::Operand::Copy(place), _), - )), + mir::StatementKind::Assign((_, mir::Rvalue::Use(mir::Operand::Copy(place), _))), .. }) = first_assignment_stmt { @@ -1879,7 +1876,7 @@ fn suggest_ampmut<'tcx>( // ^^ lifetime annotation not allowed // if let Some(rhs_stmt) = opt_assignment_rhs_stmt - && let StatementKind::Assign(box (lhs, rvalue)) = &rhs_stmt.kind + && let StatementKind::Assign((lhs, rvalue)) = &rhs_stmt.kind && let mut rhs_span = rhs_stmt.source_info.span && let Ok(mut rhs_str) = tcx.sess.source_map().span_to_snippet(rhs_span) { @@ -1900,7 +1897,7 @@ fn suggest_ampmut<'tcx>( && let [user_ty_proj] = user_ty_projs.contents.as_slice() && user_ty_proj.projs.is_empty() && let Either::Left(rhs_stmt_new) = body.stmt_at(*assign) - && let StatementKind::Assign(box (_, rvalue_new)) = &rhs_stmt_new.kind + && let StatementKind::Assign((_, rvalue_new)) = &rhs_stmt_new.kind && let rhs_span_new = rhs_stmt_new.source_info.span && let Ok(rhs_str_new) = tcx.sess.source_map().span_to_snippet(rhs_span_new) { @@ -1908,9 +1905,8 @@ fn suggest_ampmut<'tcx>( } if let Either::Right(call) = body.stmt_at(*assign) - && let TerminatorKind::Call { - func: Operand::Constant(box const_operand), args, .. - } = &call.kind + && let TerminatorKind::Call { func: Operand::Constant(const_operand), args, .. } = + &call.kind && let ty::FnDef(method_def_id, method_args) = *const_operand.ty().kind() && let Some(trait_) = tcx.trait_of_assoc(method_def_id) && tcx.is_lang_item(trait_, hir::LangItem::Index) diff --git a/compiler/rustc_borrowck/src/lib.rs b/compiler/rustc_borrowck/src/lib.rs index d19d735501405..8b9f4291603a9 100644 --- a/compiler/rustc_borrowck/src/lib.rs +++ b/compiler/rustc_borrowck/src/lib.rs @@ -2,8 +2,8 @@ // tidy-alphabetical-start #![allow(internal_features)] -#![feature(box_patterns)] #![feature(default_field_values)] +#![feature(deref_patterns)] #![feature(file_buffered)] #![feature(negative_impls)] #![feature(never_type)] @@ -803,12 +803,12 @@ impl<'a, 'tcx> ResultsVisitor<'tcx, Borrowck<'a, 'tcx>> for MirBorrowckCtxt<'a, self.check_activations(location, span, state); match &stmt.kind { - StatementKind::Assign(box (lhs, rhs)) => { + StatementKind::Assign((lhs, rhs)) => { self.consume_rvalue(location, (rhs, span), state); self.mutate_place(location, (*lhs, span), Shallow(None), state); } - StatementKind::FakeRead(box (_, place)) => { + StatementKind::FakeRead((_, place)) => { // Read for match doesn't access any memory and is used to // assert that a place is safe and live. So we don't have to // do any checks here. @@ -826,7 +826,7 @@ impl<'a, 'tcx> ResultsVisitor<'tcx, Borrowck<'a, 'tcx>> for MirBorrowckCtxt<'a, state, ); } - StatementKind::Intrinsic(box kind) => match kind { + StatementKind::Intrinsic(kind) => match kind { NonDivergingIntrinsic::Assume(op) => { self.consume_operand(location, (op, span), state); } @@ -1602,7 +1602,7 @@ impl<'a, 'tcx> MirBorrowckCtxt<'a, '_, 'tcx> { ); } - Rvalue::BinaryOp(_bin_op, box (operand1, operand2)) => { + Rvalue::BinaryOp(_bin_op, (operand1, operand2)) => { self.consume_operand(location, (operand1, span), state); self.consume_operand(location, (operand2, span), state); } @@ -1725,7 +1725,7 @@ impl<'a, 'tcx> MirBorrowckCtxt<'a, '_, 'tcx> { debug!("temporary assigned in: stmt={:?}", stmt); match stmt.kind { - StatementKind::Assign(box ( + StatementKind::Assign(( _, Rvalue::Ref(_, _, source) | Rvalue::Use(Operand::Copy(source) | Operand::Move(source), _), diff --git a/compiler/rustc_borrowck/src/polonius/legacy/loan_invalidations.rs b/compiler/rustc_borrowck/src/polonius/legacy/loan_invalidations.rs index da3fc0763a430..31df87dabf815 100644 --- a/compiler/rustc_borrowck/src/polonius/legacy/loan_invalidations.rs +++ b/compiler/rustc_borrowck/src/polonius/legacy/loan_invalidations.rs @@ -45,18 +45,18 @@ impl<'a, 'tcx> Visitor<'tcx> for LoanInvalidationsGenerator<'a, 'tcx> { self.check_activations(location); match &statement.kind { - StatementKind::Assign(box (lhs, rhs)) => { + StatementKind::Assign((lhs, rhs)) => { self.consume_rvalue(location, rhs); self.mutate_place(location, *lhs, Shallow(None)); } - StatementKind::FakeRead(box (_, _)) => { + StatementKind::FakeRead((_, _)) => { // Only relevant for initialized/liveness/safety checks. } - StatementKind::Intrinsic(box NonDivergingIntrinsic::Assume(op)) => { + StatementKind::Intrinsic(NonDivergingIntrinsic::Assume(op)) => { self.consume_operand(location, op); } - StatementKind::Intrinsic(box NonDivergingIntrinsic::CopyNonOverlapping(CopyNonOverlapping { + StatementKind::Intrinsic(NonDivergingIntrinsic::CopyNonOverlapping(CopyNonOverlapping { src, dst, count, @@ -324,7 +324,7 @@ impl<'a, 'tcx> LoanInvalidationsGenerator<'a, 'tcx> { ); } - Rvalue::BinaryOp(_bin_op, box (operand1, operand2)) => { + Rvalue::BinaryOp(_bin_op, (operand1, operand2)) => { self.consume_operand(location, operand1); self.consume_operand(location, operand2); } diff --git a/compiler/rustc_borrowck/src/type_check/mod.rs b/compiler/rustc_borrowck/src/type_check/mod.rs index 48389d9354998..fb5894b8a40a9 100644 --- a/compiler/rustc_borrowck/src/type_check/mod.rs +++ b/compiler/rustc_borrowck/src/type_check/mod.rs @@ -581,7 +581,7 @@ impl<'a, 'tcx> Visitor<'tcx> for TypeChecker<'a, 'tcx> { self.super_statement(stmt, location); let tcx = self.tcx(); match &stmt.kind { - StatementKind::Assign(box (place, rv)) => { + StatementKind::Assign((place, rv)) => { // Assignments to temporaries are not "interesting"; // they are not caused by the user, but rather artifacts // of lowering. Assignments to other sorts of places *are* interesting @@ -672,7 +672,7 @@ impl<'a, 'tcx> Visitor<'tcx> for TypeChecker<'a, 'tcx> { ); } } - StatementKind::AscribeUserType(box (place, projection), variance) => { + StatementKind::AscribeUserType((place, projection), variance) => { let place_ty = place.ty(self.body, tcx).ty; if let Err(terr) = self.relate_type_and_user_type( place_ty, @@ -693,7 +693,7 @@ impl<'a, 'tcx> Visitor<'tcx> for TypeChecker<'a, 'tcx> { ); } } - StatementKind::Intrinsic(box NonDivergingIntrinsic::Assume(..)) + StatementKind::Intrinsic(NonDivergingIntrinsic::Assume(..)) | StatementKind::FakeRead(..) | StatementKind::StorageLive(..) | StatementKind::StorageDead(..) @@ -702,7 +702,7 @@ impl<'a, 'tcx> Visitor<'tcx> for TypeChecker<'a, 'tcx> { | StatementKind::PlaceMention(..) | StatementKind::BackwardIncompatibleDropHint { .. } | StatementKind::Nop => {} - StatementKind::Intrinsic(box NonDivergingIntrinsic::CopyNonOverlapping(..)) + StatementKind::Intrinsic(NonDivergingIntrinsic::CopyNonOverlapping(..)) | StatementKind::SetDiscriminant { .. } => { bug!("Statement not allowed in this MIR phase") } @@ -1591,7 +1591,7 @@ impl<'a, 'tcx> Visitor<'tcx> for TypeChecker<'a, 'tcx> { Rvalue::BinaryOp( BinOp::Eq | BinOp::Ne | BinOp::Lt | BinOp::Le | BinOp::Gt | BinOp::Ge, - box (left, right), + (left, right), ) => { let ty_left = left.ty(self.body, tcx); match ty_left.kind() { diff --git a/compiler/rustc_borrowck/src/used_muts.rs b/compiler/rustc_borrowck/src/used_muts.rs index bde07c05c0e16..29c45e2c7bb6e 100644 --- a/compiler/rustc_borrowck/src/used_muts.rs +++ b/compiler/rustc_borrowck/src/used_muts.rs @@ -78,7 +78,7 @@ impl<'tcx> Visitor<'tcx> for GatherUsedMutsVisitor<'_, '_, '_, 'tcx> { } fn visit_statement(&mut self, statement: &Statement<'tcx>, location: Location) { - if let StatementKind::Assign(box (into, _)) = &statement.kind { + if let StatementKind::Assign((into, _)) = &statement.kind { debug!( "visit_statement: statement={:?} local={:?} \ never_initialized_mut_locals={:?}", From b8ff0d550b9d8c6f528490a3d5f7bd5592d80b47 Mon Sep 17 00:00:00 2001 From: cyrgani Date: Thu, 7 May 2026 14:14:52 +0000 Subject: [PATCH 05/19] use `deref_patterns` in `rustc_builtin_macros` --- compiler/rustc_builtin_macros/src/autodiff.rs | 4 ++-- compiler/rustc_builtin_macros/src/deriving/generic/mod.rs | 2 +- compiler/rustc_builtin_macros/src/format.rs | 2 +- compiler/rustc_builtin_macros/src/global_allocator.rs | 4 ++-- compiler/rustc_builtin_macros/src/lib.rs | 2 +- compiler/rustc_builtin_macros/src/test.rs | 8 ++++---- 6 files changed, 11 insertions(+), 11 deletions(-) diff --git a/compiler/rustc_builtin_macros/src/autodiff.rs b/compiler/rustc_builtin_macros/src/autodiff.rs index afa393a545cd4..76c43e0df1a24 100644 --- a/compiler/rustc_builtin_macros/src/autodiff.rs +++ b/compiler/rustc_builtin_macros/src/autodiff.rs @@ -75,7 +75,7 @@ mod llvm_enzyme { // Get information about the function the macro is applied to fn extract_item_info(iitem: &Box) -> Option<(Visibility, FnSig, Ident, Generics)> { match &iitem.kind { - ItemKind::Fn(box ast::Fn { sig, ident, generics, .. }) => { + ItemKind::Fn(ast::Fn { sig, ident, generics, .. }) => { Some((iitem.vis.clone(), sig.clone(), ident.clone(), generics.clone())) } _ => None, @@ -226,7 +226,7 @@ mod llvm_enzyme { }, Annotatable::AssocItem(assoc_item, _ctxt @ (Impl { of_trait: _ } | Trait)) => { match &assoc_item.kind { - ast::AssocItemKind::Fn(box ast::Fn { sig, ident, generics, .. }) => Some(( + ast::AssocItemKind::Fn(ast::Fn { sig, ident, generics, .. }) => Some(( assoc_item.vis.clone(), sig.clone(), ident.clone(), diff --git a/compiler/rustc_builtin_macros/src/deriving/generic/mod.rs b/compiler/rustc_builtin_macros/src/deriving/generic/mod.rs index ace4048af26c1..8b8af1685287c 100644 --- a/compiler/rustc_builtin_macros/src/deriving/generic/mod.rs +++ b/compiler/rustc_builtin_macros/src/deriving/generic/mod.rs @@ -1027,7 +1027,7 @@ impl<'a> MethodDef<'a> { match ty { // Selflike (`&Self`) arguments only occur in non-static methods. - Ref(box Self_, _) if !self.is_static() => selflike_args.push(arg_expr), + Ref(Self_, _) if !self.is_static() => selflike_args.push(arg_expr), Self_ => cx.dcx().span_bug(span, "`Self` in non-return position"), _ => nonselflike_args.push(arg_expr), } diff --git a/compiler/rustc_builtin_macros/src/format.rs b/compiler/rustc_builtin_macros/src/format.rs index 1caa0e823090a..7c43693e15f84 100644 --- a/compiler/rustc_builtin_macros/src/format.rs +++ b/compiler/rustc_builtin_macros/src/format.rs @@ -456,7 +456,7 @@ fn make_format_args( parse::Piece::Lit(s) => { unfinished_literal.push_str(s); } - parse::Piece::NextArgument(box parse::Argument { position, position_span, format }) => { + parse::Piece::NextArgument(parse::Argument { position, position_span, format }) => { if !unfinished_literal.is_empty() { template.push(FormatArgsPiece::Literal(Symbol::intern(&unfinished_literal))); unfinished_literal.clear(); diff --git a/compiler/rustc_builtin_macros/src/global_allocator.rs b/compiler/rustc_builtin_macros/src/global_allocator.rs index 208562b8d0bc0..684411d64d943 100644 --- a/compiler/rustc_builtin_macros/src/global_allocator.rs +++ b/compiler/rustc_builtin_macros/src/global_allocator.rs @@ -25,12 +25,12 @@ pub(crate) fn expand( // Allow using `#[global_allocator]` on an item statement // FIXME - if we get deref patterns, use them to reduce duplication here let (item, ident, is_stmt, ty_span) = if let Annotatable::Item(item) = &item - && let ItemKind::Static(box ast::StaticItem { ident, ty, .. }) = &item.kind + && let ItemKind::Static(ast::StaticItem { ident, ty, .. }) = &item.kind { (item, *ident, false, ecx.with_def_site_ctxt(ty.span)) } else if let Annotatable::Stmt(stmt) = &item && let StmtKind::Item(item) = &stmt.kind - && let ItemKind::Static(box ast::StaticItem { ident, ty, .. }) = &item.kind + && let ItemKind::Static(ast::StaticItem { ident, ty, .. }) = &item.kind { (item, *ident, true, ecx.with_def_site_ctxt(ty.span)) } else { diff --git a/compiler/rustc_builtin_macros/src/lib.rs b/compiler/rustc_builtin_macros/src/lib.rs index d39e3d8103542..d5d577d39d28b 100644 --- a/compiler/rustc_builtin_macros/src/lib.rs +++ b/compiler/rustc_builtin_macros/src/lib.rs @@ -3,8 +3,8 @@ // tidy-alphabetical-start #![allow(internal_features)] -#![feature(box_patterns)] #![feature(decl_macro)] +#![feature(deref_patterns)] #![feature(iter_order_by)] #![feature(proc_macro_internals)] #![feature(proc_macro_quote)] diff --git a/compiler/rustc_builtin_macros/src/test.rs b/compiler/rustc_builtin_macros/src/test.rs index 1b761614f3e6d..ac865958011a6 100644 --- a/compiler/rustc_builtin_macros/src/test.rs +++ b/compiler/rustc_builtin_macros/src/test.rs @@ -56,9 +56,9 @@ pub(crate) fn expand_test_case( // `#[test_case]` is valid on functions, consts, and statics. Only modify // the item in those cases. match &mut item.kind { - ast::ItemKind::Fn(box ast::Fn { ident, .. }) - | ast::ItemKind::Const(box ast::ConstItem { ident, .. }) - | ast::ItemKind::Static(box ast::StaticItem { ident, .. }) => { + ast::ItemKind::Fn(ast::Fn { ident, .. }) + | ast::ItemKind::Const(ast::ConstItem { ident, .. }) + | ast::ItemKind::Static(ast::StaticItem { ident, .. }) => { ident.span = ident.span.with_ctxt(sp.ctxt()); let test_path_symbol = Symbol::intern(&item_path( // skip the name of the root module @@ -114,7 +114,7 @@ pub(crate) fn expand_test_or_bench( ) -> Vec { let (item, is_stmt) = match item { Annotatable::Item(i) => (i, false), - Annotatable::Stmt(box ast::Stmt { kind: ast::StmtKind::Item(i), .. }) => (i, true), + Annotatable::Stmt(ast::Stmt { kind: ast::StmtKind::Item(i), .. }) => (i, true), other => { not_testable_error(cx, is_bench, attr_sp, None); return vec![other]; From 1a3617d217a57539147812ef880d6a90b0231e4f Mon Sep 17 00:00:00 2001 From: cyrgani Date: Thu, 7 May 2026 14:19:57 +0000 Subject: [PATCH 06/19] use `deref_patterns` in `rustc_const_eval` --- compiler/rustc_const_eval/src/check_consts/check.rs | 2 +- .../rustc_const_eval/src/check_consts/qualifs.rs | 2 +- compiler/rustc_const_eval/src/interpret/step.rs | 12 ++++++------ compiler/rustc_const_eval/src/lib.rs | 2 +- 4 files changed, 9 insertions(+), 9 deletions(-) diff --git a/compiler/rustc_const_eval/src/check_consts/check.rs b/compiler/rustc_const_eval/src/check_consts/check.rs index d7b18518aba91..283c9aff0394d 100644 --- a/compiler/rustc_const_eval/src/check_consts/check.rs +++ b/compiler/rustc_const_eval/src/check_consts/check.rs @@ -669,7 +669,7 @@ impl<'tcx> Visitor<'tcx> for Checker<'_, 'tcx> { } } - Rvalue::BinaryOp(op, box (lhs, rhs)) => { + Rvalue::BinaryOp(op, (lhs, rhs)) => { let lhs_ty = lhs.ty(self.body, self.tcx); let rhs_ty = rhs.ty(self.body, self.tcx); diff --git a/compiler/rustc_const_eval/src/check_consts/qualifs.rs b/compiler/rustc_const_eval/src/check_consts/qualifs.rs index 0410521034b6b..10bcb1732ba06 100644 --- a/compiler/rustc_const_eval/src/check_consts/qualifs.rs +++ b/compiler/rustc_const_eval/src/check_consts/qualifs.rs @@ -237,7 +237,7 @@ where | Rvalue::UnaryOp(_, operand) | Rvalue::Cast(_, operand, _) => in_operand::(cx, in_local, operand), - Rvalue::BinaryOp(_, box (lhs, rhs)) => { + Rvalue::BinaryOp(_, (lhs, rhs)) => { in_operand::(cx, in_local, lhs) || in_operand::(cx, in_local, rhs) } diff --git a/compiler/rustc_const_eval/src/interpret/step.rs b/compiler/rustc_const_eval/src/interpret/step.rs index 8376d0499990e..c60fb92a7a200 100644 --- a/compiler/rustc_const_eval/src/interpret/step.rs +++ b/compiler/rustc_const_eval/src/interpret/step.rs @@ -90,7 +90,7 @@ impl<'tcx, M: Machine<'tcx>> InterpCx<'tcx, M> { use rustc_middle::mir::StatementKind::*; match &stmt.kind { - Assign(box (place, rvalue)) => self.eval_rvalue_into_place(rvalue, *place)?, + Assign((place, rvalue)) => self.eval_rvalue_into_place(rvalue, *place)?, SetDiscriminant { place, variant_index } => { let dest = self.eval_place(**place)?; @@ -111,11 +111,11 @@ impl<'tcx, M: Machine<'tcx>> InterpCx<'tcx, M> { // interpreter is solely intended for borrowck'ed code. FakeRead(..) => {} - Intrinsic(box intrinsic) => self.eval_nondiverging_intrinsic(intrinsic)?, + Intrinsic(intrinsic) => self.eval_nondiverging_intrinsic(intrinsic)?, // Evaluate the place expression, without reading from it. - PlaceMention(box place) => { - let _ = self.eval_place(*place)?; + PlaceMention(place) => { + let _ = self.eval_place(**place)?; } // This exists purely to guide borrowck lifetime inference, and does not have @@ -179,7 +179,7 @@ impl<'tcx, M: Machine<'tcx>> InterpCx<'tcx, M> { CopyForDeref(_) => bug!("`CopyForDeref` in runtime MIR"), - BinaryOp(bin_op, box (ref left, ref right)) => { + BinaryOp(bin_op, (ref left, ref right)) => { let layout = util::binop_left_homogeneous(bin_op).then_some(dest.layout); let left = self.read_immediate(&self.eval_operand(left, layout)?)?; let layout = util::binop_right_homogeneous(bin_op).then_some(left.layout); @@ -197,7 +197,7 @@ impl<'tcx, M: Machine<'tcx>> InterpCx<'tcx, M> { self.write_immediate(*result, &dest)?; } - Aggregate(box ref kind, ref operands) => { + Aggregate(ref kind, ref operands) => { self.write_aggregate(kind, operands, &dest)?; } diff --git a/compiler/rustc_const_eval/src/lib.rs b/compiler/rustc_const_eval/src/lib.rs index 33da1c5ecf738..5ebcd0723f5b3 100644 --- a/compiler/rustc_const_eval/src/lib.rs +++ b/compiler/rustc_const_eval/src/lib.rs @@ -1,7 +1,7 @@ // tidy-alphabetical-start #![feature(array_try_map)] -#![feature(box_patterns)] #![feature(decl_macro)] +#![feature(deref_patterns)] #![feature(never_type)] #![feature(slice_ptr_get)] #![feature(trait_alias)] From 754c496a98f4cf7ad03d00764bf5255e2bacacaf Mon Sep 17 00:00:00 2001 From: cyrgani Date: Thu, 7 May 2026 15:13:32 +0000 Subject: [PATCH 07/19] use `deref_patterns` in `rustc_hir_typeck` --- compiler/rustc_hir_typeck/src/coercion.rs | 2 +- .../rustc_hir_typeck/src/fn_ctxt/adjust_fulfillment_errors.rs | 2 +- compiler/rustc_hir_typeck/src/lib.rs | 2 +- 3 files changed, 3 insertions(+), 3 deletions(-) diff --git a/compiler/rustc_hir_typeck/src/coercion.rs b/compiler/rustc_hir_typeck/src/coercion.rs index 9d9a42c132343..7a25b5e5e7a4e 100644 --- a/compiler/rustc_hir_typeck/src/coercion.rs +++ b/compiler/rustc_hir_typeck/src/coercion.rs @@ -1802,7 +1802,7 @@ impl<'tcx> CoerceMany<'tcx> { ); unsized_return = self.is_return_ty_definitely_unsized(fcx); } - ObligationCauseCode::MatchExpressionArm(box MatchExpressionArmCause { + ObligationCauseCode::MatchExpressionArm(MatchExpressionArmCause { arm_span, arm_ty, prior_arm_ty, diff --git a/compiler/rustc_hir_typeck/src/fn_ctxt/adjust_fulfillment_errors.rs b/compiler/rustc_hir_typeck/src/fn_ctxt/adjust_fulfillment_errors.rs index 68bf29cc32a59..ced961f11515f 100644 --- a/compiler/rustc_hir_typeck/src/fn_ctxt/adjust_fulfillment_errors.rs +++ b/compiler/rustc_hir_typeck/src/fn_ctxt/adjust_fulfillment_errors.rs @@ -484,7 +484,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { span: Span, ) -> bool { if let traits::FulfillmentErrorCode::Select(traits::SelectionError::SignatureMismatch( - box traits::SignatureMismatchData { expected_trait_ref, .. }, + traits::SignatureMismatchData { expected_trait_ref, .. }, )) = error.code && let ty::Closure(def_id, _) | ty::Coroutine(def_id, ..) = expected_trait_ref.self_ty().kind() diff --git a/compiler/rustc_hir_typeck/src/lib.rs b/compiler/rustc_hir_typeck/src/lib.rs index 15729bc311e57..55a01ddfba779 100644 --- a/compiler/rustc_hir_typeck/src/lib.rs +++ b/compiler/rustc_hir_typeck/src/lib.rs @@ -1,5 +1,5 @@ // tidy-alphabetical-start -#![feature(box_patterns)] +#![feature(deref_patterns)] #![feature(iter_intersperse)] #![feature(iter_order_by)] #![feature(never_type)] From 3e557c88cfbc90fbc4a2fe895a6dd09291239824 Mon Sep 17 00:00:00 2001 From: cyrgani Date: Thu, 7 May 2026 15:15:09 +0000 Subject: [PATCH 08/19] use `deref_patterns` in `rustc_lint` --- compiler/rustc_lint/src/builtin.rs | 6 +++--- compiler/rustc_lint/src/lib.rs | 2 +- compiler/rustc_lint/src/nonstandard_style.rs | 8 +++----- compiler/rustc_lint/src/precedence.rs | 2 +- compiler/rustc_lint/src/unused.rs | 4 ++-- 5 files changed, 10 insertions(+), 12 deletions(-) diff --git a/compiler/rustc_lint/src/builtin.rs b/compiler/rustc_lint/src/builtin.rs index 6a485ea06ee86..ea0791783a642 100644 --- a/compiler/rustc_lint/src/builtin.rs +++ b/compiler/rustc_lint/src/builtin.rs @@ -260,12 +260,12 @@ impl EarlyLintPass for UnsafeCode { fn check_item(&mut self, cx: &EarlyContext<'_>, it: &ast::Item) { match it.kind { - ast::ItemKind::Trait(box ast::Trait { safety: ast::Safety::Unsafe(_), .. }) => { + ast::ItemKind::Trait(ast::Trait { safety: ast::Safety::Unsafe(_), .. }) => { self.report_unsafe(cx, it.span, BuiltinUnsafe::UnsafeTrait); } ast::ItemKind::Impl(ast::Impl { - of_trait: Some(box ast::TraitImplHeader { safety: ast::Safety::Unsafe(_), .. }), + of_trait: Some(ast::TraitImplHeader { safety: ast::Safety::Unsafe(_), .. }), .. }) => { self.report_unsafe(cx, it.span, BuiltinUnsafe::UnsafeImpl); @@ -779,7 +779,7 @@ impl EarlyLintPass for AnonymousParameters { // This is a hard error in future editions; avoid linting and erroring return; } - if let ast::AssocItemKind::Fn(box Fn { ref sig, .. }) = it.kind { + if let ast::AssocItemKind::Fn(Fn { ref sig, .. }) = it.kind { for arg in sig.decl.inputs.iter() { if let ast::PatKind::Missing = arg.pat.kind { let ty_snip = cx.sess().source_map().span_to_snippet(arg.ty.span); diff --git a/compiler/rustc_lint/src/lib.rs b/compiler/rustc_lint/src/lib.rs index ea0e657f7edef..10fd1d1501b3b 100644 --- a/compiler/rustc_lint/src/lib.rs +++ b/compiler/rustc_lint/src/lib.rs @@ -21,7 +21,7 @@ // tidy-alphabetical-start #![allow(internal_features)] -#![feature(box_patterns)] +#![feature(deref_patterns)] #![feature(iter_order_by)] #![feature(rustc_attrs)] #![feature(titlecase)] diff --git a/compiler/rustc_lint/src/nonstandard_style.rs b/compiler/rustc_lint/src/nonstandard_style.rs index 6cec7b0efd82f..fbbfbd86d319f 100644 --- a/compiler/rustc_lint/src/nonstandard_style.rs +++ b/compiler/rustc_lint/src/nonstandard_style.rs @@ -169,14 +169,12 @@ impl EarlyLintPass for NonCamelCaseTypes { } match &it.kind { - ast::ItemKind::TyAlias(box ast::TyAlias { ident, .. }) + ast::ItemKind::TyAlias(ast::TyAlias { ident, .. }) | ast::ItemKind::Enum(ident, ..) | ast::ItemKind::Struct(ident, ..) | ast::ItemKind::Union(ident, ..) => self.check_case(cx, "type", ident), - ast::ItemKind::Trait(box ast::Trait { ident, .. }) => { - self.check_case(cx, "trait", ident) - } - ast::ItemKind::TraitAlias(box ast::TraitAlias { ident, .. }) => { + ast::ItemKind::Trait(ast::Trait { ident, .. }) => self.check_case(cx, "trait", ident), + ast::ItemKind::TraitAlias(ast::TraitAlias { ident, .. }) => { self.check_case(cx, "trait alias", ident) } diff --git a/compiler/rustc_lint/src/precedence.rs b/compiler/rustc_lint/src/precedence.rs index 52321e25c7d43..7c073e5025b9b 100644 --- a/compiler/rustc_lint/src/precedence.rs +++ b/compiler/rustc_lint/src/precedence.rs @@ -43,7 +43,7 @@ impl EarlyLintPass for Precedence { let mut arg = operand; let mut at_least_one = false; - while let ExprKind::MethodCall(box MethodCall { receiver, .. }) = &arg.kind { + while let ExprKind::MethodCall(MethodCall { receiver, .. }) = &arg.kind { at_least_one = true; arg = receiver; } diff --git a/compiler/rustc_lint/src/unused.rs b/compiler/rustc_lint/src/unused.rs index 9f15f41955d86..0cb7b4cce8462 100644 --- a/compiler/rustc_lint/src/unused.rs +++ b/compiler/rustc_lint/src/unused.rs @@ -499,9 +499,9 @@ trait UnusedDelimLint { fn check_item(&mut self, cx: &EarlyContext<'_>, item: &ast::Item) { use ast::ItemKind::*; - let expr = if let Const(box ast::ConstItem { rhs_kind, .. }) = &item.kind { + let expr = if let Const(ast::ConstItem { rhs_kind, .. }) = &item.kind { if let Some(e) = rhs_kind.expr() { e } else { return } - } else if let Static(box ast::StaticItem { expr: Some(expr), .. }) = &item.kind { + } else if let Static(ast::StaticItem { expr: Some(expr), .. }) = &item.kind { expr } else { return; From 74c4e77de758bdcc9b38a0fea868f591b078c4ef Mon Sep 17 00:00:00 2001 From: cyrgani Date: Thu, 7 May 2026 15:25:00 +0000 Subject: [PATCH 09/19] use `deref_patterns` in `rustc_parse` --- compiler/rustc_parse/src/lib.rs | 2 +- compiler/rustc_parse/src/parser/item.rs | 6 +++--- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/compiler/rustc_parse/src/lib.rs b/compiler/rustc_parse/src/lib.rs index 4bfa899352393..7805994b441b8 100644 --- a/compiler/rustc_parse/src/lib.rs +++ b/compiler/rustc_parse/src/lib.rs @@ -2,9 +2,9 @@ // tidy-alphabetical-start #![cfg_attr(test, feature(iter_order_by))] -#![feature(box_patterns)] #![feature(debug_closure_helpers)] #![feature(default_field_values)] +#![feature(deref_patterns)] #![feature(iter_intersperse)] #![recursion_limit = "256"] // tidy-alphabetical-end diff --git a/compiler/rustc_parse/src/parser/item.rs b/compiler/rustc_parse/src/parser/item.rs index bd45bbb6a8582..68fda3b86ddcb 100644 --- a/compiler/rustc_parse/src/parser/item.rs +++ b/compiler/rustc_parse/src/parser/item.rs @@ -1219,7 +1219,7 @@ impl<'a> Parser<'a> { let kind = match AssocItemKind::try_from(kind) { Ok(kind) => kind, Err(kind) => match kind { - ItemKind::Static(box StaticItem { + ItemKind::Static(StaticItem { ident, ty, safety: _, @@ -1475,7 +1475,7 @@ impl<'a> Parser<'a> { let kind = match ForeignItemKind::try_from(kind) { Ok(kind) => kind, Err(kind) => match kind { - ItemKind::Const(box ConstItem { ident, ty, rhs_kind, .. }) => { + ItemKind::Const(ConstItem { ident, ty, rhs_kind, .. }) => { let const_span = Some(span.with_hi(ident.span.lo())) .filter(|span| span.can_be_used_for_suggestions()); self.dcx().emit_err(errors::ExternItemCannotBeConst { @@ -1510,7 +1510,7 @@ impl<'a> Parser<'a> { let span = self.psess.source_map().guess_head_span(span); let descr = kind.descr(); let help = match kind { - ItemKind::DelegationMac(box DelegationMac { + ItemKind::DelegationMac(DelegationMac { suffixes: DelegationSuffixes::Glob(_), .. }) => false, From 985fe3482177b9225c4551a9ca836af8c4e8dd34 Mon Sep 17 00:00:00 2001 From: cyrgani Date: Thu, 7 May 2026 15:27:06 +0000 Subject: [PATCH 10/19] use `deref_patterns` in `rustc_resolve` --- .../rustc_resolve/src/build_reduced_graph.rs | 16 ++--- compiler/rustc_resolve/src/def_collector.rs | 14 ++--- compiler/rustc_resolve/src/late.rs | 59 +++++++++---------- .../rustc_resolve/src/late/diagnostics.rs | 14 ++--- compiler/rustc_resolve/src/lib.rs | 2 +- 5 files changed, 49 insertions(+), 56 deletions(-) diff --git a/compiler/rustc_resolve/src/build_reduced_graph.rs b/compiler/rustc_resolve/src/build_reduced_graph.rs index 61da931df4d5d..5d60fe8464052 100644 --- a/compiler/rustc_resolve/src/build_reduced_graph.rs +++ b/compiler/rustc_resolve/src/build_reduced_graph.rs @@ -866,12 +866,12 @@ impl<'a, 'ra, 'tcx> DefCollector<'a, 'ra, 'tcx> { } // These items live in the value namespace. - ItemKind::Const(box ConstItem { ident, .. }) - | ItemKind::Delegation(box Delegation { ident, .. }) - | ItemKind::Static(box StaticItem { ident, .. }) => { + ItemKind::Const(ConstItem { ident, .. }) + | ItemKind::Delegation(Delegation { ident, .. }) + | ItemKind::Static(StaticItem { ident, .. }) => { self.r.define_local(parent, ident, ValueNS, res, vis, sp, expansion); } - ItemKind::Fn(box Fn { ident, .. }) => { + ItemKind::Fn(Fn { ident, .. }) => { self.r.define_local(parent, ident, ValueNS, res, vis, sp, expansion); // Functions introducing procedural macros reserve a slot @@ -880,12 +880,12 @@ impl<'a, 'ra, 'tcx> DefCollector<'a, 'ra, 'tcx> { } // These items live in the type namespace. - ItemKind::TyAlias(box TyAlias { ident, .. }) - | ItemKind::TraitAlias(box TraitAlias { ident, .. }) => { + ItemKind::TyAlias(TyAlias { ident, .. }) + | ItemKind::TraitAlias(TraitAlias { ident, .. }) => { self.r.define_local(parent, ident, TypeNS, res, vis, sp, expansion); } - ItemKind::Enum(ident, _, _) | ItemKind::Trait(box ast::Trait { ident, .. }) => { + ItemKind::Enum(ident, _, _) | ItemKind::Trait(ast::Trait { ident, .. }) => { self.r.define_local(parent, ident, TypeNS, res, vis, sp, expansion); let module = self.r.new_local_module( @@ -1295,7 +1295,7 @@ impl<'a, 'ra, 'tcx> DefCollector<'a, 'ra, 'tcx> { ItemKind::MacroDef(ident, def) => { (self.res(def_id), *ident, item.span, def.macro_rules) } - ItemKind::Fn(box ast::Fn { ident: fn_ident, .. }) => { + ItemKind::Fn(ast::Fn { ident: fn_ident, .. }) => { match self.proc_macro_stub(item, *fn_ident) { Some((macro_kind, ident, span)) => { let macro_kinds = macro_kind.into(); diff --git a/compiler/rustc_resolve/src/def_collector.rs b/compiler/rustc_resolve/src/def_collector.rs index b5f46052f03e3..06c9038d90430 100644 --- a/compiler/rustc_resolve/src/def_collector.rs +++ b/compiler/rustc_resolve/src/def_collector.rs @@ -257,7 +257,7 @@ impl<'a, 'ra, 'tcx> visit::Visitor<'a> for DefCollector<'a, 'ra, 'tcx> { fn visit_foreign_item(&mut self, fi: &'a ForeignItem) { let (ident, def_kind) = match fi.kind { - ForeignItemKind::Static(box StaticItem { + ForeignItemKind::Static(StaticItem { ident, ty: _, mutability, @@ -273,8 +273,8 @@ impl<'a, 'ra, 'tcx> visit::Visitor<'a> for DefCollector<'a, 'ra, 'tcx> { (ident, DefKind::Static { safety, mutability, nested: false }) } - ForeignItemKind::Fn(box Fn { ident, .. }) => (ident, DefKind::Fn), - ForeignItemKind::TyAlias(box TyAlias { ident, .. }) => (ident, DefKind::ForeignTy), + ForeignItemKind::Fn(Fn { ident, .. }) => (ident, DefKind::Fn), + ForeignItemKind::TyAlias(TyAlias { ident, .. }) => (ident, DefKind::ForeignTy), ForeignItemKind::MacCall(_) => { self.visit_invoc_in_module(fi.id); self.visit_macro_invoc(fi.id); @@ -344,18 +344,18 @@ impl<'a, 'ra, 'tcx> visit::Visitor<'a> for DefCollector<'a, 'ra, 'tcx> { fn visit_assoc_item(&mut self, i: &'a AssocItem, ctxt: visit::AssocCtxt) { let (ident, def_kind, ns) = match &i.kind { - AssocItemKind::Fn(box Fn { ident, .. }) - | AssocItemKind::Delegation(box Delegation { ident, .. }) => { + AssocItemKind::Fn(Fn { ident, .. }) + | AssocItemKind::Delegation(Delegation { ident, .. }) => { (*ident, DefKind::AssocFn, ValueNS) } - AssocItemKind::Const(box ConstItem { ident, rhs_kind, .. }) => ( + AssocItemKind::Const(ConstItem { ident, rhs_kind, .. }) => ( *ident, DefKind::AssocConst { is_type_const: matches!(rhs_kind, ConstItemRhsKind::TypeConst { .. }), }, ValueNS, ), - AssocItemKind::Type(box TyAlias { ident, .. }) => (*ident, DefKind::AssocTy, TypeNS), + AssocItemKind::Type(TyAlias { ident, .. }) => (*ident, DefKind::AssocTy, TypeNS), AssocItemKind::MacCall(..) => { self.visit_macro_invoc(i.id); self.visit_assoc_item_mac_call(i, ctxt); diff --git a/compiler/rustc_resolve/src/late.rs b/compiler/rustc_resolve/src/late.rs index 3337a4626b040..165800719fd24 100644 --- a/compiler/rustc_resolve/src/late.rs +++ b/compiler/rustc_resolve/src/late.rs @@ -1045,7 +1045,7 @@ impl<'ast, 'ra, 'tcx> Visitor<'ast> for LateResolutionVisitor<'_, 'ast, 'ra, 'tc self.resolve_doc_links(&foreign_item.attrs, MaybeExported::Ok(foreign_item.id)); let def_kind = self.r.local_def_kind(foreign_item.id); match foreign_item.kind { - ForeignItemKind::TyAlias(box TyAlias { ref generics, .. }) => { + ForeignItemKind::TyAlias(TyAlias { ref generics, .. }) => { self.with_generic_param_rib( &generics.params, RibKind::Item(HasGenericParams::Yes(generics.span), def_kind), @@ -1055,7 +1055,7 @@ impl<'ast, 'ra, 'tcx> Visitor<'ast> for LateResolutionVisitor<'_, 'ast, 'ra, 'tc |this| visit::walk_item(this, foreign_item), ); } - ForeignItemKind::Fn(box Fn { ref generics, .. }) => { + ForeignItemKind::Fn(Fn { ref generics, .. }) => { self.with_generic_param_rib( &generics.params, RibKind::Item(HasGenericParams::Yes(generics.span), def_kind), @@ -2809,7 +2809,7 @@ impl<'a, 'ast, 'ra, 'tcx> LateResolutionVisitor<'a, 'ast, 'ra, 'tcx> { let def_kind = self.r.local_def_kind(item.id); match &item.kind { - ItemKind::TyAlias(box TyAlias { generics, .. }) => { + ItemKind::TyAlias(TyAlias { generics, .. }) => { self.with_generic_param_rib( &generics.params, RibKind::Item(HasGenericParams::Yes(generics.span), def_kind), @@ -2820,7 +2820,7 @@ impl<'a, 'ast, 'ra, 'tcx> LateResolutionVisitor<'a, 'ast, 'ra, 'tcx> { ); } - ItemKind::Fn(box Fn { generics, define_opaque, .. }) => { + ItemKind::Fn(Fn { generics, define_opaque, .. }) => { self.with_generic_param_rib( &generics.params, RibKind::Item(HasGenericParams::Yes(generics.span), def_kind), @@ -2851,7 +2851,7 @@ impl<'a, 'ast, 'ra, 'tcx> LateResolutionVisitor<'a, 'ast, 'ra, 'tcx> { self.diag_metadata.current_impl_items = None; } - ItemKind::Trait(box Trait { generics, bounds, items, impl_restriction, .. }) => { + ItemKind::Trait(Trait { generics, bounds, items, impl_restriction, .. }) => { // resolve paths for `impl` restrictions self.resolve_impl_restriction_path(impl_restriction); @@ -2873,7 +2873,7 @@ impl<'a, 'ast, 'ra, 'tcx> LateResolutionVisitor<'a, 'ast, 'ra, 'tcx> { ); } - ItemKind::TraitAlias(box TraitAlias { generics, bounds, .. }) => { + ItemKind::TraitAlias(TraitAlias { generics, bounds, .. }) => { // Create a new rib for the trait-wide type parameters. self.with_generic_param_rib( &generics.params, @@ -2913,13 +2913,8 @@ impl<'a, 'ast, 'ra, 'tcx> LateResolutionVisitor<'a, 'ast, 'ra, 'tcx> { self.parent_scope.module = orig_module; } - ItemKind::Static(box ast::StaticItem { - ident, - ty, - expr, - define_opaque, - eii_impls, - .. + ItemKind::Static(ast::StaticItem { + ident, ty, expr, define_opaque, eii_impls, .. }) => { self.with_static_rib(def_kind, |this| { this.with_lifetime_rib(LifetimeRibKind::Elided(LifetimeRes::Static), |this| { @@ -2935,7 +2930,7 @@ impl<'a, 'ast, 'ra, 'tcx> LateResolutionVisitor<'a, 'ast, 'ra, 'tcx> { self.resolve_eii(&eii_impls); } - ItemKind::Const(box ast::ConstItem { + ItemKind::Const(ast::ConstItem { ident, generics, ty, @@ -3333,7 +3328,7 @@ impl<'a, 'ast, 'ra, 'tcx> LateResolutionVisitor<'a, 'ast, 'ra, 'tcx> { for item in trait_items { self.resolve_doc_links(&item.attrs, MaybeExported::Ok(item.id)); match &item.kind { - AssocItemKind::Const(box ast::ConstItem { + AssocItemKind::Const(ast::ConstItem { generics, ty, rhs_kind, @@ -3385,7 +3380,7 @@ impl<'a, 'ast, 'ra, 'tcx> LateResolutionVisitor<'a, 'ast, 'ra, 'tcx> { self.resolve_define_opaques(define_opaque); } - AssocItemKind::Fn(box Fn { generics, define_opaque, .. }) => { + AssocItemKind::Fn(Fn { generics, define_opaque, .. }) => { walk_assoc_item(self, generics, LifetimeBinderKind::Function, item); self.resolve_define_opaques(define_opaque); @@ -3400,7 +3395,7 @@ impl<'a, 'ast, 'ra, 'tcx> LateResolutionVisitor<'a, 'ast, 'ra, 'tcx> { |this| this.resolve_delegation(delegation, item.id, false), ); } - AssocItemKind::Type(box TyAlias { generics, .. }) => self + AssocItemKind::Type(TyAlias { generics, .. }) => self .with_lifetime_rib(LifetimeRibKind::AnonymousReportError, |this| { walk_assoc_item(this, generics, LifetimeBinderKind::Item, item) }), @@ -3551,7 +3546,7 @@ impl<'a, 'ast, 'ra, 'tcx> LateResolutionVisitor<'a, 'ast, 'ra, 'tcx> { let prev = self.diag_metadata.current_impl_item.take(); self.diag_metadata.current_impl_item = Some(&item); match &item.kind { - AssocItemKind::Const(box ast::ConstItem { + AssocItemKind::Const(ast::ConstItem { ident, generics, ty, @@ -3632,7 +3627,7 @@ impl<'a, 'ast, 'ra, 'tcx> LateResolutionVisitor<'a, 'ast, 'ra, 'tcx> { ); self.resolve_define_opaques(define_opaque); } - AssocItemKind::Fn(box Fn { ident, generics, define_opaque, .. }) => { + AssocItemKind::Fn(Fn { ident, generics, define_opaque, .. }) => { debug!("resolve_implementation AssocItemKind::Fn"); // We also need a new scope for the impl item type parameters. self.with_generic_param_rib( @@ -3660,7 +3655,7 @@ impl<'a, 'ast, 'ra, 'tcx> LateResolutionVisitor<'a, 'ast, 'ra, 'tcx> { self.resolve_define_opaques(define_opaque); } - AssocItemKind::Type(box TyAlias { ident, generics, .. }) => { + AssocItemKind::Type(TyAlias { ident, generics, .. }) => { self.diag_metadata.in_non_gat_assoc_type = Some(generics.params.is_empty()); debug!("resolve_implementation AssocItemKind::Type"); // We also need a new scope for the impl item type parameters. @@ -3690,7 +3685,7 @@ impl<'a, 'ast, 'ra, 'tcx> LateResolutionVisitor<'a, 'ast, 'ra, 'tcx> { ); self.diag_metadata.in_non_gat_assoc_type = None; } - AssocItemKind::Delegation(box delegation) => { + AssocItemKind::Delegation(delegation) => { debug!("resolve_implementation AssocItemKind::Delegation"); self.with_generic_param_rib( &[], @@ -5245,7 +5240,7 @@ impl<'a, 'ast, 'ra, 'tcx> LateResolutionVisitor<'a, 'ast, 'ra, 'tcx> { ExprKind::Field(ref subexpression, _) => { self.resolve_expr(subexpression, Some(expr)); } - ExprKind::MethodCall(box MethodCall { ref seg, ref receiver, ref args, .. }) => { + ExprKind::MethodCall(MethodCall { ref seg, ref receiver, ref args, .. }) => { self.resolve_expr(receiver, Some(expr)); for arg in args { self.resolve_expr(arg, None); @@ -5277,7 +5272,7 @@ impl<'a, 'ast, 'ra, 'tcx> LateResolutionVisitor<'a, 'ast, 'ra, 'tcx> { visit::walk_expr(self, expr); } // For closures, RibKind::FnOrCoroutine is added in visit_fn - ExprKind::Closure(box ast::Closure { + ExprKind::Closure(ast::Closure { binder: ClosureBinder::For { ref generic_params, span }, .. }) => { @@ -5577,16 +5572,16 @@ fn required_generic_args_suggestion(generics: &ast::Generics) -> Option impl<'ast> Visitor<'ast> for ItemInfoCollector<'_, '_, '_> { fn visit_item(&mut self, item: &'ast Item) { match &item.kind { - ItemKind::TyAlias(box TyAlias { generics, .. }) - | ItemKind::Const(box ConstItem { generics, .. }) - | ItemKind::Fn(box Fn { generics, .. }) + ItemKind::TyAlias(TyAlias { generics, .. }) + | ItemKind::Const(ConstItem { generics, .. }) + | ItemKind::Fn(Fn { generics, .. }) | ItemKind::Enum(_, generics, _) | ItemKind::Struct(_, generics, _) | ItemKind::Union(_, generics, _) | ItemKind::Impl(Impl { generics, .. }) - | ItemKind::Trait(box Trait { generics, .. }) - | ItemKind::TraitAlias(box TraitAlias { generics, .. }) => { - if let ItemKind::Fn(box Fn { sig, .. }) = &item.kind { + | ItemKind::Trait(Trait { generics, .. }) + | ItemKind::TraitAlias(TraitAlias { generics, .. }) => { + if let ItemKind::Fn(Fn { sig, .. }) = &item.kind { self.collect_fn_info(&sig.decl, item.id); } @@ -5601,7 +5596,7 @@ impl<'ast> Visitor<'ast> for ItemInfoCollector<'_, '_, '_> { ItemKind::ForeignMod(ForeignMod { items, .. }) => { for foreign_item in items { - if let ForeignItemKind::Fn(box Fn { sig, .. }) = &foreign_item.kind { + if let ForeignItemKind::Fn(Fn { sig, .. }) = &foreign_item.kind { self.collect_fn_info(&sig.decl, foreign_item.id); } } @@ -5627,11 +5622,11 @@ impl<'ast> Visitor<'ast> for ItemInfoCollector<'_, '_, '_> { } fn visit_assoc_item(&mut self, item: &'ast AssocItem, ctxt: AssocCtxt) { - if let AssocItemKind::Fn(box Fn { sig, .. }) = &item.kind { + if let AssocItemKind::Fn(Fn { sig, .. }) = &item.kind { self.collect_fn_info(&sig.decl, item.id); } - if let AssocItemKind::Type(box ast::TyAlias { generics, .. }) = &item.kind { + if let AssocItemKind::Type(ast::TyAlias { generics, .. }) = &item.kind { let def_id = self.r.local_def_id(item.id); if let Some(suggestion) = required_generic_args_suggestion(generics) { self.r.item_required_generic_args_suggestions.insert(def_id, suggestion); diff --git a/compiler/rustc_resolve/src/late/diagnostics.rs b/compiler/rustc_resolve/src/late/diagnostics.rs index 6f86759d46c5f..82fa171a1e585 100644 --- a/compiler/rustc_resolve/src/late/diagnostics.rs +++ b/compiler/rustc_resolve/src/late/diagnostics.rs @@ -322,9 +322,9 @@ impl<'ast, 'ra, 'tcx> LateResolutionVisitor<'_, 'ast, 'ra, 'tcx> { && let Some(assoc) = self.diag_metadata.current_impl_item { let generics = match &assoc.kind { - AssocItemKind::Const(box ast::ConstItem { generics, .. }) - | AssocItemKind::Fn(box ast::Fn { generics, .. }) - | AssocItemKind::Type(box ast::TyAlias { generics, .. }) => Some(generics), + AssocItemKind::Const(ast::ConstItem { generics, .. }) + | AssocItemKind::Fn(ast::Fn { generics, .. }) + | AssocItemKind::Type(ast::TyAlias { generics, .. }) => Some(generics), AssocItemKind::Delegation(..) | AssocItemKind::MacCall(..) | AssocItemKind::DelegationMac(..) => None, @@ -2073,9 +2073,7 @@ impl<'ast, 'ra, 'tcx> LateResolutionVisitor<'_, 'ast, 'ra, 'tcx> { let (lhs_span, rhs_span) = match &expr.kind { ExprKind::Field(base, ident) => (base.span, ident.span), - ExprKind::MethodCall(box MethodCall { receiver, span, .. }) => { - (receiver.span, *span) - } + ExprKind::MethodCall(MethodCall { receiver, span, .. }) => (receiver.span, *span), _ => return false, }; @@ -2767,7 +2765,7 @@ impl<'ast, 'ra, 'tcx> LateResolutionVisitor<'_, 'ast, 'ra, 'tcx> { { return Some(match &assoc_item.kind { ast::AssocItemKind::Const(..) => AssocSuggestion::AssocConst, - ast::AssocItemKind::Fn(box ast::Fn { sig, .. }) if sig.decl.has_self() => { + ast::AssocItemKind::Fn(ast::Fn { sig, .. }) if sig.decl.has_self() => { AssocSuggestion::MethodWithSelf { called } } ast::AssocItemKind::Fn(..) => AssocSuggestion::AssocFn { called }, @@ -3108,7 +3106,7 @@ impl<'ast, 'ra, 'tcx> LateResolutionVisitor<'_, 'ast, 'ra, 'tcx> { ExprKind::Call(..) => (None, true), // `Type.Foo(a, b)`, suggest replacing `.` -> `::` if variant `Foo` exists and is a tuple variant, // otherwise suggest adding a variant after `Type`. - ExprKind::MethodCall(box MethodCall { + ExprKind::MethodCall(MethodCall { receiver, span, seg: PathSegment { ident, .. }, diff --git a/compiler/rustc_resolve/src/lib.rs b/compiler/rustc_resolve/src/lib.rs index 879a4dd3983a6..0454cb6e783cd 100644 --- a/compiler/rustc_resolve/src/lib.rs +++ b/compiler/rustc_resolve/src/lib.rs @@ -9,11 +9,11 @@ // tidy-alphabetical-start #![allow(internal_features)] #![feature(arbitrary_self_types)] -#![feature(box_patterns)] #![feature(const_default)] #![feature(const_trait_impl)] #![feature(control_flow_into_value)] #![feature(default_field_values)] +#![feature(deref_patterns)] #![feature(iter_intersperse)] #![feature(rustc_attrs)] #![feature(trim_prefix_suffix)] From 52db3c4580f82dcda23221e767377069f37b1a10 Mon Sep 17 00:00:00 2001 From: cyrgani Date: Thu, 7 May 2026 15:28:08 +0000 Subject: [PATCH 11/19] use `deref_patterns` in `rustc_ty_utils` --- compiler/rustc_ty_utils/src/consts.rs | 2 +- compiler/rustc_ty_utils/src/lib.rs | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/compiler/rustc_ty_utils/src/consts.rs b/compiler/rustc_ty_utils/src/consts.rs index 8ed32df656454..24415c5a50e97 100644 --- a/compiler/rustc_ty_utils/src/consts.rs +++ b/compiler/rustc_ty_utils/src/consts.rs @@ -105,7 +105,7 @@ fn recurse_build<'tcx>( // } // ``` ExprKind::Block { block } => { - if let thir::Block { stmts: box [], expr: Some(e), .. } = &body.blocks[*block] { + if let thir::Block { stmts: [], expr: Some(e), .. } = &body.blocks[*block] { recurse_build(tcx, body, *e, root_span)? } else { maybe_supported_error(GenericConstantTooComplexSub::BlockNotSupported(node.span))? diff --git a/compiler/rustc_ty_utils/src/lib.rs b/compiler/rustc_ty_utils/src/lib.rs index 5f42a134ec9af..7cc68cc54a92c 100644 --- a/compiler/rustc_ty_utils/src/lib.rs +++ b/compiler/rustc_ty_utils/src/lib.rs @@ -6,7 +6,7 @@ // tidy-alphabetical-start #![feature(associated_type_defaults)] -#![feature(box_patterns)] +#![feature(deref_patterns)] #![feature(iterator_try_collect)] #![feature(never_type)] // tidy-alphabetical-end From 82ebc72b9244deb2e29e8baf9b656aa1f9679360 Mon Sep 17 00:00:00 2001 From: cyrgani Date: Thu, 7 May 2026 15:29:33 +0000 Subject: [PATCH 12/19] use `deref_patterns` in `rustc_trait_selection` --- .../src/error_reporting/infer/mod.rs | 21 +++++++++---------- .../mismatched_static_lifetime.rs | 2 +- .../nice_region_error/placeholder_error.rs | 16 +++++++------- .../src/error_reporting/infer/region.rs | 10 ++++----- .../src/error_reporting/infer/suggest.rs | 4 ++-- .../traits/fulfillment_errors.rs | 4 ++-- compiler/rustc_trait_selection/src/lib.rs | 2 +- 7 files changed, 29 insertions(+), 30 deletions(-) diff --git a/compiler/rustc_trait_selection/src/error_reporting/infer/mod.rs b/compiler/rustc_trait_selection/src/error_reporting/infer/mod.rs index 887b0804c2296..c9e2312895820 100644 --- a/compiler/rustc_trait_selection/src/error_reporting/infer/mod.rs +++ b/compiler/rustc_trait_selection/src/error_reporting/infer/mod.rs @@ -432,7 +432,7 @@ impl<'a, 'tcx> TypeErrCtxt<'a, 'tcx> { } } } - ObligationCauseCode::MatchExpressionArm(box MatchExpressionArmCause { + ObligationCauseCode::MatchExpressionArm(MatchExpressionArmCause { arm_block_id, arm_span, arm_ty, @@ -1910,9 +1910,8 @@ impl<'a, 'tcx> TypeErrCtxt<'a, 'tcx> { } } let code = trace.cause.code(); - if let &(ObligationCauseCode::MatchExpressionArm(box MatchExpressionArmCause { - source, - .. + if let &(ObligationCauseCode::MatchExpressionArm(MatchExpressionArmCause { + source, .. }) | ObligationCauseCode::BlockTailExpression(.., source)) = code && let hir::MatchSource::TryDesugar(_) = source @@ -2302,14 +2301,14 @@ impl<'tcx> ObligationCause<'tcx> { ObligationCauseCode::BlockTailExpression(.., hir::MatchSource::TryDesugar(_)) => { ObligationCauseFailureCode::TryCompat { span, subdiags } } - ObligationCauseCode::MatchExpressionArm(box MatchExpressionArmCause { - source, .. - }) => match source { - hir::MatchSource::TryDesugar(_) => { - ObligationCauseFailureCode::TryCompat { span, subdiags } + ObligationCauseCode::MatchExpressionArm(MatchExpressionArmCause { source, .. }) => { + match source { + hir::MatchSource::TryDesugar(_) => { + ObligationCauseFailureCode::TryCompat { span, subdiags } + } + _ => ObligationCauseFailureCode::MatchCompat { span, subdiags }, } - _ => ObligationCauseFailureCode::MatchCompat { span, subdiags }, - }, + } ObligationCauseCode::IfExpression { .. } => { ObligationCauseFailureCode::IfElseDifferent { span, subdiags } } diff --git a/compiler/rustc_trait_selection/src/error_reporting/infer/nice_region_error/mismatched_static_lifetime.rs b/compiler/rustc_trait_selection/src/error_reporting/infer/nice_region_error/mismatched_static_lifetime.rs index 711aab43d9e7b..4422980051afb 100644 --- a/compiler/rustc_trait_selection/src/error_reporting/infer/nice_region_error/mismatched_static_lifetime.rs +++ b/compiler/rustc_trait_selection/src/error_reporting/infer/nice_region_error/mismatched_static_lifetime.rs @@ -28,7 +28,7 @@ impl<'a, 'tcx> NiceRegionError<'a, 'tcx> { if !sub.is_static() { return None; } - let SubregionOrigin::Subtype(box TypeTrace { ref cause, .. }) = origin else { + let SubregionOrigin::Subtype(TypeTrace { ref cause, .. }) = origin else { return None; }; // If we added a "points at argument expression" obligation, we remove it here, we care diff --git a/compiler/rustc_trait_selection/src/error_reporting/infer/nice_region_error/placeholder_error.rs b/compiler/rustc_trait_selection/src/error_reporting/infer/nice_region_error/placeholder_error.rs index 9cf016019bb09..fdbf4cf228de9 100644 --- a/compiler/rustc_trait_selection/src/error_reporting/infer/nice_region_error/placeholder_error.rs +++ b/compiler/rustc_trait_selection/src/error_reporting/infer/nice_region_error/placeholder_error.rs @@ -71,7 +71,7 @@ impl<'tcx> NiceRegionError<'_, 'tcx> { Some(RegionResolutionError::SubSupConflict( vid, _, - SubregionOrigin::Subtype(box TypeTrace { cause, values }), + SubregionOrigin::Subtype(TypeTrace { cause, values }), sub_placeholder @ Region(Interned(RePlaceholder(_), _)), _, sup_placeholder @ Region(Interned(RePlaceholder(_), _)), @@ -87,7 +87,7 @@ impl<'tcx> NiceRegionError<'_, 'tcx> { Some(RegionResolutionError::SubSupConflict( vid, _, - SubregionOrigin::Subtype(box TypeTrace { cause, values }), + SubregionOrigin::Subtype(TypeTrace { cause, values }), sub_placeholder @ Region(Interned(RePlaceholder(_), _)), _, _, @@ -103,7 +103,7 @@ impl<'tcx> NiceRegionError<'_, 'tcx> { Some(RegionResolutionError::SubSupConflict( vid, _, - SubregionOrigin::Subtype(box TypeTrace { cause, values }), + SubregionOrigin::Subtype(TypeTrace { cause, values }), _, _, sup_placeholder @ Region(Interned(RePlaceholder(_), _)), @@ -121,7 +121,7 @@ impl<'tcx> NiceRegionError<'_, 'tcx> { _, _, _, - SubregionOrigin::Subtype(box TypeTrace { cause, values }), + SubregionOrigin::Subtype(TypeTrace { cause, values }), sup_placeholder @ Region(Interned(RePlaceholder(_), _)), _, )) => self.try_report_trait_placeholder_mismatch( @@ -136,7 +136,7 @@ impl<'tcx> NiceRegionError<'_, 'tcx> { vid, _, _, - SubregionOrigin::Subtype(box TypeTrace { cause, values }), + SubregionOrigin::Subtype(TypeTrace { cause, values }), sup_placeholder @ Region(Interned(RePlaceholder(_), _)), )) => self.try_report_trait_placeholder_mismatch( Some(ty::Region::new_var(self.tcx(), *vid)), @@ -147,7 +147,7 @@ impl<'tcx> NiceRegionError<'_, 'tcx> { ), Some(RegionResolutionError::ConcreteFailure( - SubregionOrigin::Subtype(box TypeTrace { cause, values }), + SubregionOrigin::Subtype(TypeTrace { cause, values }), sub_region @ Region(Interned(RePlaceholder(_), _)), sup_region @ Region(Interned(RePlaceholder(_), _)), )) => self.try_report_trait_placeholder_mismatch( @@ -159,7 +159,7 @@ impl<'tcx> NiceRegionError<'_, 'tcx> { ), Some(RegionResolutionError::ConcreteFailure( - SubregionOrigin::Subtype(box TypeTrace { cause, values }), + SubregionOrigin::Subtype(TypeTrace { cause, values }), sub_region @ Region(Interned(RePlaceholder(_), _)), sup_region, )) => self.try_report_trait_placeholder_mismatch( @@ -171,7 +171,7 @@ impl<'tcx> NiceRegionError<'_, 'tcx> { ), Some(RegionResolutionError::ConcreteFailure( - SubregionOrigin::Subtype(box TypeTrace { cause, values }), + SubregionOrigin::Subtype(TypeTrace { cause, values }), sub_region, sup_region @ Region(Interned(RePlaceholder(_), _)), )) => self.try_report_trait_placeholder_mismatch( diff --git a/compiler/rustc_trait_selection/src/error_reporting/infer/region.rs b/compiler/rustc_trait_selection/src/error_reporting/infer/region.rs index 2e9dcae700d2a..232fcf7e43809 100644 --- a/compiler/rustc_trait_selection/src/error_reporting/infer/region.rs +++ b/compiler/rustc_trait_selection/src/error_reporting/infer/region.rs @@ -303,10 +303,10 @@ impl<'a, 'tcx> TypeErrCtxt<'a, 'tcx> { sup: Region<'tcx>, ) -> Diag<'a> { let mut err = match origin { - SubregionOrigin::Subtype(box trace) => { + SubregionOrigin::Subtype(trace) => { let terr = TypeError::RegionsDoesNotOutlive(sup, sub); let mut err = self.report_and_explain_type_error( - trace, + *trace, self.tcx.param_env(generic_param_scope), terr, ); @@ -631,7 +631,7 @@ impl<'a, 'tcx> TypeErrCtxt<'a, 'tcx> { // I can't think how to do better than this right now. -nikomatsakis debug!(?placeholder_origin, ?sub, ?sup, "report_placeholder_failure"); match placeholder_origin { - SubregionOrigin::Subtype(box ref trace) + SubregionOrigin::Subtype(ref trace) if matches!( &trace.cause.code().peel_derives(), ObligationCauseCode::WhereClause(..) @@ -661,10 +661,10 @@ impl<'a, 'tcx> TypeErrCtxt<'a, 'tcx> { ) } } - SubregionOrigin::Subtype(box trace) => { + SubregionOrigin::Subtype(trace) => { let terr = TypeError::RegionsPlaceholderMismatch; return self.report_and_explain_type_error( - trace, + *trace, self.tcx.param_env(generic_param_scope), terr, ); diff --git a/compiler/rustc_trait_selection/src/error_reporting/infer/suggest.rs b/compiler/rustc_trait_selection/src/error_reporting/infer/suggest.rs index fd51109db5f99..632f6fca82e11 100644 --- a/compiler/rustc_trait_selection/src/error_reporting/infer/suggest.rs +++ b/compiler/rustc_trait_selection/src/error_reporting/infer/suggest.rs @@ -209,7 +209,7 @@ impl<'tcx> TypeErrCtxt<'_, 'tcx> { second: exp_span.shrink_to_hi(), }) } - ObligationCauseCode::MatchExpressionArm(box MatchExpressionArmCause { + ObligationCauseCode::MatchExpressionArm(MatchExpressionArmCause { prior_non_diverging_arms, .. }) => { @@ -248,7 +248,7 @@ impl<'tcx> TypeErrCtxt<'_, 'tcx> { let then_span = self.find_block_span_from_hir_id(then_expr.hir_id); Some(ConsiderAddingAwait::FutureSugg { span: then_span.shrink_to_hi() }) } - ObligationCauseCode::MatchExpressionArm(box MatchExpressionArmCause { + ObligationCauseCode::MatchExpressionArm(MatchExpressionArmCause { prior_non_diverging_arms, .. }) => Some({ diff --git a/compiler/rustc_trait_selection/src/error_reporting/traits/fulfillment_errors.rs b/compiler/rustc_trait_selection/src/error_reporting/traits/fulfillment_errors.rs index 785118bc6d7eb..4b67cada078a4 100644 --- a/compiler/rustc_trait_selection/src/error_reporting/traits/fulfillment_errors.rs +++ b/compiler/rustc_trait_selection/src/error_reporting/traits/fulfillment_errors.rs @@ -692,7 +692,7 @@ impl<'a, 'tcx> TypeErrCtxt<'a, 'tcx> { } } - SelectionError::SignatureMismatch(box SignatureMismatchData { + SelectionError::SignatureMismatch(SignatureMismatchData { found_trait_ref, expected_trait_ref, terr: terr @ TypeError::CyclicTy(_), @@ -702,7 +702,7 @@ impl<'a, 'tcx> TypeErrCtxt<'a, 'tcx> { expected_trait_ref, terr, ), - SelectionError::SignatureMismatch(box SignatureMismatchData { + SelectionError::SignatureMismatch(SignatureMismatchData { found_trait_ref, expected_trait_ref, terr: _, diff --git a/compiler/rustc_trait_selection/src/lib.rs b/compiler/rustc_trait_selection/src/lib.rs index f0c67e4b4f89c..c1a0dcf5aa4c2 100644 --- a/compiler/rustc_trait_selection/src/lib.rs +++ b/compiler/rustc_trait_selection/src/lib.rs @@ -12,8 +12,8 @@ // tidy-alphabetical-start #![feature(associated_type_defaults)] -#![feature(box_patterns)] #![feature(default_field_values)] +#![feature(deref_patterns)] #![feature(hash_set_entry)] #![feature(iter_intersperse)] #![feature(iterator_try_reduce)] From e722c36d834720959602fd67e8e8627b9480aed0 Mon Sep 17 00:00:00 2001 From: cyrgani Date: Thu, 7 May 2026 15:32:38 +0000 Subject: [PATCH 13/19] use `deref_patterns` in `rustc_middle` --- compiler/rustc_middle/src/lib.rs | 2 +- compiler/rustc_middle/src/mir/interpret/error.rs | 2 +- compiler/rustc_middle/src/mir/mod.rs | 4 ++-- compiler/rustc_middle/src/mir/pretty.rs | 12 ++++++------ compiler/rustc_middle/src/mir/statement.rs | 4 ++-- compiler/rustc_middle/src/mir/visit.rs | 12 ++++++------ compiler/rustc_middle/src/thir/visit.rs | 8 ++++---- compiler/rustc_middle/src/traits/mod.rs | 6 +++--- 8 files changed, 25 insertions(+), 25 deletions(-) diff --git a/compiler/rustc_middle/src/lib.rs b/compiler/rustc_middle/src/lib.rs index 1d6132ba2a3ea..a9e547b5862a6 100644 --- a/compiler/rustc_middle/src/lib.rs +++ b/compiler/rustc_middle/src/lib.rs @@ -31,13 +31,13 @@ #![feature(allocator_api)] #![feature(associated_type_defaults)] #![feature(box_as_ptr)] -#![feature(box_patterns)] #![feature(closure_track_caller)] #![feature(const_default)] #![feature(const_trait_impl)] #![feature(core_intrinsics)] #![feature(debug_closure_helpers)] #![feature(decl_macro)] +#![feature(deref_patterns)] #![feature(discriminant_kind)] #![feature(extern_types)] #![feature(file_buffered)] diff --git a/compiler/rustc_middle/src/mir/interpret/error.rs b/compiler/rustc_middle/src/mir/interpret/error.rs index 5af8ec554f9db..7d9f6903d3ef0 100644 --- a/compiler/rustc_middle/src/mir/interpret/error.rs +++ b/compiler/rustc_middle/src/mir/interpret/error.rs @@ -200,7 +200,7 @@ impl InterpErrorBacktrace { impl<'tcx> InterpErrorInfo<'tcx> { pub fn into_parts(self) -> (InterpErrorKind<'tcx>, InterpErrorBacktrace) { - let InterpErrorInfo(box InterpErrorInfoInner { kind, backtrace }) = self; + let InterpErrorInfo(InterpErrorInfoInner { kind, backtrace }) = self; (kind, backtrace) } diff --git a/compiler/rustc_middle/src/mir/mod.rs b/compiler/rustc_middle/src/mir/mod.rs index 28932240953b4..57c2883ef42e4 100644 --- a/compiler/rustc_middle/src/mir/mod.rs +++ b/compiler/rustc_middle/src/mir/mod.rs @@ -1694,7 +1694,7 @@ pub fn find_self_call<'tcx>( debug!("find_self_call(local={:?}): terminator={:?}", local, body[block].terminator); if let Some(Terminator { kind: TerminatorKind::Call { func, args, .. }, .. }) = &body[block].terminator - && let Operand::Constant(box ConstOperand { const_, .. }) = func + && let Operand::Constant(ConstOperand { const_, .. }) = func && let ty::FnDef(def_id, fn_args) = *const_.ty().kind() && let Some(item) = tcx.opt_associated_item(def_id) && item.is_method() @@ -1708,7 +1708,7 @@ pub fn find_self_call<'tcx>( // Handle the case where `self_place` gets reborrowed. // This happens when the receiver is `&T`. for stmt in &body[block].statements { - if let StatementKind::Assign(box (place, rvalue)) = &stmt.kind + if let StatementKind::Assign((place, rvalue)) = &stmt.kind && let Some(reborrow_local) = place.as_local() && self_place.as_local() == Some(reborrow_local) && let Rvalue::Ref(_, _, deref_place) = rvalue diff --git a/compiler/rustc_middle/src/mir/pretty.rs b/compiler/rustc_middle/src/mir/pretty.rs index e1bc29d5c3684..5fa0216300530 100644 --- a/compiler/rustc_middle/src/mir/pretty.rs +++ b/compiler/rustc_middle/src/mir/pretty.rs @@ -522,7 +522,7 @@ fn write_scope_tree( impl Debug for VarDebugInfo<'_> { fn fmt(&self, fmt: &mut Formatter<'_>) -> fmt::Result { - if let Some(box VarDebugInfoFragment { ty, ref projection }) = self.composite { + if let Some(VarDebugInfoFragment { ty, ref projection }) = self.composite { pre_fmt_projection(&projection[..], fmt)?; write!(fmt, "({}: {})", self.name, ty)?; post_fmt_projection(&projection[..], fmt)?; @@ -806,8 +806,8 @@ impl Debug for StatementKind<'_> { fn fmt(&self, fmt: &mut Formatter<'_>) -> fmt::Result { use self::StatementKind::*; match *self { - Assign(box (ref place, ref rv)) => write!(fmt, "{place:?} = {rv:?}"), - FakeRead(box (ref cause, ref place)) => { + Assign((ref place, ref rv)) => write!(fmt, "{place:?} = {rv:?}"), + FakeRead((ref cause, ref place)) => { write!(fmt, "FakeRead({cause:?}, {place:?})") } StorageLive(ref place) => write!(fmt, "StorageLive({place:?})"), @@ -818,11 +818,11 @@ impl Debug for StatementKind<'_> { PlaceMention(ref place) => { write!(fmt, "PlaceMention({place:?})") } - AscribeUserType(box (ref place, ref c_ty), ref variance) => { + AscribeUserType((ref place, ref c_ty), ref variance) => { write!(fmt, "AscribeUserType({place:?}, {variance:?}, {c_ty:?})") } Coverage(ref kind) => write!(fmt, "Coverage::{kind:?}"), - Intrinsic(box ref intrinsic) => write!(fmt, "{intrinsic}"), + Intrinsic(ref intrinsic) => write!(fmt, "{intrinsic}"), ConstEvalCounter => write!(fmt, "ConstEvalCounter"), Nop => write!(fmt, "nop"), BackwardIncompatibleDropHint { ref place, reason: _ } => { @@ -1096,7 +1096,7 @@ impl<'tcx> Debug for Rvalue<'tcx> { Cast(ref kind, ref place, ref ty) => { with_no_trimmed_paths!(write!(fmt, "{place:?} as {ty} ({kind:?})")) } - BinaryOp(ref op, box (ref a, ref b)) => write!(fmt, "{op:?}({a:?}, {b:?})"), + BinaryOp(ref op, (ref a, ref b)) => write!(fmt, "{op:?}({a:?}, {b:?})"), UnaryOp(ref op, ref a) => write!(fmt, "{op:?}({a:?})"), Discriminant(ref place) => write!(fmt, "discriminant({place:?})"), ThreadLocalRef(did) => ty::tls::with(|tcx| { diff --git a/compiler/rustc_middle/src/mir/statement.rs b/compiler/rustc_middle/src/mir/statement.rs index c1f1b398ac147..dda38ef053f94 100644 --- a/compiler/rustc_middle/src/mir/statement.rs +++ b/compiler/rustc_middle/src/mir/statement.rs @@ -77,7 +77,7 @@ impl<'tcx> StatementKind<'tcx> { pub fn as_debuginfo(&self) -> Option> { match self { - StatementKind::Assign(box (place, Rvalue::Ref(_, _, ref_place))) + StatementKind::Assign((place, Rvalue::Ref(_, _, ref_place))) if let Some(local) = place.as_local() => { Some(StmtDebugInfo::AssignRef(local, *ref_place)) @@ -817,7 +817,7 @@ impl<'tcx> Rvalue<'tcx> { Ty::new_ptr(tcx, place_ty, kind.to_mutbl_lossy()) } Rvalue::Cast(.., ty) => ty, - Rvalue::BinaryOp(op, box (ref lhs, ref rhs)) => { + Rvalue::BinaryOp(op, (ref lhs, ref rhs)) => { let lhs_ty = lhs.ty(local_decls, tcx); let rhs_ty = rhs.ty(local_decls, tcx); op.ty(tcx, lhs_ty, rhs_ty) diff --git a/compiler/rustc_middle/src/mir/visit.rs b/compiler/rustc_middle/src/mir/visit.rs index d73eac59dfb5d..e6e911dece742 100644 --- a/compiler/rustc_middle/src/mir/visit.rs +++ b/compiler/rustc_middle/src/mir/visit.rs @@ -419,10 +419,10 @@ macro_rules! make_mir_visitor { self.visit_statement_debuginfo(debuginfo, location); } match kind { - StatementKind::Assign(box (place, rvalue)) => { + StatementKind::Assign((place, rvalue)) => { self.visit_assign(place, rvalue, location); } - StatementKind::FakeRead(box (_, place)) => { + StatementKind::FakeRead((_, place)) => { self.visit_place( place, PlaceContext::NonMutatingUse(NonMutatingUseContext::Inspect), @@ -457,7 +457,7 @@ macro_rules! make_mir_visitor { location ); } - StatementKind::AscribeUserType(box (place, user_ty), variance) => { + StatementKind::AscribeUserType((place, user_ty), variance) => { self.visit_ascribe_user_ty( place, $(& $mutability)? *variance, @@ -471,7 +471,7 @@ macro_rules! make_mir_visitor { location ) } - StatementKind::Intrinsic(box intrinsic) => { + StatementKind::Intrinsic(intrinsic) => { match intrinsic { NonDivergingIntrinsic::Assume(op) => self.visit_operand(op, location), NonDivergingIntrinsic::CopyNonOverlapping(CopyNonOverlapping { @@ -758,7 +758,7 @@ macro_rules! make_mir_visitor { self.visit_ty($(& $mutability)? *ty, TyContext::Location(location)); } - Rvalue::BinaryOp(_bin_op, box(lhs, rhs)) => { + Rvalue::BinaryOp(_bin_op, (lhs, rhs)) => { self.visit_operand(lhs, location); self.visit_operand(rhs, location); } @@ -918,7 +918,7 @@ macro_rules! make_mir_visitor { self.visit_source_info(source_info); let location = Location::START; - if let Some(box VarDebugInfoFragment { + if let Some(VarDebugInfoFragment { ty, projection }) = composite { diff --git a/compiler/rustc_middle/src/thir/visit.rs b/compiler/rustc_middle/src/thir/visit.rs index 3361e43b15dd9..a96f4e9457cb0 100644 --- a/compiler/rustc_middle/src/thir/visit.rs +++ b/compiler/rustc_middle/src/thir/visit.rs @@ -81,7 +81,7 @@ pub fn walk_expr<'thir, 'tcx: 'thir, V: Visitor<'thir, 'tcx>>( visitor.visit_pat(pat); } Loop { body } => visitor.visit_expr(&visitor.thir()[body]), - LoopMatch { match_data: box LoopMatchMatchData { scrutinee, ref arms, .. }, .. } + LoopMatch { match_data: LoopMatchMatchData { scrutinee, ref arms, .. }, .. } | Match { scrutinee, ref arms, .. } => { visitor.visit_expr(&visitor.thir()[scrutinee]); for &arm in &**arms { @@ -123,7 +123,7 @@ pub fn walk_expr<'thir, 'tcx: 'thir, V: Visitor<'thir, 'tcx>>( visitor.visit_expr(&visitor.thir()[field]); } } - Adt(box AdtExpr { + Adt(AdtExpr { ref fields, ref base, adt_def: _, @@ -145,7 +145,7 @@ pub fn walk_expr<'thir, 'tcx: 'thir, V: Visitor<'thir, 'tcx>>( PlaceUnwrapUnsafeBinder { source } | ValueUnwrapUnsafeBinder { source } | WrapUnsafeBinder { source } => visitor.visit_expr(&visitor.thir()[source]), - Closure(box ClosureExpr { + Closure(ClosureExpr { closure_id: _, args: _, upvars: _, @@ -158,7 +158,7 @@ pub fn walk_expr<'thir, 'tcx: 'thir, V: Visitor<'thir, 'tcx>>( NamedConst { def_id: _, args: _, user_ty: _ } => {} ConstParam { param: _, def_id: _ } => {} StaticRef { alloc_id: _, ty: _, def_id: _ } => {} - InlineAsm(box InlineAsmExpr { + InlineAsm(InlineAsmExpr { asm_macro: _, ref operands, template: _, diff --git a/compiler/rustc_middle/src/traits/mod.rs b/compiler/rustc_middle/src/traits/mod.rs index daa0df4013272..4cd124248e093 100644 --- a/compiler/rustc_middle/src/traits/mod.rs +++ b/compiler/rustc_middle/src/traits/mod.rs @@ -478,11 +478,11 @@ impl<'tcx> ObligationCauseCode<'tcx> { ObligationCauseCode::FunctionArg { parent_code, .. } => Some(parent_code), ObligationCauseCode::BuiltinDerived(derived) | ObligationCauseCode::WellFormedDerived(derived) - | ObligationCauseCode::ImplDerived(box ImplDerivedCause { derived, .. }) => { + | ObligationCauseCode::ImplDerived(ImplDerivedCause { derived, .. }) => { Some(&derived.parent_code) } ObligationCauseCode::BuiltinDerivedHost(derived) - | ObligationCauseCode::ImplDerivedHost(box ImplDerivedHostCause { derived, .. }) => { + | ObligationCauseCode::ImplDerivedHost(ImplDerivedHostCause { derived, .. }) => { Some(&derived.parent_code) } _ => None, @@ -509,7 +509,7 @@ impl<'tcx> ObligationCauseCode<'tcx> { ObligationCauseCode::FunctionArg { parent_code, .. } => Some((parent_code, None)), ObligationCauseCode::BuiltinDerived(derived) | ObligationCauseCode::WellFormedDerived(derived) - | ObligationCauseCode::ImplDerived(box ImplDerivedCause { derived, .. }) => { + | ObligationCauseCode::ImplDerived(ImplDerivedCause { derived, .. }) => { Some((&derived.parent_code, Some(derived.parent_trait_pred))) } _ => None, From a06037901c1270b705ec3758b3149e58e0aba68a Mon Sep 17 00:00:00 2001 From: cyrgani Date: Thu, 7 May 2026 15:42:59 +0000 Subject: [PATCH 14/19] use `deref_patterns` in `rustc_codegen_ssa` --- compiler/rustc_codegen_ssa/src/lib.rs | 2 +- compiler/rustc_codegen_ssa/src/mir/rvalue.rs | 4 ++-- compiler/rustc_codegen_ssa/src/mir/statement.rs | 10 +++++----- 3 files changed, 8 insertions(+), 8 deletions(-) diff --git a/compiler/rustc_codegen_ssa/src/lib.rs b/compiler/rustc_codegen_ssa/src/lib.rs index d48b54166270e..e4b61e71a48e7 100644 --- a/compiler/rustc_codegen_ssa/src/lib.rs +++ b/compiler/rustc_codegen_ssa/src/lib.rs @@ -1,5 +1,5 @@ // tidy-alphabetical-start -#![feature(box_patterns)] +#![feature(deref_patterns)] #![feature(file_buffered)] #![feature(negative_impls)] #![feature(string_from_utf8_lossy_owned)] diff --git a/compiler/rustc_codegen_ssa/src/mir/rvalue.rs b/compiler/rustc_codegen_ssa/src/mir/rvalue.rs index 45c6621ba0131..0feb22e8d1d70 100644 --- a/compiler/rustc_codegen_ssa/src/mir/rvalue.rs +++ b/compiler/rustc_codegen_ssa/src/mir/rvalue.rs @@ -533,7 +533,7 @@ impl<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>> FunctionCx<'a, 'tcx, Bx> { self.codegen_place_to_pointer(bx, place, mk_ptr) } - mir::Rvalue::BinaryOp(op_with_overflow, box (ref lhs, ref rhs)) + mir::Rvalue::BinaryOp(op_with_overflow, (ref lhs, ref rhs)) if let Some(op) = op_with_overflow.overflowing_to_wrapping() => { let lhs = self.codegen_operand(bx, lhs); @@ -553,7 +553,7 @@ impl<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>> FunctionCx<'a, 'tcx, Bx> { move_annotation: None, } } - mir::Rvalue::BinaryOp(op, box (ref lhs, ref rhs)) => { + mir::Rvalue::BinaryOp(op, (ref lhs, ref rhs)) => { let lhs = self.codegen_operand(bx, lhs); let rhs = self.codegen_operand(bx, rhs); let llresult = match (lhs.val, rhs.val) { diff --git a/compiler/rustc_codegen_ssa/src/mir/statement.rs b/compiler/rustc_codegen_ssa/src/mir/statement.rs index 1821710fbcc36..afbef86bd089e 100644 --- a/compiler/rustc_codegen_ssa/src/mir/statement.rs +++ b/compiler/rustc_codegen_ssa/src/mir/statement.rs @@ -11,7 +11,7 @@ impl<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>> FunctionCx<'a, 'tcx, Bx> { self.codegen_stmt_debuginfos(bx, &statement.debuginfos); self.set_debug_loc(bx, statement.source_info); match statement.kind { - mir::StatementKind::Assign(box (ref place, ref rvalue)) => { + mir::StatementKind::Assign((ref place, ref rvalue)) => { if let Some(index) = place.as_local() { match self.locals[index] { LocalRef::Place(cg_dest) => self.codegen_rvalue(bx, cg_dest, rvalue), @@ -47,8 +47,8 @@ impl<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>> FunctionCx<'a, 'tcx, Bx> { self.codegen_rvalue(bx, cg_dest, rvalue); } } - mir::StatementKind::SetDiscriminant { box ref place, variant_index } => { - self.codegen_place(bx, place.as_ref()).codegen_set_discr(bx, variant_index); + mir::StatementKind::SetDiscriminant { ref place, variant_index } => { + self.codegen_place(bx, (**place).as_ref()).codegen_set_discr(bx, variant_index); } mir::StatementKind::StorageLive(local) => { if let LocalRef::Place(cg_place) = self.locals[local] { @@ -67,11 +67,11 @@ impl<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>> FunctionCx<'a, 'tcx, Bx> { mir::StatementKind::Coverage(ref kind) => { self.codegen_coverage(bx, kind, statement.source_info.scope); } - mir::StatementKind::Intrinsic(box NonDivergingIntrinsic::Assume(ref op)) => { + mir::StatementKind::Intrinsic(NonDivergingIntrinsic::Assume(ref op)) => { let op_val = self.codegen_operand(bx, op); bx.assume(op_val.immediate()); } - mir::StatementKind::Intrinsic(box NonDivergingIntrinsic::CopyNonOverlapping( + mir::StatementKind::Intrinsic(NonDivergingIntrinsic::CopyNonOverlapping( mir::CopyNonOverlapping { ref count, ref src, ref dst }, )) => { let dst_val = self.codegen_operand(bx, dst); From 32a3612a2bb3964fe5376c498d3e9c04eadd55eb Mon Sep 17 00:00:00 2001 From: danieljofficial Date: Mon, 4 May 2026 16:02:23 +0100 Subject: [PATCH 15/19] add issue links and bless --- tests/ui/cast/ambiguous-raw-pointer-cast-errors.rs | 2 ++ tests/ui/cast/ambiguous-raw-pointer-cast-errors.stderr | 6 +++--- tests/ui/cast/as-cast-unifies-raw-pointer-and-fn-type.rs | 2 ++ tests/ui/cast/cast-not-treated-as-lvalue.rs | 2 ++ tests/ui/cast/cast-ptr-to-fat-ptr.rs | 2 ++ tests/ui/cast/invalid-thin-to-fat-pointer-cast.rs | 2 ++ tests/ui/cast/invalid-thin-to-fat-pointer-cast.stderr | 2 +- tests/ui/cast/negative-integer-cast-to-pointer.rs | 2 ++ tests/ui/cast/non-primitive-cast-self-to-dyn-index.rs | 2 ++ tests/ui/cast/non-primitive-cast-self-to-dyn-index.stderr | 2 +- tests/ui/cast/raw-pointer-from-str-comparison.rs | 2 ++ 11 files changed, 21 insertions(+), 5 deletions(-) diff --git a/tests/ui/cast/ambiguous-raw-pointer-cast-errors.rs b/tests/ui/cast/ambiguous-raw-pointer-cast-errors.rs index 3776759fe07a5..22413898eb32c 100644 --- a/tests/ui/cast/ambiguous-raw-pointer-cast-errors.rs +++ b/tests/ui/cast/ambiguous-raw-pointer-cast-errors.rs @@ -1,3 +1,5 @@ +//! Regression test for https://github.com/rust-lang/rust/issues/45730 + use std::fmt; fn main() { let x: *const _ = 0 as _; //~ ERROR cannot cast diff --git a/tests/ui/cast/ambiguous-raw-pointer-cast-errors.stderr b/tests/ui/cast/ambiguous-raw-pointer-cast-errors.stderr index d00f3d91b49da..dea81bcfbc9a3 100644 --- a/tests/ui/cast/ambiguous-raw-pointer-cast-errors.stderr +++ b/tests/ui/cast/ambiguous-raw-pointer-cast-errors.stderr @@ -1,5 +1,5 @@ error[E0641]: cannot cast to a pointer of an unknown kind - --> $DIR/issue-45730.rs:3:28 + --> $DIR/ambiguous-raw-pointer-cast-errors.rs:5:28 | LL | let x: *const _ = 0 as _; | ^ needs more type information @@ -7,7 +7,7 @@ LL | let x: *const _ = 0 as _; = note: the type information given here is insufficient to check whether the pointer cast is valid error[E0641]: cannot cast to a pointer of an unknown kind - --> $DIR/issue-45730.rs:5:28 + --> $DIR/ambiguous-raw-pointer-cast-errors.rs:7:28 | LL | let x: *const _ = 0 as *const _; | ^^^^^^^^ needs more type information @@ -15,7 +15,7 @@ LL | let x: *const _ = 0 as *const _; = note: the type information given here is insufficient to check whether the pointer cast is valid error[E0641]: cannot cast to a pointer of an unknown kind - --> $DIR/issue-45730.rs:8:44 + --> $DIR/ambiguous-raw-pointer-cast-errors.rs:10:44 | LL | let x = 0 as *const i32 as *const _ as *mut _; | ^^^^^^ needs more type information diff --git a/tests/ui/cast/as-cast-unifies-raw-pointer-and-fn-type.rs b/tests/ui/cast/as-cast-unifies-raw-pointer-and-fn-type.rs index 6dde2dfd93001..ce4319b7cc6dd 100644 --- a/tests/ui/cast/as-cast-unifies-raw-pointer-and-fn-type.rs +++ b/tests/ui/cast/as-cast-unifies-raw-pointer-and-fn-type.rs @@ -1,3 +1,5 @@ +//! Regression test for https://github.com/rust-lang/rust/issues/23699 + //@ run-pass #![allow(unused_variables)] fn gimme_a_raw_pointer(_: *const T) { } diff --git a/tests/ui/cast/cast-not-treated-as-lvalue.rs b/tests/ui/cast/cast-not-treated-as-lvalue.rs index 4fbac00212672..42d74530ded61 100644 --- a/tests/ui/cast/cast-not-treated-as-lvalue.rs +++ b/tests/ui/cast/cast-not-treated-as-lvalue.rs @@ -1,3 +1,5 @@ +//! Regression test for https://github.com/rust-lang/rust/issues/36936 + //@ run-pass // check that casts are not being treated as lexprs. diff --git a/tests/ui/cast/cast-ptr-to-fat-ptr.rs b/tests/ui/cast/cast-ptr-to-fat-ptr.rs index 6157e593ea327..74a2435af4343 100644 --- a/tests/ui/cast/cast-ptr-to-fat-ptr.rs +++ b/tests/ui/cast/cast-ptr-to-fat-ptr.rs @@ -1,3 +1,5 @@ +//! Regression test for https://github.com/rust-lang/rust/issues/30615 + //@ run-pass fn main() { &0u8 as *const u8 as *const dyn PartialEq; diff --git a/tests/ui/cast/invalid-thin-to-fat-pointer-cast.rs b/tests/ui/cast/invalid-thin-to-fat-pointer-cast.rs index 6c8df1157c6c8..72af9f7259faa 100644 --- a/tests/ui/cast/invalid-thin-to-fat-pointer-cast.rs +++ b/tests/ui/cast/invalid-thin-to-fat-pointer-cast.rs @@ -1,3 +1,5 @@ +//! Regression test for https://github.com/rust-lang/rust/issues/31511 + fn cast_thin_to_fat(x: *const ()) { x as *const [u8]; //~^ ERROR: cannot cast thin pointer `*const ()` to wide pointer `*const [u8]` diff --git a/tests/ui/cast/invalid-thin-to-fat-pointer-cast.stderr b/tests/ui/cast/invalid-thin-to-fat-pointer-cast.stderr index 2048bd7ec1666..e6fa066e82083 100644 --- a/tests/ui/cast/invalid-thin-to-fat-pointer-cast.stderr +++ b/tests/ui/cast/invalid-thin-to-fat-pointer-cast.stderr @@ -1,5 +1,5 @@ error[E0607]: cannot cast thin pointer `*const ()` to wide pointer `*const [u8]` - --> $DIR/issue-31511.rs:2:5 + --> $DIR/invalid-thin-to-fat-pointer-cast.rs:4:5 | LL | x as *const [u8]; | ^^^^^^^^^^^^^^^^ diff --git a/tests/ui/cast/negative-integer-cast-to-pointer.rs b/tests/ui/cast/negative-integer-cast-to-pointer.rs index e3fea3c942601..43093c269a53e 100644 --- a/tests/ui/cast/negative-integer-cast-to-pointer.rs +++ b/tests/ui/cast/negative-integer-cast-to-pointer.rs @@ -1,3 +1,5 @@ +//! Regression test for https://github.com/rust-lang/rust/issues/43291 + //@ run-pass pub fn main() { assert_eq!(!0usize as *const (), foo(0, 1)); diff --git a/tests/ui/cast/non-primitive-cast-self-to-dyn-index.rs b/tests/ui/cast/non-primitive-cast-self-to-dyn-index.rs index 4e359b3412a71..52debf6fe440e 100644 --- a/tests/ui/cast/non-primitive-cast-self-to-dyn-index.rs +++ b/tests/ui/cast/non-primitive-cast-self-to-dyn-index.rs @@ -1,3 +1,5 @@ +//! Regression test for https://github.com/rust-lang/rust/issues/22312 + use std::ops::Index; pub trait Array2D: Index + Sized { diff --git a/tests/ui/cast/non-primitive-cast-self-to-dyn-index.stderr b/tests/ui/cast/non-primitive-cast-self-to-dyn-index.stderr index be3f5ace5480e..8ef1d55910792 100644 --- a/tests/ui/cast/non-primitive-cast-self-to-dyn-index.stderr +++ b/tests/ui/cast/non-primitive-cast-self-to-dyn-index.stderr @@ -1,5 +1,5 @@ error[E0605]: non-primitive cast: `Self` as `&dyn Index>::Output>` - --> $DIR/issue-22312.rs:11:24 + --> $DIR/non-primitive-cast-self-to-dyn-index.rs:13:24 | LL | let indexer = &(*self as &dyn Index>::Output>); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ invalid cast diff --git a/tests/ui/cast/raw-pointer-from-str-comparison.rs b/tests/ui/cast/raw-pointer-from-str-comparison.rs index 8ce2caaeaa57b..9713c36dde265 100644 --- a/tests/ui/cast/raw-pointer-from-str-comparison.rs +++ b/tests/ui/cast/raw-pointer-from-str-comparison.rs @@ -1,3 +1,5 @@ +//! Regression test for https://github.com/rust-lang/rust/issues/17336 + //@ build-pass #![allow(unused_must_use)] From 7a876ac4185ded67fbae324c2e697ae999d52ce9 Mon Sep 17 00:00:00 2001 From: danieljofficial Date: Tue, 12 May 2026 08:58:45 +0100 Subject: [PATCH 16/19] add helpful comments to tests --- tests/ui/cast/cast-ptr-to-fat-ptr.rs | 2 ++ tests/ui/cast/invalid-thin-to-fat-pointer-cast.rs | 2 ++ tests/ui/cast/invalid-thin-to-fat-pointer-cast.stderr | 2 +- 3 files changed, 5 insertions(+), 1 deletion(-) diff --git a/tests/ui/cast/cast-ptr-to-fat-ptr.rs b/tests/ui/cast/cast-ptr-to-fat-ptr.rs index 74a2435af4343..557d929a0a033 100644 --- a/tests/ui/cast/cast-ptr-to-fat-ptr.rs +++ b/tests/ui/cast/cast-ptr-to-fat-ptr.rs @@ -1,4 +1,6 @@ //! Regression test for https://github.com/rust-lang/rust/issues/30615 +//! This test confirms that valid code casting a thin pointer to a fat pointer does not cause ICE +//! and compiles. //@ run-pass fn main() { diff --git a/tests/ui/cast/invalid-thin-to-fat-pointer-cast.rs b/tests/ui/cast/invalid-thin-to-fat-pointer-cast.rs index 72af9f7259faa..085566fd95390 100644 --- a/tests/ui/cast/invalid-thin-to-fat-pointer-cast.rs +++ b/tests/ui/cast/invalid-thin-to-fat-pointer-cast.rs @@ -1,4 +1,6 @@ //! Regression test for https://github.com/rust-lang/rust/issues/31511 +//! This test confirms that a helpful enough error is shown when you try +//! to incorrectly cast a thin pointer to a fat pointer. fn cast_thin_to_fat(x: *const ()) { x as *const [u8]; diff --git a/tests/ui/cast/invalid-thin-to-fat-pointer-cast.stderr b/tests/ui/cast/invalid-thin-to-fat-pointer-cast.stderr index e6fa066e82083..6929b719f5db7 100644 --- a/tests/ui/cast/invalid-thin-to-fat-pointer-cast.stderr +++ b/tests/ui/cast/invalid-thin-to-fat-pointer-cast.stderr @@ -1,5 +1,5 @@ error[E0607]: cannot cast thin pointer `*const ()` to wide pointer `*const [u8]` - --> $DIR/invalid-thin-to-fat-pointer-cast.rs:4:5 + --> $DIR/invalid-thin-to-fat-pointer-cast.rs:6:5 | LL | x as *const [u8]; | ^^^^^^^^^^^^^^^^ From c37d020c3bfa46bcef7c559dec1e0a7649db2200 Mon Sep 17 00:00:00 2001 From: jyn Date: Tue, 12 May 2026 12:27:31 +0200 Subject: [PATCH 17/19] give an example of a Ctor in the doc-comments --- compiler/rustc_hir/src/def.rs | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/compiler/rustc_hir/src/def.rs b/compiler/rustc_hir/src/def.rs index 917b685958da4..ad5d6b1509dfd 100644 --- a/compiler/rustc_hir/src/def.rs +++ b/compiler/rustc_hir/src/def.rs @@ -134,6 +134,11 @@ pub enum DefKind { }, /// Refers to the struct or enum variant's constructor. /// + /// ``` + /// struct S; + /// let x = S; // S in the value namespace is a Ctor + /// ``` + /// /// The reason `Ctor` exists in addition to [`DefKind::Struct`] and /// [`DefKind::Variant`] is because structs and enum variants exist /// in the *type* namespace, whereas struct and enum variant *constructors* From e9125c62b16995ec0eb1918acfe9cb0428cc6f90 Mon Sep 17 00:00:00 2001 From: Zac Harrold Date: Mon, 11 May 2026 12:11:29 +1000 Subject: [PATCH 18/19] Move `std::io::Cursor` into `core::io` --- library/core/src/io/cursor.rs | 291 ++++++++++++++++++++++++++ library/core/src/io/mod.rs | 3 + library/std/src/io/cursor.rs | 372 ++++++---------------------------- library/std/src/lib.rs | 1 + 4 files changed, 353 insertions(+), 314 deletions(-) create mode 100644 library/core/src/io/cursor.rs diff --git a/library/core/src/io/cursor.rs b/library/core/src/io/cursor.rs new file mode 100644 index 0000000000000..ebbec6c5e8210 --- /dev/null +++ b/library/core/src/io/cursor.rs @@ -0,0 +1,291 @@ +/// A `Cursor` wraps an in-memory buffer and provides it with a +/// [`Seek`] implementation. +/// +/// `Cursor`s are used with in-memory buffers, anything implementing +/// [AsRef]<\[u8]>, to allow them to implement [`Read`] and/or [`Write`], +/// allowing these buffers to be used anywhere you might use a reader or writer +/// that does actual I/O. +/// +/// The standard library implements some I/O traits on various types which +/// are commonly used as a buffer, like Cursor<[Vec]\> and +/// Cursor<[&\[u8\]][bytes]>. +/// +/// # Examples +/// +/// We may want to write bytes to a [`File`] in our production +/// code, but use an in-memory buffer in our tests. We can do this with +/// `Cursor`: +/// +/// [bytes]: crate::slice "slice" +/// [`File`]: ../../std/fs/struct.File.html +/// [`Read`]: ../../std/io/trait.Read.html +/// [`Write`]: ../../std/io/trait.Write.html +/// [`Seek`]: ../../std/io/trait.Seek.html +/// [Vec]: ../../alloc/vec/struct.Vec.html +/// +/// ```no_run +/// use std::io::prelude::*; +/// use std::io::{self, SeekFrom}; +/// use std::fs::File; +/// +/// // a library function we've written +/// fn write_ten_bytes_at_end(mut writer: W) -> io::Result<()> { +/// writer.seek(SeekFrom::End(-10))?; +/// +/// for i in 0..10 { +/// writer.write(&[i])?; +/// } +/// +/// // all went well +/// Ok(()) +/// } +/// +/// # fn foo() -> io::Result<()> { +/// // Here's some code that uses this library function. +/// // +/// // We might want to use a BufReader here for efficiency, but let's +/// // keep this example focused. +/// let mut file = File::create("foo.txt")?; +/// // First, we need to allocate 10 bytes to be able to write into. +/// file.set_len(10)?; +/// +/// write_ten_bytes_at_end(&mut file)?; +/// # Ok(()) +/// # } +/// +/// // now let's write a test +/// #[test] +/// fn test_writes_bytes() { +/// // setting up a real File is much slower than an in-memory buffer, +/// // let's use a cursor instead +/// use std::io::Cursor; +/// let mut buff = Cursor::new(vec![0; 15]); +/// +/// write_ten_bytes_at_end(&mut buff).unwrap(); +/// +/// assert_eq!(&buff.get_ref()[5..15], &[0, 1, 2, 3, 4, 5, 6, 7, 8, 9]); +/// } +/// ``` +#[stable(feature = "rust1", since = "1.0.0")] +#[derive(Debug, Default, Eq, PartialEq)] +pub struct Cursor { + inner: T, + pos: u64, +} + +impl Cursor { + /// Creates a new cursor wrapping the provided underlying in-memory buffer. + /// + /// Cursor initial position is `0` even if underlying buffer (e.g., [`Vec`]) + /// is not empty. So writing to cursor starts with overwriting [`Vec`] + /// content, not with appending to it. + /// + /// [`Vec`]: ../../alloc/vec/struct.Vec.html + /// + /// # Examples + /// + /// ``` + /// use std::io::Cursor; + /// + /// let buff = Cursor::new(Vec::new()); + /// # fn force_inference(_: &Cursor>) {} + /// # force_inference(&buff); + /// ``` + #[stable(feature = "rust1", since = "1.0.0")] + #[rustc_const_stable(feature = "const_io_structs", since = "1.79.0")] + pub const fn new(inner: T) -> Cursor { + Cursor { pos: 0, inner } + } + + /// Consumes this cursor, returning the underlying value. + /// + /// # Examples + /// + /// ``` + /// use std::io::Cursor; + /// + /// let buff = Cursor::new(Vec::new()); + /// # fn force_inference(_: &Cursor>) {} + /// # force_inference(&buff); + /// + /// let vec = buff.into_inner(); + /// ``` + #[stable(feature = "rust1", since = "1.0.0")] + pub fn into_inner(self) -> T { + self.inner + } + + /// Gets a reference to the underlying value in this cursor. + /// + /// # Examples + /// + /// ``` + /// use std::io::Cursor; + /// + /// let buff = Cursor::new(Vec::new()); + /// # fn force_inference(_: &Cursor>) {} + /// # force_inference(&buff); + /// + /// let reference = buff.get_ref(); + /// ``` + #[stable(feature = "rust1", since = "1.0.0")] + #[rustc_const_stable(feature = "const_io_structs", since = "1.79.0")] + pub const fn get_ref(&self) -> &T { + &self.inner + } + + /// Gets a mutable reference to the underlying value in this cursor. + /// + /// Care should be taken to avoid modifying the internal I/O state of the + /// underlying value as it may corrupt this cursor's position. + /// + /// # Examples + /// + /// ``` + /// use std::io::Cursor; + /// + /// let mut buff = Cursor::new(Vec::new()); + /// # fn force_inference(_: &Cursor>) {} + /// # force_inference(&buff); + /// + /// let reference = buff.get_mut(); + /// ``` + #[stable(feature = "rust1", since = "1.0.0")] + #[rustc_const_stable(feature = "const_mut_cursor", since = "1.86.0")] + pub const fn get_mut(&mut self) -> &mut T { + &mut self.inner + } + + /// Returns the current position of this cursor. + /// + /// # Examples + /// + /// ``` + /// use std::io::Cursor; + /// use std::io::prelude::*; + /// use std::io::SeekFrom; + /// + /// let mut buff = Cursor::new(vec![1, 2, 3, 4, 5]); + /// + /// assert_eq!(buff.position(), 0); + /// + /// buff.seek(SeekFrom::Current(2)).unwrap(); + /// assert_eq!(buff.position(), 2); + /// + /// buff.seek(SeekFrom::Current(-1)).unwrap(); + /// assert_eq!(buff.position(), 1); + /// ``` + #[stable(feature = "rust1", since = "1.0.0")] + #[rustc_const_stable(feature = "const_io_structs", since = "1.79.0")] + pub const fn position(&self) -> u64 { + self.pos + } + + /// Sets the position of this cursor. + /// + /// # Examples + /// + /// ``` + /// use std::io::Cursor; + /// + /// let mut buff = Cursor::new(vec![1, 2, 3, 4, 5]); + /// + /// assert_eq!(buff.position(), 0); + /// + /// buff.set_position(2); + /// assert_eq!(buff.position(), 2); + /// + /// buff.set_position(4); + /// assert_eq!(buff.position(), 4); + /// ``` + #[stable(feature = "rust1", since = "1.0.0")] + #[rustc_const_stable(feature = "const_mut_cursor", since = "1.86.0")] + pub const fn set_position(&mut self, pos: u64) { + self.pos = pos; + } + + #[doc(hidden)] + #[unstable(feature = "core_io_internals", reason = "exposed only for libstd", issue = "none")] + #[inline] + pub const fn into_parts_mut(&mut self) -> (&mut u64, &mut T) { + (&mut self.pos, &mut self.inner) + } +} + +impl Cursor +where + T: AsRef<[u8]>, +{ + /// Splits the underlying slice at the cursor position and returns them. + /// + /// # Examples + /// + /// ``` + /// #![feature(cursor_split)] + /// use std::io::Cursor; + /// + /// let mut buff = Cursor::new(vec![1, 2, 3, 4, 5]); + /// + /// assert_eq!(buff.split(), ([].as_slice(), [1, 2, 3, 4, 5].as_slice())); + /// + /// buff.set_position(2); + /// assert_eq!(buff.split(), ([1, 2].as_slice(), [3, 4, 5].as_slice())); + /// + /// buff.set_position(6); + /// assert_eq!(buff.split(), ([1, 2, 3, 4, 5].as_slice(), [].as_slice())); + /// ``` + #[unstable(feature = "cursor_split", issue = "86369")] + pub fn split(&self) -> (&[u8], &[u8]) { + let slice = self.inner.as_ref(); + let pos = self.pos.min(slice.len() as u64); + slice.split_at(pos as usize) + } +} + +impl Cursor +where + T: AsMut<[u8]>, +{ + /// Splits the underlying slice at the cursor position and returns them + /// mutably. + /// + /// # Examples + /// + /// ``` + /// #![feature(cursor_split)] + /// use std::io::Cursor; + /// + /// let mut buff = Cursor::new(vec![1, 2, 3, 4, 5]); + /// + /// assert_eq!(buff.split_mut(), ([].as_mut_slice(), [1, 2, 3, 4, 5].as_mut_slice())); + /// + /// buff.set_position(2); + /// assert_eq!(buff.split_mut(), ([1, 2].as_mut_slice(), [3, 4, 5].as_mut_slice())); + /// + /// buff.set_position(6); + /// assert_eq!(buff.split_mut(), ([1, 2, 3, 4, 5].as_mut_slice(), [].as_mut_slice())); + /// ``` + #[unstable(feature = "cursor_split", issue = "86369")] + pub fn split_mut(&mut self) -> (&mut [u8], &mut [u8]) { + let slice = self.inner.as_mut(); + let pos = self.pos.min(slice.len() as u64); + slice.split_at_mut(pos as usize) + } +} + +#[stable(feature = "rust1", since = "1.0.0")] +impl Clone for Cursor +where + T: Clone, +{ + #[inline] + fn clone(&self) -> Self { + Cursor { inner: self.inner.clone(), pos: self.pos } + } + + #[inline] + fn clone_from(&mut self, other: &Self) { + self.inner.clone_from(&other.inner); + self.pos = other.pos; + } +} diff --git a/library/core/src/io/mod.rs b/library/core/src/io/mod.rs index 2d8273dd1b2d0..333e436ddb573 100644 --- a/library/core/src/io/mod.rs +++ b/library/core/src/io/mod.rs @@ -1,11 +1,14 @@ //! Traits, helpers, and type definitions for core I/O functionality. mod borrowed_buf; +mod cursor; mod error; #[unstable(feature = "core_io_borrowed_buf", issue = "117693")] pub use self::borrowed_buf::{BorrowedBuf, BorrowedCursor}; #[unstable(feature = "core_io", issue = "154046")] +pub use self::cursor::Cursor; +#[unstable(feature = "core_io", issue = "154046")] pub use self::error::ErrorKind; #[unstable(feature = "raw_os_error_ty", issue = "107792")] pub use self::error::RawOsError; diff --git a/library/std/src/io/cursor.rs b/library/std/src/io/cursor.rs index d7131e2fe92fd..9cd6d013f472c 100644 --- a/library/std/src/io/cursor.rs +++ b/library/std/src/io/cursor.rs @@ -1,290 +1,14 @@ #[cfg(test)] mod tests; +#[stable(feature = "rust1", since = "1.0.0")] +pub use core::io::Cursor; + use crate::alloc::Allocator; use crate::cmp; use crate::io::prelude::*; use crate::io::{self, BorrowedCursor, ErrorKind, IoSlice, IoSliceMut, SeekFrom}; -/// A `Cursor` wraps an in-memory buffer and provides it with a -/// [`Seek`] implementation. -/// -/// `Cursor`s are used with in-memory buffers, anything implementing -/// [AsRef]<\[u8]>, to allow them to implement [`Read`] and/or [`Write`], -/// allowing these buffers to be used anywhere you might use a reader or writer -/// that does actual I/O. -/// -/// The standard library implements some I/O traits on various types which -/// are commonly used as a buffer, like Cursor<[Vec]\> and -/// Cursor<[&\[u8\]][bytes]>. -/// -/// # Examples -/// -/// We may want to write bytes to a [`File`] in our production -/// code, but use an in-memory buffer in our tests. We can do this with -/// `Cursor`: -/// -/// [bytes]: crate::slice "slice" -/// [`File`]: crate::fs::File -/// -/// ```no_run -/// use std::io::prelude::*; -/// use std::io::{self, SeekFrom}; -/// use std::fs::File; -/// -/// // a library function we've written -/// fn write_ten_bytes_at_end(mut writer: W) -> io::Result<()> { -/// writer.seek(SeekFrom::End(-10))?; -/// -/// for i in 0..10 { -/// writer.write(&[i])?; -/// } -/// -/// // all went well -/// Ok(()) -/// } -/// -/// # fn foo() -> io::Result<()> { -/// // Here's some code that uses this library function. -/// // -/// // We might want to use a BufReader here for efficiency, but let's -/// // keep this example focused. -/// let mut file = File::create("foo.txt")?; -/// // First, we need to allocate 10 bytes to be able to write into. -/// file.set_len(10)?; -/// -/// write_ten_bytes_at_end(&mut file)?; -/// # Ok(()) -/// # } -/// -/// // now let's write a test -/// #[test] -/// fn test_writes_bytes() { -/// // setting up a real File is much slower than an in-memory buffer, -/// // let's use a cursor instead -/// use std::io::Cursor; -/// let mut buff = Cursor::new(vec![0; 15]); -/// -/// write_ten_bytes_at_end(&mut buff).unwrap(); -/// -/// assert_eq!(&buff.get_ref()[5..15], &[0, 1, 2, 3, 4, 5, 6, 7, 8, 9]); -/// } -/// ``` -#[stable(feature = "rust1", since = "1.0.0")] -#[derive(Debug, Default, Eq, PartialEq)] -pub struct Cursor { - inner: T, - pos: u64, -} - -impl Cursor { - /// Creates a new cursor wrapping the provided underlying in-memory buffer. - /// - /// Cursor initial position is `0` even if underlying buffer (e.g., [`Vec`]) - /// is not empty. So writing to cursor starts with overwriting [`Vec`] - /// content, not with appending to it. - /// - /// # Examples - /// - /// ``` - /// use std::io::Cursor; - /// - /// let buff = Cursor::new(Vec::new()); - /// # fn force_inference(_: &Cursor>) {} - /// # force_inference(&buff); - /// ``` - #[stable(feature = "rust1", since = "1.0.0")] - #[rustc_const_stable(feature = "const_io_structs", since = "1.79.0")] - pub const fn new(inner: T) -> Cursor { - Cursor { pos: 0, inner } - } - - /// Consumes this cursor, returning the underlying value. - /// - /// # Examples - /// - /// ``` - /// use std::io::Cursor; - /// - /// let buff = Cursor::new(Vec::new()); - /// # fn force_inference(_: &Cursor>) {} - /// # force_inference(&buff); - /// - /// let vec = buff.into_inner(); - /// ``` - #[stable(feature = "rust1", since = "1.0.0")] - pub fn into_inner(self) -> T { - self.inner - } - - /// Gets a reference to the underlying value in this cursor. - /// - /// # Examples - /// - /// ``` - /// use std::io::Cursor; - /// - /// let buff = Cursor::new(Vec::new()); - /// # fn force_inference(_: &Cursor>) {} - /// # force_inference(&buff); - /// - /// let reference = buff.get_ref(); - /// ``` - #[stable(feature = "rust1", since = "1.0.0")] - #[rustc_const_stable(feature = "const_io_structs", since = "1.79.0")] - pub const fn get_ref(&self) -> &T { - &self.inner - } - - /// Gets a mutable reference to the underlying value in this cursor. - /// - /// Care should be taken to avoid modifying the internal I/O state of the - /// underlying value as it may corrupt this cursor's position. - /// - /// # Examples - /// - /// ``` - /// use std::io::Cursor; - /// - /// let mut buff = Cursor::new(Vec::new()); - /// # fn force_inference(_: &Cursor>) {} - /// # force_inference(&buff); - /// - /// let reference = buff.get_mut(); - /// ``` - #[stable(feature = "rust1", since = "1.0.0")] - #[rustc_const_stable(feature = "const_mut_cursor", since = "1.86.0")] - pub const fn get_mut(&mut self) -> &mut T { - &mut self.inner - } - - /// Returns the current position of this cursor. - /// - /// # Examples - /// - /// ``` - /// use std::io::Cursor; - /// use std::io::prelude::*; - /// use std::io::SeekFrom; - /// - /// let mut buff = Cursor::new(vec![1, 2, 3, 4, 5]); - /// - /// assert_eq!(buff.position(), 0); - /// - /// buff.seek(SeekFrom::Current(2)).unwrap(); - /// assert_eq!(buff.position(), 2); - /// - /// buff.seek(SeekFrom::Current(-1)).unwrap(); - /// assert_eq!(buff.position(), 1); - /// ``` - #[stable(feature = "rust1", since = "1.0.0")] - #[rustc_const_stable(feature = "const_io_structs", since = "1.79.0")] - pub const fn position(&self) -> u64 { - self.pos - } - - /// Sets the position of this cursor. - /// - /// # Examples - /// - /// ``` - /// use std::io::Cursor; - /// - /// let mut buff = Cursor::new(vec![1, 2, 3, 4, 5]); - /// - /// assert_eq!(buff.position(), 0); - /// - /// buff.set_position(2); - /// assert_eq!(buff.position(), 2); - /// - /// buff.set_position(4); - /// assert_eq!(buff.position(), 4); - /// ``` - #[stable(feature = "rust1", since = "1.0.0")] - #[rustc_const_stable(feature = "const_mut_cursor", since = "1.86.0")] - pub const fn set_position(&mut self, pos: u64) { - self.pos = pos; - } -} - -impl Cursor -where - T: AsRef<[u8]>, -{ - /// Splits the underlying slice at the cursor position and returns them. - /// - /// # Examples - /// - /// ``` - /// #![feature(cursor_split)] - /// use std::io::Cursor; - /// - /// let mut buff = Cursor::new(vec![1, 2, 3, 4, 5]); - /// - /// assert_eq!(buff.split(), ([].as_slice(), [1, 2, 3, 4, 5].as_slice())); - /// - /// buff.set_position(2); - /// assert_eq!(buff.split(), ([1, 2].as_slice(), [3, 4, 5].as_slice())); - /// - /// buff.set_position(6); - /// assert_eq!(buff.split(), ([1, 2, 3, 4, 5].as_slice(), [].as_slice())); - /// ``` - #[unstable(feature = "cursor_split", issue = "86369")] - pub fn split(&self) -> (&[u8], &[u8]) { - let slice = self.inner.as_ref(); - let pos = self.pos.min(slice.len() as u64); - slice.split_at(pos as usize) - } -} - -impl Cursor -where - T: AsMut<[u8]>, -{ - /// Splits the underlying slice at the cursor position and returns them - /// mutably. - /// - /// # Examples - /// - /// ``` - /// #![feature(cursor_split)] - /// use std::io::Cursor; - /// - /// let mut buff = Cursor::new(vec![1, 2, 3, 4, 5]); - /// - /// assert_eq!(buff.split_mut(), ([].as_mut_slice(), [1, 2, 3, 4, 5].as_mut_slice())); - /// - /// buff.set_position(2); - /// assert_eq!(buff.split_mut(), ([1, 2].as_mut_slice(), [3, 4, 5].as_mut_slice())); - /// - /// buff.set_position(6); - /// assert_eq!(buff.split_mut(), ([1, 2, 3, 4, 5].as_mut_slice(), [].as_mut_slice())); - /// ``` - #[unstable(feature = "cursor_split", issue = "86369")] - pub fn split_mut(&mut self) -> (&mut [u8], &mut [u8]) { - let slice = self.inner.as_mut(); - let pos = self.pos.min(slice.len() as u64); - slice.split_at_mut(pos as usize) - } -} - -#[stable(feature = "rust1", since = "1.0.0")] -impl Clone for Cursor -where - T: Clone, -{ - #[inline] - fn clone(&self) -> Self { - Cursor { inner: self.inner.clone(), pos: self.pos } - } - - #[inline] - fn clone_from(&mut self, other: &Self) { - self.inner.clone_from(&other.inner); - self.pos = other.pos; - } -} - #[stable(feature = "rust1", since = "1.0.0")] impl io::Seek for Cursor where @@ -293,16 +17,16 @@ where fn seek(&mut self, style: SeekFrom) -> io::Result { let (base_pos, offset) = match style { SeekFrom::Start(n) => { - self.pos = n; + self.set_position(n); return Ok(n); } - SeekFrom::End(n) => (self.inner.as_ref().len() as u64, n), - SeekFrom::Current(n) => (self.pos, n), + SeekFrom::End(n) => (self.get_ref().as_ref().len() as u64, n), + SeekFrom::Current(n) => (self.position(), n), }; match base_pos.checked_add_signed(offset) { Some(n) => { - self.pos = n; - Ok(self.pos) + self.set_position(n); + Ok(n) } None => Err(io::const_error!( ErrorKind::InvalidInput, @@ -312,11 +36,11 @@ where } fn stream_len(&mut self) -> io::Result { - Ok(self.inner.as_ref().len() as u64) + Ok(self.get_ref().as_ref().len() as u64) } fn stream_position(&mut self) -> io::Result { - Ok(self.pos) + Ok(self.position()) } } @@ -327,7 +51,7 @@ where { fn read(&mut self, buf: &mut [u8]) -> io::Result { let n = Read::read(&mut Cursor::split(self).1, buf)?; - self.pos += n as u64; + self.set_position(self.position() + n as u64); Ok(n) } @@ -336,7 +60,7 @@ where Read::read_buf(&mut Cursor::split(self).1, cursor.reborrow())?; - self.pos += (cursor.written() - prev_written) as u64; + self.set_position(self.position() + (cursor.written() - prev_written) as u64); Ok(()) } @@ -361,9 +85,9 @@ where let result = Read::read_exact(&mut Cursor::split(self).1, buf); match result { - Ok(_) => self.pos += buf.len() as u64, + Ok(_) => self.set_position(self.position() + buf.len() as u64), // The only possible error condition is EOF, so place the cursor at "EOF" - Err(_) => self.pos = self.inner.as_ref().len() as u64, + Err(_) => self.set_position(self.get_ref().as_ref().len() as u64), } result @@ -373,7 +97,7 @@ where let prev_written = cursor.written(); let result = Read::read_buf_exact(&mut Cursor::split(self).1, cursor.reborrow()); - self.pos += (cursor.written() - prev_written) as u64; + self.set_position(self.position() + (cursor.written() - prev_written) as u64); result } @@ -383,7 +107,7 @@ where let len = content.len(); buf.try_reserve(len)?; buf.extend_from_slice(content); - self.pos += len as u64; + self.set_position(self.position() + len as u64); Ok(len) } @@ -394,7 +118,7 @@ where let len = content.len(); buf.try_reserve(len)?; buf.push_str(content); - self.pos += len as u64; + self.set_position(self.position() + len as u64); Ok(len) } @@ -409,7 +133,7 @@ where Ok(Cursor::split(self).1) } fn consume(&mut self, amt: usize) { - self.pos += amt as u64; + self.set_position(self.position() + amt as u64); } } @@ -590,12 +314,14 @@ where impl Write for Cursor<&mut [u8]> { #[inline] fn write(&mut self, buf: &[u8]) -> io::Result { - slice_write(&mut self.pos, self.inner, buf) + let (pos, inner) = self.into_parts_mut(); + slice_write(pos, inner, buf) } #[inline] fn write_vectored(&mut self, bufs: &[IoSlice<'_>]) -> io::Result { - slice_write_vectored(&mut self.pos, self.inner, bufs) + let (pos, inner) = self.into_parts_mut(); + slice_write_vectored(pos, inner, bufs) } #[inline] @@ -605,12 +331,14 @@ impl Write for Cursor<&mut [u8]> { #[inline] fn write_all(&mut self, buf: &[u8]) -> io::Result<()> { - slice_write_all(&mut self.pos, self.inner, buf) + let (pos, inner) = self.into_parts_mut(); + slice_write_all(pos, inner, buf) } #[inline] fn write_all_vectored(&mut self, bufs: &mut [IoSlice<'_>]) -> io::Result<()> { - slice_write_all_vectored(&mut self.pos, self.inner, bufs) + let (pos, inner) = self.into_parts_mut(); + slice_write_all_vectored(pos, inner, bufs) } #[inline] @@ -625,11 +353,13 @@ where A: Allocator, { fn write(&mut self, buf: &[u8]) -> io::Result { - vec_write_all(&mut self.pos, self.inner, buf) + let (pos, inner) = self.into_parts_mut(); + vec_write_all(pos, inner, buf) } fn write_vectored(&mut self, bufs: &[IoSlice<'_>]) -> io::Result { - vec_write_all_vectored(&mut self.pos, self.inner, bufs) + let (pos, inner) = self.into_parts_mut(); + vec_write_all_vectored(pos, inner, bufs) } #[inline] @@ -638,12 +368,14 @@ where } fn write_all(&mut self, buf: &[u8]) -> io::Result<()> { - vec_write_all(&mut self.pos, self.inner, buf)?; + let (pos, inner) = self.into_parts_mut(); + vec_write_all(pos, inner, buf)?; Ok(()) } fn write_all_vectored(&mut self, bufs: &mut [IoSlice<'_>]) -> io::Result<()> { - vec_write_all_vectored(&mut self.pos, self.inner, bufs)?; + let (pos, inner) = self.into_parts_mut(); + vec_write_all_vectored(pos, inner, bufs)?; Ok(()) } @@ -659,11 +391,13 @@ where A: Allocator, { fn write(&mut self, buf: &[u8]) -> io::Result { - vec_write_all(&mut self.pos, &mut self.inner, buf) + let (pos, inner) = self.into_parts_mut(); + vec_write_all(pos, inner, buf) } fn write_vectored(&mut self, bufs: &[IoSlice<'_>]) -> io::Result { - vec_write_all_vectored(&mut self.pos, &mut self.inner, bufs) + let (pos, inner) = self.into_parts_mut(); + vec_write_all_vectored(pos, inner, bufs) } #[inline] @@ -672,12 +406,14 @@ where } fn write_all(&mut self, buf: &[u8]) -> io::Result<()> { - vec_write_all(&mut self.pos, &mut self.inner, buf)?; + let (pos, inner) = self.into_parts_mut(); + vec_write_all(pos, inner, buf)?; Ok(()) } fn write_all_vectored(&mut self, bufs: &mut [IoSlice<'_>]) -> io::Result<()> { - vec_write_all_vectored(&mut self.pos, &mut self.inner, bufs)?; + let (pos, inner) = self.into_parts_mut(); + vec_write_all_vectored(pos, inner, bufs)?; Ok(()) } @@ -694,12 +430,14 @@ where { #[inline] fn write(&mut self, buf: &[u8]) -> io::Result { - slice_write(&mut self.pos, &mut self.inner, buf) + let (pos, inner) = self.into_parts_mut(); + slice_write(pos, inner, buf) } #[inline] fn write_vectored(&mut self, bufs: &[IoSlice<'_>]) -> io::Result { - slice_write_vectored(&mut self.pos, &mut self.inner, bufs) + let (pos, inner) = self.into_parts_mut(); + slice_write_vectored(pos, inner, bufs) } #[inline] @@ -709,12 +447,14 @@ where #[inline] fn write_all(&mut self, buf: &[u8]) -> io::Result<()> { - slice_write_all(&mut self.pos, &mut self.inner, buf) + let (pos, inner) = self.into_parts_mut(); + slice_write_all(pos, inner, buf) } #[inline] fn write_all_vectored(&mut self, bufs: &mut [IoSlice<'_>]) -> io::Result<()> { - slice_write_all_vectored(&mut self.pos, &mut self.inner, bufs) + let (pos, inner) = self.into_parts_mut(); + slice_write_all_vectored(pos, inner, bufs) } #[inline] @@ -727,12 +467,14 @@ where impl Write for Cursor<[u8; N]> { #[inline] fn write(&mut self, buf: &[u8]) -> io::Result { - slice_write(&mut self.pos, &mut self.inner, buf) + let (pos, inner) = self.into_parts_mut(); + slice_write(pos, inner, buf) } #[inline] fn write_vectored(&mut self, bufs: &[IoSlice<'_>]) -> io::Result { - slice_write_vectored(&mut self.pos, &mut self.inner, bufs) + let (pos, inner) = self.into_parts_mut(); + slice_write_vectored(pos, inner, bufs) } #[inline] @@ -742,12 +484,14 @@ impl Write for Cursor<[u8; N]> { #[inline] fn write_all(&mut self, buf: &[u8]) -> io::Result<()> { - slice_write_all(&mut self.pos, &mut self.inner, buf) + let (pos, inner) = self.into_parts_mut(); + slice_write_all(pos, inner, buf) } #[inline] fn write_all_vectored(&mut self, bufs: &mut [IoSlice<'_>]) -> io::Result<()> { - slice_write_all_vectored(&mut self.pos, &mut self.inner, bufs) + let (pos, inner) = self.into_parts_mut(); + slice_write_all_vectored(pos, inner, bufs) } #[inline] diff --git a/library/std/src/lib.rs b/library/std/src/lib.rs index bb280f698b852..f20d1d72d22cb 100644 --- a/library/std/src/lib.rs +++ b/library/std/src/lib.rs @@ -326,6 +326,7 @@ #![feature(core_io_borrowed_buf)] #![feature(core_io_internals)] #![feature(cstr_display)] +#![feature(cursor_split)] #![feature(drop_guard)] #![feature(duration_constants)] #![feature(error_generic_member_access)] From 5cbf9f8c8bcfb8ee0ebefdc7c28d3459ad742254 Mon Sep 17 00:00:00 2001 From: Zac Harrold Date: Mon, 11 May 2026 12:56:26 +1000 Subject: [PATCH 19/19] Move `std::io::util` to `core::io` --- library/core/src/io/mod.rs | 6 + library/core/src/io/util.rs | 415 ++++++++++++++++++++++++++++++++++++ library/std/src/io/mod.rs | 264 +---------------------- library/std/src/io/util.rs | 121 +---------- library/std/src/lib.rs | 1 + 5 files changed, 428 insertions(+), 379 deletions(-) create mode 100644 library/core/src/io/util.rs diff --git a/library/core/src/io/mod.rs b/library/core/src/io/mod.rs index 2d8273dd1b2d0..29ef6e01a9331 100644 --- a/library/core/src/io/mod.rs +++ b/library/core/src/io/mod.rs @@ -2,6 +2,7 @@ mod borrowed_buf; mod error; +mod util; #[unstable(feature = "core_io_borrowed_buf", issue = "117693")] pub use self::borrowed_buf::{BorrowedBuf, BorrowedCursor}; @@ -9,3 +10,8 @@ pub use self::borrowed_buf::{BorrowedBuf, BorrowedCursor}; pub use self::error::ErrorKind; #[unstable(feature = "raw_os_error_ty", issue = "107792")] pub use self::error::RawOsError; +#[unstable(feature = "core_io", issue = "154046")] +pub use self::util::{Chain, Empty, Repeat, Sink, Take, empty, repeat, sink}; +#[doc(hidden)] +#[unstable(feature = "core_io_internals", reason = "exposed only for libstd", issue = "none")] +pub use self::util::{chain, take}; diff --git a/library/core/src/io/util.rs b/library/core/src/io/util.rs new file mode 100644 index 0000000000000..232e388433fb0 --- /dev/null +++ b/library/core/src/io/util.rs @@ -0,0 +1,415 @@ +use crate::fmt; + +/// `Empty` ignores any data written via [`Write`], and will always be empty +/// (returning zero bytes) when read via [`Read`]. +/// +/// [`Write`]: ../../std/io/trait.Write.html +/// [`Read`]: ../../std/io/trait.Read.html +/// +/// This struct is generally created by calling [`empty()`]. Please +/// see the documentation of [`empty()`] for more details. +#[stable(feature = "rust1", since = "1.0.0")] +#[non_exhaustive] +#[derive(Copy, Clone, Debug, Default)] +pub struct Empty; + +/// Creates a value that is always at EOF for reads, and ignores all data written. +/// +/// All calls to [`write`] on the returned instance will return [`Ok(buf.len())`] +/// and the contents of the buffer will not be inspected. +/// +/// All calls to [`read`] from the returned reader will return [`Ok(0)`]. +/// +/// [`Ok(buf.len())`]: Ok +/// [`Ok(0)`]: Ok +/// +/// [`write`]: ../../std/io/trait.Write.html#tymethod.write +/// [`read`]: ../../std/io/trait.Read.html#tymethod.read +/// +/// # Examples +/// +/// ```rust +/// use std::io::{self, Write}; +/// +/// let buffer = vec![1, 2, 3, 5, 8]; +/// let num_bytes = io::empty().write(&buffer).unwrap(); +/// assert_eq!(num_bytes, 5); +/// ``` +/// +/// +/// ```rust +/// use std::io::{self, Read}; +/// +/// let mut buffer = String::new(); +/// io::empty().read_to_string(&mut buffer).unwrap(); +/// assert!(buffer.is_empty()); +/// ``` +#[must_use] +#[stable(feature = "rust1", since = "1.0.0")] +#[rustc_const_stable(feature = "const_io_structs", since = "1.79.0")] +pub const fn empty() -> Empty { + Empty +} + +/// A reader which yields one byte over and over and over and over and over and... +/// +/// This struct is generally created by calling [`repeat()`]. Please +/// see the documentation of [`repeat()`] for more details. +#[stable(feature = "rust1", since = "1.0.0")] +#[non_exhaustive] +pub struct Repeat { + #[doc(hidden)] + #[unstable(feature = "core_io_internals", reason = "exposed only for libstd", issue = "none")] + pub byte: u8, +} + +/// Creates an instance of a reader that infinitely repeats one byte. +/// +/// All reads from this reader will succeed by filling the specified buffer with +/// the given byte. +/// +/// # Examples +/// +/// ``` +/// use std::io::{self, Read}; +/// +/// let mut buffer = [0; 3]; +/// io::repeat(0b101).read_exact(&mut buffer).unwrap(); +/// assert_eq!(buffer, [0b101, 0b101, 0b101]); +/// ``` +#[must_use] +#[stable(feature = "rust1", since = "1.0.0")] +#[rustc_const_stable(feature = "const_io_structs", since = "1.79.0")] +pub const fn repeat(byte: u8) -> Repeat { + Repeat { byte } +} + +#[stable(feature = "std_debug", since = "1.16.0")] +impl fmt::Debug for Repeat { + fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { + f.debug_struct("Repeat").finish_non_exhaustive() + } +} + +/// A writer which will move data into the void. +/// +/// This struct is generally created by calling [`sink()`]. Please +/// see the documentation of [`sink()`] for more details. +#[stable(feature = "rust1", since = "1.0.0")] +#[non_exhaustive] +#[derive(Copy, Clone, Debug, Default)] +pub struct Sink; + +/// Creates an instance of a writer which will successfully consume all data. +/// +/// All calls to [`write`] on the returned instance will return [`Ok(buf.len())`] +/// and the contents of the buffer will not be inspected. +/// +/// [`write`]: ../../std/io/trait.Write.html#tymethod.write +/// [`Ok(buf.len())`]: Ok +/// +/// # Examples +/// +/// ```rust +/// use std::io::{self, Write}; +/// +/// let buffer = vec![1, 2, 3, 5, 8]; +/// let num_bytes = io::sink().write(&buffer).unwrap(); +/// assert_eq!(num_bytes, 5); +/// ``` +#[must_use] +#[stable(feature = "rust1", since = "1.0.0")] +#[rustc_const_stable(feature = "const_io_structs", since = "1.79.0")] +pub const fn sink() -> Sink { + Sink +} + +/// Adapter to chain together two readers. +/// +/// This struct is generally created by calling [`chain`] on a reader. +/// Please see the documentation of [`chain`] for more details. +/// +/// [`chain`]: ../../std/io/trait.Read.html#method.chain +#[stable(feature = "rust1", since = "1.0.0")] +#[derive(Debug)] +#[non_exhaustive] +pub struct Chain { + #[doc(hidden)] + #[unstable(feature = "core_io_internals", reason = "exposed only for libstd", issue = "none")] + pub first: T, + #[doc(hidden)] + #[unstable(feature = "core_io_internals", reason = "exposed only for libstd", issue = "none")] + pub second: U, + #[doc(hidden)] + #[unstable(feature = "core_io_internals", reason = "exposed only for libstd", issue = "none")] + pub done_first: bool, +} + +impl Chain { + /// Consumes the `Chain`, returning the wrapped readers. + /// + /// # Examples + /// + /// ```no_run + /// use std::io; + /// use std::io::prelude::*; + /// use std::fs::File; + /// + /// fn main() -> io::Result<()> { + /// let mut foo_file = File::open("foo.txt")?; + /// let mut bar_file = File::open("bar.txt")?; + /// + /// let chain = foo_file.chain(bar_file); + /// let (foo_file, bar_file) = chain.into_inner(); + /// Ok(()) + /// } + /// ``` + #[stable(feature = "more_io_inner_methods", since = "1.20.0")] + pub fn into_inner(self) -> (T, U) { + (self.first, self.second) + } + + /// Gets references to the underlying readers in this `Chain`. + /// + /// Care should be taken to avoid modifying the internal I/O state of the + /// underlying readers as doing so may corrupt the internal state of this + /// `Chain`. + /// + /// # Examples + /// + /// ```no_run + /// use std::io; + /// use std::io::prelude::*; + /// use std::fs::File; + /// + /// fn main() -> io::Result<()> { + /// let mut foo_file = File::open("foo.txt")?; + /// let mut bar_file = File::open("bar.txt")?; + /// + /// let chain = foo_file.chain(bar_file); + /// let (foo_file, bar_file) = chain.get_ref(); + /// Ok(()) + /// } + /// ``` + #[stable(feature = "more_io_inner_methods", since = "1.20.0")] + pub fn get_ref(&self) -> (&T, &U) { + (&self.first, &self.second) + } + + /// Gets mutable references to the underlying readers in this `Chain`. + /// + /// Care should be taken to avoid modifying the internal I/O state of the + /// underlying readers as doing so may corrupt the internal state of this + /// `Chain`. + /// + /// # Examples + /// + /// ```no_run + /// use std::io; + /// use std::io::prelude::*; + /// use std::fs::File; + /// + /// fn main() -> io::Result<()> { + /// let mut foo_file = File::open("foo.txt")?; + /// let mut bar_file = File::open("bar.txt")?; + /// + /// let mut chain = foo_file.chain(bar_file); + /// let (foo_file, bar_file) = chain.get_mut(); + /// Ok(()) + /// } + /// ``` + #[stable(feature = "more_io_inner_methods", since = "1.20.0")] + pub fn get_mut(&mut self) -> (&mut T, &mut U) { + (&mut self.first, &mut self.second) + } +} + +#[doc(hidden)] +#[unstable(feature = "core_io_internals", reason = "exposed only for libstd", issue = "none")] +#[must_use] +#[inline] +pub const fn chain(first: T, second: U) -> Chain { + Chain { first, second, done_first: false } +} + +/// Reader adapter which limits the bytes read from an underlying reader. +/// +/// This struct is generally created by calling [`take`] on a reader. +/// Please see the documentation of [`take`] for more details. +/// +/// [`take`]: ../../std/io/trait.Read.html#method.take +#[stable(feature = "rust1", since = "1.0.0")] +#[derive(Debug)] +#[non_exhaustive] +pub struct Take { + #[doc(hidden)] + #[unstable(feature = "core_io_internals", reason = "exposed only for libstd", issue = "none")] + pub inner: T, + #[doc(hidden)] + #[unstable(feature = "core_io_internals", reason = "exposed only for libstd", issue = "none")] + pub len: u64, + #[doc(hidden)] + #[unstable(feature = "core_io_internals", reason = "exposed only for libstd", issue = "none")] + pub limit: u64, +} + +impl Take { + /// Returns the number of bytes that can be read before this instance will + /// return EOF. + /// + /// # Note + /// + /// This instance may reach `EOF` after reading fewer bytes than indicated by + /// this method if the underlying [`Read`] instance reaches EOF. + /// + /// [`Read`]: ../../std/io/trait.Read.html + /// + /// # Examples + /// + /// ```no_run + /// use std::io; + /// use std::io::prelude::*; + /// use std::fs::File; + /// + /// fn main() -> io::Result<()> { + /// let f = File::open("foo.txt")?; + /// + /// // read at most five bytes + /// let handle = f.take(5); + /// + /// println!("limit: {}", handle.limit()); + /// Ok(()) + /// } + /// ``` + #[stable(feature = "rust1", since = "1.0.0")] + pub fn limit(&self) -> u64 { + self.limit + } + + /// Returns the number of bytes read so far. + #[unstable(feature = "seek_io_take_position", issue = "97227")] + #[inline] + pub fn position(&self) -> u64 { + self.len - self.limit + } + + /// Sets the number of bytes that can be read before this instance will + /// return EOF. This is the same as constructing a new `Take` instance, so + /// the amount of bytes read and the previous limit value don't matter when + /// calling this method. + /// + /// # Examples + /// + /// ```no_run + /// use std::io; + /// use std::io::prelude::*; + /// use std::fs::File; + /// + /// fn main() -> io::Result<()> { + /// let f = File::open("foo.txt")?; + /// + /// // read at most five bytes + /// let mut handle = f.take(5); + /// handle.set_limit(10); + /// + /// assert_eq!(handle.limit(), 10); + /// Ok(()) + /// } + /// ``` + #[stable(feature = "take_set_limit", since = "1.27.0")] + pub fn set_limit(&mut self, limit: u64) { + self.len = limit; + self.limit = limit; + } + + /// Consumes the `Take`, returning the wrapped reader. + /// + /// # Examples + /// + /// ```no_run + /// use std::io; + /// use std::io::prelude::*; + /// use std::fs::File; + /// + /// fn main() -> io::Result<()> { + /// let mut file = File::open("foo.txt")?; + /// + /// let mut buffer = [0; 5]; + /// let mut handle = file.take(5); + /// handle.read(&mut buffer)?; + /// + /// let file = handle.into_inner(); + /// Ok(()) + /// } + /// ``` + #[stable(feature = "io_take_into_inner", since = "1.15.0")] + pub fn into_inner(self) -> T { + self.inner + } + + /// Gets a reference to the underlying reader. + /// + /// Care should be taken to avoid modifying the internal I/O state of the + /// underlying reader as doing so may corrupt the internal limit of this + /// `Take`. + /// + /// # Examples + /// + /// ```no_run + /// use std::io; + /// use std::io::prelude::*; + /// use std::fs::File; + /// + /// fn main() -> io::Result<()> { + /// let mut file = File::open("foo.txt")?; + /// + /// let mut buffer = [0; 5]; + /// let mut handle = file.take(5); + /// handle.read(&mut buffer)?; + /// + /// let file = handle.get_ref(); + /// Ok(()) + /// } + /// ``` + #[stable(feature = "more_io_inner_methods", since = "1.20.0")] + pub fn get_ref(&self) -> &T { + &self.inner + } + + /// Gets a mutable reference to the underlying reader. + /// + /// Care should be taken to avoid modifying the internal I/O state of the + /// underlying reader as doing so may corrupt the internal limit of this + /// `Take`. + /// + /// # Examples + /// + /// ```no_run + /// use std::io; + /// use std::io::prelude::*; + /// use std::fs::File; + /// + /// fn main() -> io::Result<()> { + /// let mut file = File::open("foo.txt")?; + /// + /// let mut buffer = [0; 5]; + /// let mut handle = file.take(5); + /// handle.read(&mut buffer)?; + /// + /// let file = handle.get_mut(); + /// Ok(()) + /// } + /// ``` + #[stable(feature = "more_io_inner_methods", since = "1.20.0")] + pub fn get_mut(&mut self) -> &mut T { + &mut self.inner + } +} + +#[doc(hidden)] +#[unstable(feature = "core_io_internals", reason = "exposed only for libstd", issue = "none")] +#[must_use] +#[inline] +pub const fn take(inner: T, limit: u64) -> Take { + Take { inner, limit, len: limit } +} diff --git a/library/std/src/io/mod.rs b/library/std/src/io/mod.rs index f79a93214ea2c..43a6a18ac2c3f 100644 --- a/library/std/src/io/mod.rs +++ b/library/std/src/io/mod.rs @@ -299,6 +299,8 @@ mod tests; #[unstable(feature = "read_buf", issue = "78485")] pub use core::io::{BorrowedBuf, BorrowedCursor}; +#[stable(feature = "rust1", since = "1.0.0")] +pub use core::io::{Chain, Empty, Repeat, Sink, Take, empty, repeat, sink}; use core::slice::memchr; #[stable(feature = "bufwriter_into_parts", since = "1.56.0")] @@ -328,7 +330,6 @@ pub use self::{ cursor::Cursor, error::{Error, ErrorKind, Result}, stdio::{Stderr, StderrLock, Stdin, StdinLock, Stdout, StdoutLock, stderr, stdin, stdout}, - util::{Empty, Repeat, Sink, empty, repeat, sink}, }; use crate::mem::{MaybeUninit, take}; use crate::ops::{Deref, DerefMut}; @@ -1183,7 +1184,7 @@ pub trait Read { where Self: Sized, { - Chain { first: self, second: next, done_first: false } + core::io::chain(self, next) } /// Creates an adapter which will read at most `limit` bytes from it. @@ -1222,7 +1223,7 @@ pub trait Read { where Self: Sized, { - Take { inner: self, len: limit, limit } + core::io::take(self, limit) } /// Read and return a fixed array of bytes from this source. @@ -2704,99 +2705,6 @@ pub trait BufRead: Read { } } -/// Adapter to chain together two readers. -/// -/// This struct is generally created by calling [`chain`] on a reader. -/// Please see the documentation of [`chain`] for more details. -/// -/// [`chain`]: Read::chain -#[stable(feature = "rust1", since = "1.0.0")] -#[derive(Debug)] -pub struct Chain { - first: T, - second: U, - done_first: bool, -} - -impl Chain { - /// Consumes the `Chain`, returning the wrapped readers. - /// - /// # Examples - /// - /// ```no_run - /// use std::io; - /// use std::io::prelude::*; - /// use std::fs::File; - /// - /// fn main() -> io::Result<()> { - /// let mut foo_file = File::open("foo.txt")?; - /// let mut bar_file = File::open("bar.txt")?; - /// - /// let chain = foo_file.chain(bar_file); - /// let (foo_file, bar_file) = chain.into_inner(); - /// Ok(()) - /// } - /// ``` - #[stable(feature = "more_io_inner_methods", since = "1.20.0")] - pub fn into_inner(self) -> (T, U) { - (self.first, self.second) - } - - /// Gets references to the underlying readers in this `Chain`. - /// - /// Care should be taken to avoid modifying the internal I/O state of the - /// underlying readers as doing so may corrupt the internal state of this - /// `Chain`. - /// - /// # Examples - /// - /// ```no_run - /// use std::io; - /// use std::io::prelude::*; - /// use std::fs::File; - /// - /// fn main() -> io::Result<()> { - /// let mut foo_file = File::open("foo.txt")?; - /// let mut bar_file = File::open("bar.txt")?; - /// - /// let chain = foo_file.chain(bar_file); - /// let (foo_file, bar_file) = chain.get_ref(); - /// Ok(()) - /// } - /// ``` - #[stable(feature = "more_io_inner_methods", since = "1.20.0")] - pub fn get_ref(&self) -> (&T, &U) { - (&self.first, &self.second) - } - - /// Gets mutable references to the underlying readers in this `Chain`. - /// - /// Care should be taken to avoid modifying the internal I/O state of the - /// underlying readers as doing so may corrupt the internal state of this - /// `Chain`. - /// - /// # Examples - /// - /// ```no_run - /// use std::io; - /// use std::io::prelude::*; - /// use std::fs::File; - /// - /// fn main() -> io::Result<()> { - /// let mut foo_file = File::open("foo.txt")?; - /// let mut bar_file = File::open("bar.txt")?; - /// - /// let mut chain = foo_file.chain(bar_file); - /// let (foo_file, bar_file) = chain.get_mut(); - /// Ok(()) - /// } - /// ``` - #[stable(feature = "more_io_inner_methods", since = "1.20.0")] - pub fn get_mut(&mut self) -> (&mut T, &mut U) { - (&mut self.first, &mut self.second) - } -} - #[stable(feature = "rust1", since = "1.0.0")] impl Read for Chain { fn read(&mut self, buf: &mut [u8]) -> Result { @@ -2906,170 +2814,6 @@ impl SizeHint for Chain { } } -/// Reader adapter which limits the bytes read from an underlying reader. -/// -/// This struct is generally created by calling [`take`] on a reader. -/// Please see the documentation of [`take`] for more details. -/// -/// [`take`]: Read::take -#[stable(feature = "rust1", since = "1.0.0")] -#[derive(Debug)] -pub struct Take { - inner: T, - len: u64, - limit: u64, -} - -impl Take { - /// Returns the number of bytes that can be read before this instance will - /// return EOF. - /// - /// # Note - /// - /// This instance may reach `EOF` after reading fewer bytes than indicated by - /// this method if the underlying [`Read`] instance reaches EOF. - /// - /// # Examples - /// - /// ```no_run - /// use std::io; - /// use std::io::prelude::*; - /// use std::fs::File; - /// - /// fn main() -> io::Result<()> { - /// let f = File::open("foo.txt")?; - /// - /// // read at most five bytes - /// let handle = f.take(5); - /// - /// println!("limit: {}", handle.limit()); - /// Ok(()) - /// } - /// ``` - #[stable(feature = "rust1", since = "1.0.0")] - pub fn limit(&self) -> u64 { - self.limit - } - - /// Returns the number of bytes read so far. - #[unstable(feature = "seek_io_take_position", issue = "97227")] - pub fn position(&self) -> u64 { - self.len - self.limit - } - - /// Sets the number of bytes that can be read before this instance will - /// return EOF. This is the same as constructing a new `Take` instance, so - /// the amount of bytes read and the previous limit value don't matter when - /// calling this method. - /// - /// # Examples - /// - /// ```no_run - /// use std::io; - /// use std::io::prelude::*; - /// use std::fs::File; - /// - /// fn main() -> io::Result<()> { - /// let f = File::open("foo.txt")?; - /// - /// // read at most five bytes - /// let mut handle = f.take(5); - /// handle.set_limit(10); - /// - /// assert_eq!(handle.limit(), 10); - /// Ok(()) - /// } - /// ``` - #[stable(feature = "take_set_limit", since = "1.27.0")] - pub fn set_limit(&mut self, limit: u64) { - self.len = limit; - self.limit = limit; - } - - /// Consumes the `Take`, returning the wrapped reader. - /// - /// # Examples - /// - /// ```no_run - /// use std::io; - /// use std::io::prelude::*; - /// use std::fs::File; - /// - /// fn main() -> io::Result<()> { - /// let mut file = File::open("foo.txt")?; - /// - /// let mut buffer = [0; 5]; - /// let mut handle = file.take(5); - /// handle.read(&mut buffer)?; - /// - /// let file = handle.into_inner(); - /// Ok(()) - /// } - /// ``` - #[stable(feature = "io_take_into_inner", since = "1.15.0")] - pub fn into_inner(self) -> T { - self.inner - } - - /// Gets a reference to the underlying reader. - /// - /// Care should be taken to avoid modifying the internal I/O state of the - /// underlying reader as doing so may corrupt the internal limit of this - /// `Take`. - /// - /// # Examples - /// - /// ```no_run - /// use std::io; - /// use std::io::prelude::*; - /// use std::fs::File; - /// - /// fn main() -> io::Result<()> { - /// let mut file = File::open("foo.txt")?; - /// - /// let mut buffer = [0; 5]; - /// let mut handle = file.take(5); - /// handle.read(&mut buffer)?; - /// - /// let file = handle.get_ref(); - /// Ok(()) - /// } - /// ``` - #[stable(feature = "more_io_inner_methods", since = "1.20.0")] - pub fn get_ref(&self) -> &T { - &self.inner - } - - /// Gets a mutable reference to the underlying reader. - /// - /// Care should be taken to avoid modifying the internal I/O state of the - /// underlying reader as doing so may corrupt the internal limit of this - /// `Take`. - /// - /// # Examples - /// - /// ```no_run - /// use std::io; - /// use std::io::prelude::*; - /// use std::fs::File; - /// - /// fn main() -> io::Result<()> { - /// let mut file = File::open("foo.txt")?; - /// - /// let mut buffer = [0; 5]; - /// let mut handle = file.take(5); - /// handle.read(&mut buffer)?; - /// - /// let file = handle.get_mut(); - /// Ok(()) - /// } - /// ``` - #[stable(feature = "more_io_inner_methods", since = "1.20.0")] - pub fn get_mut(&mut self) -> &mut T { - &mut self.inner - } -} - #[stable(feature = "rust1", since = "1.0.0")] impl Read for Take { fn read(&mut self, buf: &mut [u8]) -> Result { diff --git a/library/std/src/io/util.rs b/library/std/src/io/util.rs index a09c8bc069306..3f207939c7389 100644 --- a/library/std/src/io/util.rs +++ b/library/std/src/io/util.rs @@ -5,57 +5,10 @@ mod tests; use crate::fmt; use crate::io::{ - self, BorrowedCursor, BufRead, IoSlice, IoSliceMut, Read, Seek, SeekFrom, SizeHint, Write, + self, BorrowedCursor, BufRead, Empty, IoSlice, IoSliceMut, Read, Repeat, Seek, SeekFrom, Sink, + SizeHint, Write, }; -/// `Empty` ignores any data written via [`Write`], and will always be empty -/// (returning zero bytes) when read via [`Read`]. -/// -/// This struct is generally created by calling [`empty()`]. Please -/// see the documentation of [`empty()`] for more details. -#[stable(feature = "rust1", since = "1.0.0")] -#[non_exhaustive] -#[derive(Copy, Clone, Debug, Default)] -pub struct Empty; - -/// Creates a value that is always at EOF for reads, and ignores all data written. -/// -/// All calls to [`write`] on the returned instance will return [`Ok(buf.len())`] -/// and the contents of the buffer will not be inspected. -/// -/// All calls to [`read`] from the returned reader will return [`Ok(0)`]. -/// -/// [`Ok(buf.len())`]: Ok -/// [`Ok(0)`]: Ok -/// -/// [`write`]: Write::write -/// [`read`]: Read::read -/// -/// # Examples -/// -/// ```rust -/// use std::io::{self, Write}; -/// -/// let buffer = vec![1, 2, 3, 5, 8]; -/// let num_bytes = io::empty().write(&buffer).unwrap(); -/// assert_eq!(num_bytes, 5); -/// ``` -/// -/// -/// ```rust -/// use std::io::{self, Read}; -/// -/// let mut buffer = String::new(); -/// io::empty().read_to_string(&mut buffer).unwrap(); -/// assert!(buffer.is_empty()); -/// ``` -#[must_use] -#[stable(feature = "rust1", since = "1.0.0")] -#[rustc_const_stable(feature = "const_io_structs", since = "1.79.0")] -pub const fn empty() -> Empty { - Empty -} - #[stable(feature = "rust1", since = "1.0.0")] impl Read for Empty { #[inline] @@ -234,36 +187,6 @@ impl Write for &Empty { } } -/// A reader which yields one byte over and over and over and over and over and... -/// -/// This struct is generally created by calling [`repeat()`]. Please -/// see the documentation of [`repeat()`] for more details. -#[stable(feature = "rust1", since = "1.0.0")] -pub struct Repeat { - byte: u8, -} - -/// Creates an instance of a reader that infinitely repeats one byte. -/// -/// All reads from this reader will succeed by filling the specified buffer with -/// the given byte. -/// -/// # Examples -/// -/// ``` -/// use std::io::{self, Read}; -/// -/// let mut buffer = [0; 3]; -/// io::repeat(0b101).read_exact(&mut buffer).unwrap(); -/// assert_eq!(buffer, [0b101, 0b101, 0b101]); -/// ``` -#[must_use] -#[stable(feature = "rust1", since = "1.0.0")] -#[rustc_const_stable(feature = "const_io_structs", since = "1.79.0")] -pub const fn repeat(byte: u8) -> Repeat { - Repeat { byte } -} - #[stable(feature = "rust1", since = "1.0.0")] impl Read for Repeat { #[inline] @@ -329,46 +252,6 @@ impl SizeHint for Repeat { } } -#[stable(feature = "std_debug", since = "1.16.0")] -impl fmt::Debug for Repeat { - fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { - f.debug_struct("Repeat").finish_non_exhaustive() - } -} - -/// A writer which will move data into the void. -/// -/// This struct is generally created by calling [`sink()`]. Please -/// see the documentation of [`sink()`] for more details. -#[stable(feature = "rust1", since = "1.0.0")] -#[non_exhaustive] -#[derive(Copy, Clone, Debug, Default)] -pub struct Sink; - -/// Creates an instance of a writer which will successfully consume all data. -/// -/// All calls to [`write`] on the returned instance will return [`Ok(buf.len())`] -/// and the contents of the buffer will not be inspected. -/// -/// [`write`]: Write::write -/// [`Ok(buf.len())`]: Ok -/// -/// # Examples -/// -/// ```rust -/// use std::io::{self, Write}; -/// -/// let buffer = vec![1, 2, 3, 5, 8]; -/// let num_bytes = io::sink().write(&buffer).unwrap(); -/// assert_eq!(num_bytes, 5); -/// ``` -#[must_use] -#[stable(feature = "rust1", since = "1.0.0")] -#[rustc_const_stable(feature = "const_io_structs", since = "1.79.0")] -pub const fn sink() -> Sink { - Sink -} - #[stable(feature = "rust1", since = "1.0.0")] impl Write for Sink { #[inline] diff --git a/library/std/src/lib.rs b/library/std/src/lib.rs index bb280f698b852..501871b3a93b9 100644 --- a/library/std/src/lib.rs +++ b/library/std/src/lib.rs @@ -365,6 +365,7 @@ #![feature(ptr_mask)] #![feature(random)] #![feature(raw_os_error_ty)] +#![feature(seek_io_take_position)] #![feature(slice_internals)] #![feature(slice_ptr_get)] #![feature(slice_range)]