From 8b4077329636345480fdaa3c467f4d7b6a9e56d2 Mon Sep 17 00:00:00 2001 From: Obei Sideg Date: Thu, 25 Jun 2026 01:12:01 +0300 Subject: [PATCH 01/12] Add `raw_borrows_via_references` lint Signed-off-by: Obei Sideg --- compiler/rustc_lint/src/lib.rs | 3 + compiler/rustc_lint/src/lints.rs | 26 ++++++ .../src/raw_borrows_via_references.rs | 83 +++++++++++++++++++ 3 files changed, 112 insertions(+) create mode 100644 compiler/rustc_lint/src/raw_borrows_via_references.rs diff --git a/compiler/rustc_lint/src/lib.rs b/compiler/rustc_lint/src/lib.rs index 5271217593e62..310cbb430bbe7 100644 --- a/compiler/rustc_lint/src/lib.rs +++ b/compiler/rustc_lint/src/lib.rs @@ -71,6 +71,7 @@ mod opaque_hidden_inferred_bound; mod passes; mod precedence; mod ptr_nulls; +mod raw_borrows_via_references; mod redundant_semicolon; mod reference_casting; mod runtime_symbols; @@ -117,6 +118,7 @@ use noop_method_call::*; use opaque_hidden_inferred_bound::*; use precedence::*; use ptr_nulls::*; +use raw_borrows_via_references::*; use redundant_semicolon::*; use reference_casting::*; use runtime_symbols::*; @@ -273,6 +275,7 @@ late_lint_methods!( InternalEqTraitMethodImpls: InternalEqTraitMethodImpls, ImplicitProvenanceCasts: ImplicitProvenanceCasts, CVoidReturns: CVoidReturns, + RawBorrowsViaReferences: RawBorrowsViaReferences, ] ] ); diff --git a/compiler/rustc_lint/src/lints.rs b/compiler/rustc_lint/src/lints.rs index 7ea5635034a27..0a0dce2e9d2fc 100644 --- a/compiler/rustc_lint/src/lints.rs +++ b/compiler/rustc_lint/src/lints.rs @@ -3037,3 +3037,29 @@ pub(crate) enum Ptr2IntSuggestion<'tcx> { cast_span: Span, }, } + +#[derive(Diagnostic)] +#[diag( + "creating an intermediate reference implies aliasing requirements even when immediately cast to a raw pointers" +)] +pub(crate) struct RawBorrowViaReference<'a> { + #[subdiagnostic] + pub suggestion: RawBorrowViaReferenceSuggestion<'a>, +} + +#[derive(Subdiagnostic)] +pub(crate) enum RawBorrowViaReferenceSuggestion<'a> { + #[multipart_suggestion( + "consider using `&raw {$mutbl}` for a safer and more explicit raw pointer", + applicability = "machine-applicable" + )] + Spanful { + #[suggestion_part(code = "&raw {mutbl} ")] + left: Span, + #[suggestion_part(code = "")] + right: Span, + mutbl: &'a str, + }, + #[help("consider using `&raw {$mutbl}` for a safer and more explicit raw pointer")] + Spanless { mutbl: &'a str }, +} diff --git a/compiler/rustc_lint/src/raw_borrows_via_references.rs b/compiler/rustc_lint/src/raw_borrows_via_references.rs new file mode 100644 index 0000000000000..69ae1b61e094c --- /dev/null +++ b/compiler/rustc_lint/src/raw_borrows_via_references.rs @@ -0,0 +1,83 @@ +use rustc_ast::BorrowKind; +use rustc_hir::{Expr, ExprKind, TyKind}; +use rustc_session::{declare_lint, declare_lint_pass}; + +use crate::lints::{RawBorrowViaReference, RawBorrowViaReferenceSuggestion}; +use crate::{LateContext, LateLintPass, LintContext}; + +declare_lint! { + /// The `raw_borrows_via_references` lint checks for references that decay immediately into raw borrows. + /// + /// ### Example + /// + /// ```rust + /// #![warn(raw_borrows_via_references)] + /// + /// fn via_ref(x: *const (i32, i32)) -> *const i32 { + /// unsafe { &(*x).0 as *const i32 } + /// } + /// + /// fn main() { + /// let x = (0, 1); + /// let _r = via_ref(&x); + /// } + /// ``` + /// + /// {{produces}} + /// + /// ### Explanation + /// + /// Creating unnecessary references is discouraged because it makes code + /// less explicit and can lead to undefined behavior. Creating a reference + /// induces aliasing assumptions that the compiler relies on, so an + /// otherwise-pointless reference can cause undefined behavior even when the + /// reference is never read through. Avoiding them keeps the code more + /// explicit and easier to reason about. + /// + /// See the [Reference] for the full set of validity requirements that + /// references must uphold. + /// + /// [Reference]: https://doc.rust-lang.org/reference/behavior-considered-undefined.html + /// + /// This lint is "allow" by default because it will trigger for a large + /// amount of existing Rust code. + /// Eventually it is desired for this to become warn-by-default. + pub RAW_BORROWS_VIA_REFERENCES, + // FIXME: This should eventually be `Warn`, see the "Explanation" above. + Allow, + "creating raw borrows via references is discouraged" +} + +declare_lint_pass!(RawBorrowsViaReferences => [RAW_BORROWS_VIA_REFERENCES]); + +impl<'tcx> LateLintPass<'tcx> for RawBorrowsViaReferences { + fn check_expr(&mut self, cx: &LateContext<'tcx>, expr: &Expr<'_>) { + if let ExprKind::Cast(exp, ty) = expr.kind + && let ExprKind::AddrOf(BorrowKind::Ref, mutbl, addr_of_exp) = exp.kind + && let TyKind::Ptr(_) = ty.kind + && addr_of_exp.is_syntactic_place_expr() + { + let suggestion = if let Some(addr_of_span) = + addr_of_exp.span.find_ancestor_in_same_ctxt(expr.span) + && let Some(ty_span) = ty.span.find_ancestor_in_same_ctxt(expr.span) + && expr.span.can_be_used_for_suggestions() + && addr_of_span.can_be_used_for_suggestions() + && ty_span.can_be_used_for_suggestions() + { + RawBorrowViaReferenceSuggestion::Spanful { + left: expr.span.until(addr_of_span), + right: addr_of_span.shrink_to_hi().until(ty_span.shrink_to_hi()), + mutbl: mutbl.ptr_str(), + } + } else { + RawBorrowViaReferenceSuggestion::Spanless { mutbl: mutbl.ptr_str() } + }; + + cx.emit_span_lint( + RAW_BORROWS_VIA_REFERENCES, + expr.span, + RawBorrowViaReference { suggestion }, + ); + } + } +} From ce2fc225d1bedfb721c9ac5569b7eae0d4db98eb Mon Sep 17 00:00:00 2001 From: Obei Sideg Date: Sat, 27 Jun 2026 11:47:47 +0300 Subject: [PATCH 02/12] Add test for `raw_borrows_via_references` lint Signed-off-by: Obei Sideg --- .../lint-raw-borrows-via-references.fixed | 87 ++++++++++++ .../lint/lint-raw-borrows-via-references.rs | 87 ++++++++++++ .../lint-raw-borrows-via-references.stderr | 127 ++++++++++++++++++ 3 files changed, 301 insertions(+) create mode 100644 tests/ui/lint/lint-raw-borrows-via-references.fixed create mode 100644 tests/ui/lint/lint-raw-borrows-via-references.rs create mode 100644 tests/ui/lint/lint-raw-borrows-via-references.stderr diff --git a/tests/ui/lint/lint-raw-borrows-via-references.fixed b/tests/ui/lint/lint-raw-borrows-via-references.fixed new file mode 100644 index 0000000000000..8b81164f60375 --- /dev/null +++ b/tests/ui/lint/lint-raw-borrows-via-references.fixed @@ -0,0 +1,87 @@ +//@ check-pass +//@ run-rustfix +//@ rustfix-only-machine-applicable + +#![allow(dead_code, unused_variables)] +#![warn(raw_borrows_via_references)] + +struct A { + a: i32, + b: u8, +} + +fn via_ref(x: *const (i32, i32)) -> *const i32 { + unsafe { &raw const (*x).0 } + //~^ WARN creating an intermediate reference implies aliasing requirements even when immediately cast to a raw pointers [raw_borrows_via_references] +} + +fn via_ref_struct(x: *const A) -> *const u8 { + unsafe { &raw const (*x).b } + //~^ WARN creating an intermediate reference implies aliasing requirements even when immediately cast to a raw pointers [raw_borrows_via_references] +} + +fn via_ref_mut(x: *mut (i32, i32)) -> *mut i32 { + unsafe { &raw mut (*x).0 } + //~^ WARN creating an intermediate reference implies aliasing requirements even when immediately cast to a raw pointers [raw_borrows_via_references] +} + +fn via_ref_struct_mut(x: *mut A) -> *mut i32 { + unsafe { &raw mut (*x).a } + //~^ WARN creating an intermediate reference implies aliasing requirements even when immediately cast to a raw pointers [raw_borrows_via_references] +} + +fn multiple_casts(x: *const (i32, i32)) -> *const u8 { + unsafe { &raw const (*x).0 as *const u8 } + //~^ WARN creating an intermediate reference implies aliasing requirements even when immediately cast to a raw pointers [raw_borrows_via_references] +} + +fn ret_i32() -> i32 { + 0 +} + +fn temporaries() { + let _ = &1 as *const i32; + let _ = &(1 + 2) as *const i32; + let _ = &ret_i32() as *const i32; + let _ = &(1, 2) as *const (i32, i32); + let _ = &[1, 2, 3] as *const [i32; 3]; + let _ = &A { a: 0, b: 0 } as *const A; + let _ = &mut 4 as *mut i32; +} + +fn inner_blocks() { + let x = 0; + let _ = { &raw const x }; + //~^ WARN creating an intermediate reference implies aliasing requirements even when immediately cast to a raw pointers [raw_borrows_via_references] + + let _ = { + let y = 0; + { &raw const y } + //~^ WARN creating an intermediate reference implies aliasing requirements even when immediately cast to a raw pointers [raw_borrows_via_references] + }; + + let _ = { &1 as *const i32 }; +} + +macro_rules! ref_cast { + ($e:expr) => { + &$e as *const i32 + //~^ WARN creating an intermediate reference implies aliasing requirements even when immediately cast to a raw pointers [raw_borrows_via_references] + }; +} + +fn from_macro(x: *const i32) -> *const i32 { + unsafe { ref_cast!(*x) } +} + +fn main() { + let a = 0; + let a = &raw const a; + //~^ WARN creating an intermediate reference implies aliasing requirements even when immediately cast to a raw pointers [raw_borrows_via_references] + + let mut b = 0; + let b = &raw mut b; + //~^ WARN creating an intermediate reference implies aliasing requirements even when immediately cast to a raw pointers [raw_borrows_via_references] + + let i = &1 as *const i32; +} diff --git a/tests/ui/lint/lint-raw-borrows-via-references.rs b/tests/ui/lint/lint-raw-borrows-via-references.rs new file mode 100644 index 0000000000000..621907bd15df0 --- /dev/null +++ b/tests/ui/lint/lint-raw-borrows-via-references.rs @@ -0,0 +1,87 @@ +//@ check-pass +//@ run-rustfix +//@ rustfix-only-machine-applicable + +#![allow(dead_code, unused_variables)] +#![warn(raw_borrows_via_references)] + +struct A { + a: i32, + b: u8, +} + +fn via_ref(x: *const (i32, i32)) -> *const i32 { + unsafe { &(*x).0 as *const i32 } + //~^ WARN creating an intermediate reference implies aliasing requirements even when immediately cast to a raw pointers [raw_borrows_via_references] +} + +fn via_ref_struct(x: *const A) -> *const u8 { + unsafe { &(*x).b as *const u8 } + //~^ WARN creating an intermediate reference implies aliasing requirements even when immediately cast to a raw pointers [raw_borrows_via_references] +} + +fn via_ref_mut(x: *mut (i32, i32)) -> *mut i32 { + unsafe { &mut (*x).0 as *mut i32 } + //~^ WARN creating an intermediate reference implies aliasing requirements even when immediately cast to a raw pointers [raw_borrows_via_references] +} + +fn via_ref_struct_mut(x: *mut A) -> *mut i32 { + unsafe { &mut (*x).a as *mut i32 } + //~^ WARN creating an intermediate reference implies aliasing requirements even when immediately cast to a raw pointers [raw_borrows_via_references] +} + +fn multiple_casts(x: *const (i32, i32)) -> *const u8 { + unsafe { &(*x).0 as *const i32 as *const u8 } + //~^ WARN creating an intermediate reference implies aliasing requirements even when immediately cast to a raw pointers [raw_borrows_via_references] +} + +fn ret_i32() -> i32 { + 0 +} + +fn temporaries() { + let _ = &1 as *const i32; + let _ = &(1 + 2) as *const i32; + let _ = &ret_i32() as *const i32; + let _ = &(1, 2) as *const (i32, i32); + let _ = &[1, 2, 3] as *const [i32; 3]; + let _ = &A { a: 0, b: 0 } as *const A; + let _ = &mut 4 as *mut i32; +} + +fn inner_blocks() { + let x = 0; + let _ = { &x as *const i32 }; + //~^ WARN creating an intermediate reference implies aliasing requirements even when immediately cast to a raw pointers [raw_borrows_via_references] + + let _ = { + let y = 0; + { &y as *const i32 } + //~^ WARN creating an intermediate reference implies aliasing requirements even when immediately cast to a raw pointers [raw_borrows_via_references] + }; + + let _ = { &1 as *const i32 }; +} + +macro_rules! ref_cast { + ($e:expr) => { + &$e as *const i32 + //~^ WARN creating an intermediate reference implies aliasing requirements even when immediately cast to a raw pointers [raw_borrows_via_references] + }; +} + +fn from_macro(x: *const i32) -> *const i32 { + unsafe { ref_cast!(*x) } +} + +fn main() { + let a = 0; + let a = &a as *const i32; + //~^ WARN creating an intermediate reference implies aliasing requirements even when immediately cast to a raw pointers [raw_borrows_via_references] + + let mut b = 0; + let b = &mut b as *mut i32; + //~^ WARN creating an intermediate reference implies aliasing requirements even when immediately cast to a raw pointers [raw_borrows_via_references] + + let i = &1 as *const i32; +} diff --git a/tests/ui/lint/lint-raw-borrows-via-references.stderr b/tests/ui/lint/lint-raw-borrows-via-references.stderr new file mode 100644 index 0000000000000..f04922b52f05a --- /dev/null +++ b/tests/ui/lint/lint-raw-borrows-via-references.stderr @@ -0,0 +1,127 @@ +warning: creating an intermediate reference implies aliasing requirements even when immediately cast to a raw pointers + --> $DIR/lint-raw-borrows-via-references.rs:14:14 + | +LL | unsafe { &(*x).0 as *const i32 } + | ^^^^^^^^^^^^^^^^^^^^^ + | +note: the lint level is defined here + --> $DIR/lint-raw-borrows-via-references.rs:6:9 + | +LL | #![warn(raw_borrows_via_references)] + | ^^^^^^^^^^^^^^^^^^^^^^^^^^ +help: consider using `&raw const` for a safer and more explicit raw pointer + | +LL - unsafe { &(*x).0 as *const i32 } +LL + unsafe { &raw const (*x).0 } + | + +warning: creating an intermediate reference implies aliasing requirements even when immediately cast to a raw pointers + --> $DIR/lint-raw-borrows-via-references.rs:19:14 + | +LL | unsafe { &(*x).b as *const u8 } + | ^^^^^^^^^^^^^^^^^^^^ + | +help: consider using `&raw const` for a safer and more explicit raw pointer + | +LL - unsafe { &(*x).b as *const u8 } +LL + unsafe { &raw const (*x).b } + | + +warning: creating an intermediate reference implies aliasing requirements even when immediately cast to a raw pointers + --> $DIR/lint-raw-borrows-via-references.rs:24:14 + | +LL | unsafe { &mut (*x).0 as *mut i32 } + | ^^^^^^^^^^^^^^^^^^^^^^^ + | +help: consider using `&raw mut` for a safer and more explicit raw pointer + | +LL - unsafe { &mut (*x).0 as *mut i32 } +LL + unsafe { &raw mut (*x).0 } + | + +warning: creating an intermediate reference implies aliasing requirements even when immediately cast to a raw pointers + --> $DIR/lint-raw-borrows-via-references.rs:29:14 + | +LL | unsafe { &mut (*x).a as *mut i32 } + | ^^^^^^^^^^^^^^^^^^^^^^^ + | +help: consider using `&raw mut` for a safer and more explicit raw pointer + | +LL - unsafe { &mut (*x).a as *mut i32 } +LL + unsafe { &raw mut (*x).a } + | + +warning: creating an intermediate reference implies aliasing requirements even when immediately cast to a raw pointers + --> $DIR/lint-raw-borrows-via-references.rs:34:14 + | +LL | unsafe { &(*x).0 as *const i32 as *const u8 } + | ^^^^^^^^^^^^^^^^^^^^^ + | +help: consider using `&raw const` for a safer and more explicit raw pointer + | +LL - unsafe { &(*x).0 as *const i32 as *const u8 } +LL + unsafe { &raw const (*x).0 as *const u8 } + | + +warning: creating an intermediate reference implies aliasing requirements even when immediately cast to a raw pointers + --> $DIR/lint-raw-borrows-via-references.rs:54:15 + | +LL | let _ = { &x as *const i32 }; + | ^^^^^^^^^^^^^^^^ + | +help: consider using `&raw const` for a safer and more explicit raw pointer + | +LL - let _ = { &x as *const i32 }; +LL + let _ = { &raw const x }; + | + +warning: creating an intermediate reference implies aliasing requirements even when immediately cast to a raw pointers + --> $DIR/lint-raw-borrows-via-references.rs:59:11 + | +LL | { &y as *const i32 } + | ^^^^^^^^^^^^^^^^ + | +help: consider using `&raw const` for a safer and more explicit raw pointer + | +LL - { &y as *const i32 } +LL + { &raw const y } + | + +warning: creating an intermediate reference implies aliasing requirements even when immediately cast to a raw pointers + --> $DIR/lint-raw-borrows-via-references.rs:68:10 + | +LL | &$e as *const i32 + | ^^^^^^^^^^^^^^^^ +... +LL | unsafe { ref_cast!(*x) } + | ------------- in this macro invocation + | + = help: consider using `&raw const` for a safer and more explicit raw pointer + = note: this warning originates in the macro `ref_cast` (in Nightly builds, run with -Z macro-backtrace for more info) + +warning: creating an intermediate reference implies aliasing requirements even when immediately cast to a raw pointers + --> $DIR/lint-raw-borrows-via-references.rs:79:13 + | +LL | let a = &a as *const i32; + | ^^^^^^^^^^^^^^^^ + | +help: consider using `&raw const` for a safer and more explicit raw pointer + | +LL - let a = &a as *const i32; +LL + let a = &raw const a; + | + +warning: creating an intermediate reference implies aliasing requirements even when immediately cast to a raw pointers + --> $DIR/lint-raw-borrows-via-references.rs:83:13 + | +LL | let b = &mut b as *mut i32; + | ^^^^^^^^^^^^^^^^^^ + | +help: consider using `&raw mut` for a safer and more explicit raw pointer + | +LL - let b = &mut b as *mut i32; +LL + let b = &raw mut b; + | + +warning: 10 warnings emitted + From a67aa12d6e70d56e904a67f46531637f14250e42 Mon Sep 17 00:00:00 2001 From: Zalathar Date: Sun, 26 Jul 2026 17:58:42 +1000 Subject: [PATCH 03/12] Use an explicit list of types for `RefDecodable` into arena This is a little more verbose than using a `[decode]` modifier, but will allow us to stop using higher-order macros when declaring arenas. --- compiler/rustc_middle/src/arena.rs | 86 +++++++++++++++++++++++---- compiler/rustc_middle/src/ty/codec.rs | 49 --------------- 2 files changed, 76 insertions(+), 59 deletions(-) diff --git a/compiler/rustc_middle/src/arena.rs b/compiler/rustc_middle/src/arena.rs index 87e19fafc0e22..90ae9963b33a0 100644 --- a/compiler/rustc_middle/src/arena.rs +++ b/compiler/rustc_middle/src/arena.rs @@ -1,3 +1,8 @@ +use rustc_serialize::Decodable; + +use crate::ty::Ty; +use crate::ty::codec::{RefDecodable, TyDecoder}; + /// This higher-order macro declares a list of types which can be allocated by `Arena`. /// /// Specifying the `decode` modifier will add decode impls for `&T` and `&[T]` where `T` is the type @@ -12,7 +17,7 @@ macro_rules! arena_types { [] adt_def: rustc_middle::ty::AdtDefData, [] steal_thir: rustc_data_structures::steal::Steal>, [] steal_mir: rustc_data_structures::steal::Steal>, - [decode] mir: rustc_middle::mir::Body<'tcx>, + [] mir: rustc_middle::mir::Body<'tcx>, [] steal_promoted: rustc_data_structures::steal::Steal< rustc_index::IndexVec< @@ -20,12 +25,12 @@ macro_rules! arena_types { rustc_middle::mir::Body<'tcx> > >, - [decode] promoted: + [] promoted: rustc_index::IndexVec< rustc_middle::mir::Promoted, rustc_middle::mir::Body<'tcx> >, - [decode] typeck_results: rustc_middle::ty::TypeckResults<'tcx>, + [] typeck_results: rustc_middle::ty::TypeckResults<'tcx>, [] borrowck_result: rustc_data_structures::fx::FxIndexMap< rustc_hir::def_id::LocalDefId, rustc_middle::ty::DefinitionSiteHiddenType<'tcx>, @@ -92,7 +97,7 @@ macro_rules! arena_types { [] upvars_mentioned: rustc_data_structures::fx::FxIndexMap, [] dyn_compatibility_violations: rustc_middle::traits::DynCompatibilityViolation, [] codegen_unit: rustc_middle::mono::CodegenUnit<'tcx>, - [decode] attribute: rustc_hir::Attribute, + [] attribute: rustc_hir::Attribute, [] name_set: rustc_data_structures::unord::UnordSet, [] autodiff_item: rustc_hir::attrs::AutoDiffItem, [] ordered_name_set: rustc_data_structures::fx::FxIndexSet, @@ -102,14 +107,14 @@ macro_rules! arena_types { // Note that this deliberately duplicates items in the `rustc_hir::arena`, // since we need to allocate this type on both the `rustc_hir` arena // (during lowering) and the `rustc_middle` arena (for decoding MIR) - [decode] asm_template: rustc_ast::InlineAsmTemplatePiece, - [decode] used_trait_imports: rustc_data_structures::unord::UnordSet, + [] asm_template: rustc_ast::InlineAsmTemplatePiece, + [] used_trait_imports: rustc_data_structures::unord::UnordSet, [] is_late_bound_map: rustc_data_structures::fx::FxIndexSet, - [decode] impl_source: rustc_middle::traits::ImplSource<'tcx, ()>, + [] impl_source: rustc_middle::traits::ImplSource<'tcx, ()>, [] dep_kind_vtable: rustc_middle::dep_graph::DepKindVTable<'tcx>, - [decode] trait_impl_trait_tys: + [] trait_impl_trait_tys: rustc_data_structures::unord::UnordMap< rustc_hir::def_id::DefId, rustc_middle::ty::EarlyBinder<'tcx, rustc_middle::ty::Ty<'tcx>> @@ -119,10 +124,10 @@ macro_rules! arena_types { [] stripped_cfg_items: rustc_hir::attrs::StrippedCfgItem, [] mod_child: rustc_middle::metadata::ModChild, [] features: rustc_feature::Features, - [decode] specialization_graph: rustc_middle::traits::specialization_graph::Graph, + [] specialization_graph: rustc_middle::traits::specialization_graph::Graph, [] crate_inherent_impls: rustc_middle::ty::CrateInherentImpls, [] hir_owner_nodes: rustc_hir::OwnerNodes<'tcx>, - [decode] token_stream: rustc_ast::tokenstream::TokenStream, + [] token_stream: rustc_ast::tokenstream::TokenStream, [] maybe_owner: rustc_middle::hir::ProjectedMaybeOwner<'tcx>, [] owner_info: rustc_middle::hir::ProjectedOwnerInfo<'tcx>, [] parenting: rustc_hir::def_id::LocalDefIdMap, @@ -133,3 +138,64 @@ macro_rules! arena_types { } arena_types!(rustc_arena::declare_arena); + +#[inline] +fn decode_arena_allocatable<'tcx, D, T>(decoder: &mut D) -> &'tcx T +where + D: TyDecoder<'tcx>, + T: ArenaAllocatable<'tcx> + Decodable, +{ + let value: T = Decodable::decode(decoder); + decoder.interner().arena.alloc(value) +} + +#[inline] +fn decode_arena_allocatable_slice<'tcx, D, T>(decoder: &mut D) -> &'tcx [T] +where + D: TyDecoder<'tcx>, + T: ArenaAllocatable<'tcx> + Decodable, +{ + let values: Vec = Decodable::decode(decoder); + decoder.interner().arena.alloc_from_iter(values) +} + +/// Implements [`RefDecodable`] for `T` (and `[T]`), by decoding to `T` and +/// then moving the value or values into an arena allocation. +macro_rules! impl_ref_decodable_into_arena { + ( + $( + $ty:ty, + )* + ) => { + $( + impl<'tcx, D: TyDecoder<'tcx>> RefDecodable<'tcx, D> for $ty { + #[inline] + fn decode(decoder: &mut D) -> &'tcx Self { + decode_arena_allocatable(decoder) + } + } + + impl<'tcx, D: TyDecoder<'tcx>> RefDecodable<'tcx, D> for [$ty] { + #[inline] + fn decode(decoder: &mut D) -> &'tcx Self { + decode_arena_allocatable_slice(decoder) + } + } + )* + } +} + +impl_ref_decodable_into_arena! { + // tidy-alphabetical-start + rustc_ast::InlineAsmTemplatePiece, + rustc_ast::tokenstream::TokenStream, + rustc_data_structures::unord::UnordMap>>, + rustc_data_structures::unord::UnordSet, + rustc_hir::Attribute, + rustc_index::IndexVec>, + rustc_middle::mir::Body<'tcx>, + rustc_middle::traits::ImplSource<'tcx, ()>, + rustc_middle::traits::specialization_graph::Graph, + rustc_middle::ty::TypeckResults<'tcx>, + // tidy-alphabetical-end +} diff --git a/compiler/rustc_middle/src/ty/codec.rs b/compiler/rustc_middle/src/ty/codec.rs index 5f76467ed7db2..a58d972f0e528 100644 --- a/compiler/rustc_middle/src/ty/codec.rs +++ b/compiler/rustc_middle/src/ty/codec.rs @@ -17,7 +17,6 @@ use rustc_middle::ty::Const; use rustc_serialize::{Decodable, Encodable}; use rustc_span::{Span, SpanDecoder, SpanEncoder, Spanned}; -use crate::arena::ArenaAllocatable; use crate::infer::canonical::{CanonicalVarKind, CanonicalVarKinds}; use crate::mir::interpret::{AllocId, ConstAllocation, CtfeProvenance}; use crate::mono::MonoItem; @@ -206,24 +205,6 @@ impl<'tcx, E: TyEncoder<'tcx>> Encodable for ty::ParamEnv<'tcx> { } } -#[inline] -fn decode_arena_allocable<'tcx, D: TyDecoder<'tcx>, T: ArenaAllocatable<'tcx> + Decodable>( - decoder: &mut D, -) -> &'tcx T { - decoder.interner().arena.alloc(Decodable::decode(decoder)) -} - -#[inline] -fn decode_arena_allocable_slice< - 'tcx, - D: TyDecoder<'tcx>, - T: ArenaAllocatable<'tcx> + Decodable, ->( - decoder: &mut D, -) -> &'tcx [T] { - decoder.interner().arena.alloc_from_iter( as Decodable>::decode(decoder)) -} - impl<'tcx, D: TyDecoder<'tcx>> Decodable for Ty<'tcx> { #[allow(rustc::usage_of_ty_tykind)] fn decode(decoder: &mut D) -> Ty<'tcx> { @@ -500,36 +481,6 @@ macro_rules! __impl_decoder_methods { } } -macro_rules! impl_arena_allocatable_decoder { - ([] $name:ident: $ty:ty) => {}; - ([decode] $name:ident: $ty:ty) => { - impl<'tcx, D: TyDecoder<'tcx>> RefDecodable<'tcx, D> for $ty { - #[inline] - fn decode(decoder: &mut D) -> &'tcx Self { - decode_arena_allocable(decoder) - } - } - - impl<'tcx, D: TyDecoder<'tcx>> RefDecodable<'tcx, D> for [$ty] { - #[inline] - fn decode(decoder: &mut D) -> &'tcx Self { - decode_arena_allocable_slice(decoder) - } - } - }; -} - -macro_rules! impl_arena_allocatable_decoders { - ([$($a:tt $name:ident: $ty:ty,)*]) => { - $( - impl_arena_allocatable_decoder!($a $name: $ty); - )* - } -} - -rustc_hir::arena_types!(impl_arena_allocatable_decoders); -arena_types!(impl_arena_allocatable_decoders); - macro_rules! impl_arena_copy_decoder { (<$tcx:tt> $($ty:ty,)*) => { $(impl<'tcx, D: TyDecoder<'tcx>> RefDecodable<'tcx, D> for $ty { From 08cb62dd570fcf44f85de43be917b8ac8db6c196 Mon Sep 17 00:00:00 2001 From: Zalathar Date: Sun, 26 Jul 2026 18:03:49 +1000 Subject: [PATCH 04/12] Use the same list for `RefDecodable` of Copy types --- compiler/rustc_middle/src/arena.rs | 15 ++++++++++---- compiler/rustc_middle/src/ty/codec.rs | 28 --------------------------- 2 files changed, 11 insertions(+), 32 deletions(-) diff --git a/compiler/rustc_middle/src/arena.rs b/compiler/rustc_middle/src/arena.rs index 90ae9963b33a0..035aa3d5deed9 100644 --- a/compiler/rustc_middle/src/arena.rs +++ b/compiler/rustc_middle/src/arena.rs @@ -140,20 +140,20 @@ macro_rules! arena_types { arena_types!(rustc_arena::declare_arena); #[inline] -fn decode_arena_allocatable<'tcx, D, T>(decoder: &mut D) -> &'tcx T +fn decode_arena_allocatable<'tcx, D, C, T>(decoder: &mut D) -> &'tcx T where D: TyDecoder<'tcx>, - T: ArenaAllocatable<'tcx> + Decodable, + T: ArenaAllocatable<'tcx, C> + Decodable, { let value: T = Decodable::decode(decoder); decoder.interner().arena.alloc(value) } #[inline] -fn decode_arena_allocatable_slice<'tcx, D, T>(decoder: &mut D) -> &'tcx [T] +fn decode_arena_allocatable_slice<'tcx, D, C, T>(decoder: &mut D) -> &'tcx [T] where D: TyDecoder<'tcx>, - T: ArenaAllocatable<'tcx> + Decodable, + T: ArenaAllocatable<'tcx, C> + Decodable, { let values: Vec = Decodable::decode(decoder); decoder.interner().arena.alloc_from_iter(values) @@ -187,15 +187,22 @@ macro_rules! impl_ref_decodable_into_arena { impl_ref_decodable_into_arena! { // tidy-alphabetical-start + (rustc_middle::middle::exported_symbols::ExportedSymbol<'tcx>, rustc_middle::middle::exported_symbols::SymbolExportInfo), rustc_ast::InlineAsmTemplatePiece, rustc_ast::tokenstream::TokenStream, rustc_data_structures::unord::UnordMap>>, rustc_data_structures::unord::UnordSet, rustc_hir::Attribute, rustc_index::IndexVec>, + rustc_middle::middle::deduced_param_attrs::DeducedParamAttrs, rustc_middle::mir::Body<'tcx>, rustc_middle::traits::ImplSource<'tcx, ()>, rustc_middle::traits::specialization_graph::Graph, rustc_middle::ty::TypeckResults<'tcx>, + rustc_middle::ty::Variance, + rustc_span::Ident, + rustc_span::Span, + rustc_span::def_id::DefId, + rustc_span::def_id::LocalDefId, // tidy-alphabetical-end } diff --git a/compiler/rustc_middle/src/ty/codec.rs b/compiler/rustc_middle/src/ty/codec.rs index a58d972f0e528..0b2a1c55cfcf5 100644 --- a/compiler/rustc_middle/src/ty/codec.rs +++ b/compiler/rustc_middle/src/ty/codec.rs @@ -481,34 +481,6 @@ macro_rules! __impl_decoder_methods { } } -macro_rules! impl_arena_copy_decoder { - (<$tcx:tt> $($ty:ty,)*) => { - $(impl<'tcx, D: TyDecoder<'tcx>> RefDecodable<'tcx, D> for $ty { - #[inline] - fn decode(decoder: &mut D) -> &'tcx Self { - decoder.interner().arena.alloc(Decodable::decode(decoder)) - } - } - - impl<'tcx, D: TyDecoder<'tcx>> RefDecodable<'tcx, D> for [$ty] { - #[inline] - fn decode(decoder: &mut D) -> &'tcx Self { - decoder.interner().arena.alloc_from_iter( as Decodable>::decode(decoder)) - } - })* - }; -} - -impl_arena_copy_decoder! {<'tcx> - Span, - rustc_span::Ident, - ty::Variance, - rustc_span::def_id::DefId, - rustc_span::def_id::LocalDefId, - (rustc_middle::middle::exported_symbols::ExportedSymbol<'tcx>, rustc_middle::middle::exported_symbols::SymbolExportInfo), - rustc_middle::middle::deduced_param_attrs::DeducedParamAttrs, -} - #[macro_export] macro_rules! implement_ty_decoder { ($DecoderName:ident <$($typaram:tt),*>) => { From b0b25c9775b9183d82a4d66fff8be6949a008937 Mon Sep 17 00:00:00 2001 From: Zalathar Date: Sun, 26 Jul 2026 18:08:07 +1000 Subject: [PATCH 05/12] Stop using higher-order macros to declare arenas --- compiler/rustc_arena/src/lib.rs | 35 ++-- compiler/rustc_hir/src/arena.rs | 24 +-- compiler/rustc_hir/src/lib.rs | 2 +- compiler/rustc_middle/src/arena.rs | 269 +++++++++++++------------- compiler/rustc_middle/src/ty/codec.rs | 3 + 5 files changed, 172 insertions(+), 161 deletions(-) diff --git a/compiler/rustc_arena/src/lib.rs b/compiler/rustc_arena/src/lib.rs index a4248a82bce73..d75f23eedd26c 100644 --- a/compiler/rustc_arena/src/lib.rs +++ b/compiler/rustc_arena/src/lib.rs @@ -598,21 +598,32 @@ impl DroplessArena { } } -/// Declare an `Arena` containing one dropless arena and many typed arenas (the -/// types of the typed arenas are specified by the arguments). +/// Declares an `Arena` that can allocate values of a variety of `Copy`, `needs_drop` and +/// `!needs_drop` types. /// -/// There are three cases of interest. -/// - Types that are `Copy`: these need not be specified in the arguments. They -/// will use the `DroplessArena`. -/// - Types that are `!Copy` and `!Drop`: these must be specified in the -/// arguments. An empty `TypedArena` will be created for each one, but the -/// `DroplessArena` will always be used and the `TypedArena` will stay empty. -/// This is odd but harmless, because an empty arena allocates no memory. -/// - Types that are `!Copy` and `Drop`: these must be specified in the -/// arguments. The `TypedArena` will be used for them. +/// The declared arena actually contains a single [`DroplessArena`], plus a separate +/// [`TypedArena`] for each of the types listed in the body of the macro invocation. /// +/// Any type that is `Copy` can be allocated in the arena without needing to be listed +/// explicitly. Those values will be stored in the [`DroplessArena`]. +/// +/// Types that are `!Copy` can only be allocated if they are listed in the macro invocation. +/// For types that are `!Copy + needs_drop`, values will be stored in the corresponding +/// [`TypedArena`] and will be dropped when the arena is dropped. +/// +/// As an optimization, types that are `!Copy + !needs_drop` will actually be stored in the +/// [`DroplessArena`], and the corresponding [`TypedArena`] will remain empty. This makes +/// better use of the dropless arena's storage blocks, while the overhead of having a few +/// unused typed-arenas is negligible. #[rustc_macro_transparency = "semiopaque"] -pub macro declare_arena([$($a:tt $name:ident: $ty:ty,)*]) { +pub macro declare_arena( + // Each of these entries becomes a `$name: TypedArena<$ty>` field in the arena. + // This allows values of non-copy type $ty to be allocated in the arena. + // The field names must be distinct, but have no further significance. + $( + [] $name:ident: $ty:ty, + )* +) { #[derive(Default)] pub struct Arena<'tcx> { pub dropless: $crate::DroplessArena, diff --git a/compiler/rustc_hir/src/arena.rs b/compiler/rustc_hir/src/arena.rs index b4b9db5d93f48..8ccd2c9320216 100644 --- a/compiler/rustc_hir/src/arena.rs +++ b/compiler/rustc_hir/src/arena.rs @@ -1,15 +1,11 @@ -/// This higher-order macro declares a list of types which can be allocated by `Arena`. -/// Note that all `Copy` types can be allocated by default and need not be specified here. -#[macro_export] -macro_rules! arena_types { - ($macro:path) => ( - $macro!([ - // HIR types - [] asm_template: rustc_ast::InlineAsmTemplatePiece, - [] attribute: crate::Attribute, - [] owner_info: crate::OwnerInfo<'tcx>, - [] macro_def: rustc_ast::MacroDef, - [] delegation_info: crate::DelegationInfo, - ]); - ) +//! Declares an arena that can allocate values of any `Copy` type, and of +//! any `!Copy` type listed below. + +rustc_arena::declare_arena! { + // HIR types + [] asm_template: rustc_ast::InlineAsmTemplatePiece, + [] attribute: crate::Attribute, + [] owner_info: crate::OwnerInfo<'tcx>, + [] macro_def: rustc_ast::MacroDef, + [] delegation_info: crate::DelegationInfo, } diff --git a/compiler/rustc_hir/src/lib.rs b/compiler/rustc_hir/src/lib.rs index 37aa024be6278..761fc680d2ff6 100644 --- a/compiler/rustc_hir/src/lib.rs +++ b/compiler/rustc_hir/src/lib.rs @@ -42,4 +42,4 @@ pub use rustc_span::def_id; pub use stability::*; pub use target::{MethodKind, Target}; -arena_types!(rustc_arena::declare_arena); +pub use crate::arena::Arena; diff --git a/compiler/rustc_middle/src/arena.rs b/compiler/rustc_middle/src/arena.rs index 035aa3d5deed9..5449bfe214b0b 100644 --- a/compiler/rustc_middle/src/arena.rs +++ b/compiler/rustc_middle/src/arena.rs @@ -1,143 +1,141 @@ +//! Declares [`rustc_middle::arena::Arena`], which can allocate values of any +//! `Copy` type, and any `!Copy` type explicitly listed below. + use rustc_serialize::Decodable; -use crate::ty::Ty; use crate::ty::codec::{RefDecodable, TyDecoder}; +use crate::ty::{Ty, TyCtxt}; -/// This higher-order macro declares a list of types which can be allocated by `Arena`. -/// -/// Specifying the `decode` modifier will add decode impls for `&T` and `&[T]` where `T` is the type -/// listed. See the `impl_arena_allocatable_decoder!` macro for more. -#[macro_export] -macro_rules! arena_types { - ($macro:path) => ( - $macro!([ - [] layout: rustc_abi::LayoutData, - [] proxy_coroutine_layout: rustc_middle::mir::CoroutineLayout<'tcx>, - [] fn_abi: rustc_target::callconv::FnAbi<'tcx, rustc_middle::ty::Ty<'tcx>>, - [] adt_def: rustc_middle::ty::AdtDefData, - [] steal_thir: rustc_data_structures::steal::Steal>, - [] steal_mir: rustc_data_structures::steal::Steal>, - [] mir: rustc_middle::mir::Body<'tcx>, - [] steal_promoted: - rustc_data_structures::steal::Steal< - rustc_index::IndexVec< - rustc_middle::mir::Promoted, - rustc_middle::mir::Body<'tcx> - > - >, - [] promoted: - rustc_index::IndexVec< - rustc_middle::mir::Promoted, - rustc_middle::mir::Body<'tcx> - >, - [] typeck_results: rustc_middle::ty::TypeckResults<'tcx>, - [] borrowck_result: rustc_data_structures::fx::FxIndexMap< - rustc_hir::def_id::LocalDefId, - rustc_middle::ty::DefinitionSiteHiddenType<'tcx>, - >, - [] resolver: rustc_data_structures::steal::Steal>, - [] index_ast: rustc_index::IndexVec< - rustc_span::def_id::LocalDefId, - rustc_data_structures::steal::Steal<( - std::sync::Arc>, - rustc_ast::AstOwner - )> - >, - [] crate_alone: rustc_data_structures::steal::Steal, - [] crate_for_resolver: rustc_data_structures::steal::Steal<(rustc_ast::Crate, rustc_ast::AttrVec)>, - [] resolutions: rustc_middle::ty::ResolverGlobalCtxt, - [] const_allocs: rustc_middle::mir::interpret::Allocation, - [] region_scope_tree: rustc_middle::middle::region::ScopeTree, - // Required for the incremental on-disk cache - [] mir_keys: rustc_hir::def_id::DefIdSet, - [] dropck_outlives: - rustc_middle::infer::canonical::Canonical<'tcx, - rustc_middle::infer::canonical::QueryResponse<'tcx, - rustc_middle::traits::query::DropckOutlivesResult<'tcx> - > - >, - [] normalize_canonicalized_projection: - rustc_middle::infer::canonical::Canonical<'tcx, - rustc_middle::infer::canonical::QueryResponse<'tcx, - rustc_middle::traits::query::NormalizationResult<'tcx> - > - >, - [] implied_outlives_bounds: - rustc_middle::infer::canonical::Canonical<'tcx, - rustc_middle::infer::canonical::QueryResponse<'tcx, - Vec> - > - >, - [] dtorck_constraint: rustc_middle::traits::query::DropckConstraint<'tcx>, - [] candidate_step: rustc_middle::traits::query::CandidateStep<'tcx>, - [] autoderef_bad_ty: rustc_middle::traits::query::MethodAutoderefBadTy<'tcx>, - [] query_region_constraints: rustc_middle::infer::canonical::QueryRegionConstraints<'tcx>, - [] type_op_subtype: - rustc_middle::infer::canonical::Canonical<'tcx, - rustc_middle::infer::canonical::QueryResponse<'tcx, ()> - >, - [] type_op_normalize_poly_fn_sig: - rustc_middle::infer::canonical::Canonical<'tcx, - rustc_middle::infer::canonical::QueryResponse<'tcx, rustc_middle::ty::PolyFnSig<'tcx>> - >, - [] type_op_normalize_fn_sig: - rustc_middle::infer::canonical::Canonical<'tcx, - rustc_middle::infer::canonical::QueryResponse<'tcx, rustc_middle::ty::FnSig<'tcx>> - >, - [] type_op_normalize_clause: - rustc_middle::infer::canonical::Canonical<'tcx, - rustc_middle::infer::canonical::QueryResponse<'tcx, rustc_middle::ty::Clause<'tcx>> - >, - [] type_op_normalize_ty: - rustc_middle::infer::canonical::Canonical<'tcx, - rustc_middle::infer::canonical::QueryResponse<'tcx, rustc_middle::ty::Ty<'tcx>> - >, - [] inspect_probe: rustc_middle::traits::solve::inspect::Probe>, - [] effective_visibilities: rustc_middle::middle::privacy::EffectiveVisibilities, - [] upvars_mentioned: rustc_data_structures::fx::FxIndexMap, - [] dyn_compatibility_violations: rustc_middle::traits::DynCompatibilityViolation, - [] codegen_unit: rustc_middle::mono::CodegenUnit<'tcx>, - [] attribute: rustc_hir::Attribute, - [] name_set: rustc_data_structures::unord::UnordSet, - [] autodiff_item: rustc_hir::attrs::AutoDiffItem, - [] ordered_name_set: rustc_data_structures::fx::FxIndexSet, - [] stable_order_of_exportable_impls: - rustc_data_structures::fx::FxIndexMap, +// If a type `T` supported by the arena also needs to support decoding into `&'tcx T` +// backed by an arena allocation (via `RefDecodable`), add it to the list in +// `impl_ref_decodable_into_arena!`. - // Note that this deliberately duplicates items in the `rustc_hir::arena`, - // since we need to allocate this type on both the `rustc_hir` arena - // (during lowering) and the `rustc_middle` arena (for decoding MIR) - [] asm_template: rustc_ast::InlineAsmTemplatePiece, - [] used_trait_imports: rustc_data_structures::unord::UnordSet, - [] is_late_bound_map: rustc_data_structures::fx::FxIndexSet, - [] impl_source: rustc_middle::traits::ImplSource<'tcx, ()>, +rustc_arena::declare_arena! { + [] layout: rustc_abi::LayoutData, + [] proxy_coroutine_layout: rustc_middle::mir::CoroutineLayout<'tcx>, + [] fn_abi: rustc_target::callconv::FnAbi<'tcx, Ty<'tcx>>, + [] adt_def: rustc_middle::ty::AdtDefData, + [] steal_thir: rustc_data_structures::steal::Steal>, + [] steal_mir: rustc_data_structures::steal::Steal>, + [] mir: rustc_middle::mir::Body<'tcx>, + [] steal_promoted: + rustc_data_structures::steal::Steal< + rustc_index::IndexVec< + rustc_middle::mir::Promoted, + rustc_middle::mir::Body<'tcx> + > + >, + [] promoted: + rustc_index::IndexVec< + rustc_middle::mir::Promoted, + rustc_middle::mir::Body<'tcx> + >, + [] typeck_results: rustc_middle::ty::TypeckResults<'tcx>, + [] borrowck_result: + rustc_data_structures::fx::FxIndexMap< + rustc_hir::def_id::LocalDefId, + rustc_middle::ty::DefinitionSiteHiddenType<'tcx>, + >, + [] resolver: rustc_data_structures::steal::Steal>, + [] index_ast: + rustc_index::IndexVec< + rustc_span::def_id::LocalDefId, + rustc_data_structures::steal::Steal<( + std::sync::Arc>, + rustc_ast::AstOwner + )> + >, + [] crate_alone: rustc_data_structures::steal::Steal, + [] crate_for_resolver: rustc_data_structures::steal::Steal<(rustc_ast::Crate, rustc_ast::AttrVec)>, + [] resolutions: rustc_middle::ty::ResolverGlobalCtxt, + [] const_allocs: rustc_middle::mir::interpret::Allocation, + [] region_scope_tree: rustc_middle::middle::region::ScopeTree, + // Required for the incremental on-disk cache + [] mir_keys: rustc_hir::def_id::DefIdSet, + [] dropck_outlives: + rustc_middle::infer::canonical::Canonical<'tcx, + rustc_middle::infer::canonical::QueryResponse<'tcx, + rustc_middle::traits::query::DropckOutlivesResult<'tcx> + > + >, + [] normalize_canonicalized_projection: + rustc_middle::infer::canonical::Canonical<'tcx, + rustc_middle::infer::canonical::QueryResponse<'tcx, + rustc_middle::traits::query::NormalizationResult<'tcx> + > + >, + [] implied_outlives_bounds: + rustc_middle::infer::canonical::Canonical<'tcx, + rustc_middle::infer::canonical::QueryResponse<'tcx, + Vec> + > + >, + [] dtorck_constraint: rustc_middle::traits::query::DropckConstraint<'tcx>, + [] candidate_step: rustc_middle::traits::query::CandidateStep<'tcx>, + [] autoderef_bad_ty: rustc_middle::traits::query::MethodAutoderefBadTy<'tcx>, + [] query_region_constraints: rustc_middle::infer::canonical::QueryRegionConstraints<'tcx>, + [] type_op_subtype: + rustc_middle::infer::canonical::Canonical<'tcx, + rustc_middle::infer::canonical::QueryResponse<'tcx, ()> + >, + [] type_op_normalize_poly_fn_sig: + rustc_middle::infer::canonical::Canonical<'tcx, + rustc_middle::infer::canonical::QueryResponse<'tcx, rustc_middle::ty::PolyFnSig<'tcx>> + >, + [] type_op_normalize_fn_sig: + rustc_middle::infer::canonical::Canonical<'tcx, + rustc_middle::infer::canonical::QueryResponse<'tcx, rustc_middle::ty::FnSig<'tcx>> + >, + [] type_op_normalize_clause: + rustc_middle::infer::canonical::Canonical<'tcx, + rustc_middle::infer::canonical::QueryResponse<'tcx, rustc_middle::ty::Clause<'tcx>> + >, + [] type_op_normalize_ty: + rustc_middle::infer::canonical::Canonical<'tcx, + rustc_middle::infer::canonical::QueryResponse<'tcx, Ty<'tcx>> + >, + [] inspect_probe: rustc_middle::traits::solve::inspect::Probe>, + [] effective_visibilities: rustc_middle::middle::privacy::EffectiveVisibilities, + [] upvars_mentioned: rustc_data_structures::fx::FxIndexMap, + [] dyn_compatibility_violations: rustc_middle::traits::DynCompatibilityViolation, + [] codegen_unit: rustc_middle::mono::CodegenUnit<'tcx>, + [] attribute: rustc_hir::Attribute, + [] name_set: rustc_data_structures::unord::UnordSet, + [] autodiff_item: rustc_hir::attrs::AutoDiffItem, + [] ordered_name_set: rustc_data_structures::fx::FxIndexSet, + [] stable_order_of_exportable_impls: + rustc_data_structures::fx::FxIndexMap, - [] dep_kind_vtable: rustc_middle::dep_graph::DepKindVTable<'tcx>, + // Note that this deliberately duplicates items in the `rustc_hir::arena`, + // since we need to allocate this type on both the `rustc_hir` arena + // (during lowering) and the `rustc_middle` arena (for decoding MIR) + [] asm_template: rustc_ast::InlineAsmTemplatePiece, + [] used_trait_imports: rustc_data_structures::unord::UnordSet, + [] is_late_bound_map: rustc_data_structures::fx::FxIndexSet, + [] impl_source: rustc_middle::traits::ImplSource<'tcx, ()>, - [] trait_impl_trait_tys: - rustc_data_structures::unord::UnordMap< - rustc_hir::def_id::DefId, - rustc_middle::ty::EarlyBinder<'tcx, rustc_middle::ty::Ty<'tcx>> - >, - [] external_constraints: rustc_middle::traits::solve::ExternalConstraintsData>, - [] doc_link_resolutions: rustc_hir::def::DocLinkResMap, - [] stripped_cfg_items: rustc_hir::attrs::StrippedCfgItem, - [] mod_child: rustc_middle::metadata::ModChild, - [] features: rustc_feature::Features, - [] specialization_graph: rustc_middle::traits::specialization_graph::Graph, - [] crate_inherent_impls: rustc_middle::ty::CrateInherentImpls, - [] hir_owner_nodes: rustc_hir::OwnerNodes<'tcx>, - [] token_stream: rustc_ast::tokenstream::TokenStream, - [] maybe_owner: rustc_middle::hir::ProjectedMaybeOwner<'tcx>, - [] owner_info: rustc_middle::hir::ProjectedOwnerInfo<'tcx>, - [] parenting: rustc_hir::def_id::LocalDefIdMap, - [] trait_candidates: rustc_hir::ItemLocalMap<&'tcx [rustc_hir::TraitCandidate<'tcx>]>, - [] delayed_lints: rustc_data_structures::steal::Steal, - ]); - ) -} + [] dep_kind_vtable: rustc_middle::dep_graph::DepKindVTable<'tcx>, -arena_types!(rustc_arena::declare_arena); + [] trait_impl_trait_tys: + rustc_data_structures::unord::UnordMap< + rustc_hir::def_id::DefId, + rustc_middle::ty::EarlyBinder<'tcx, Ty<'tcx>> + >, + [] external_constraints: rustc_middle::traits::solve::ExternalConstraintsData>, + [] doc_link_resolutions: rustc_hir::def::DocLinkResMap, + [] stripped_cfg_items: rustc_hir::attrs::StrippedCfgItem, + [] mod_child: rustc_middle::metadata::ModChild, + [] features: rustc_feature::Features, + [] specialization_graph: rustc_middle::traits::specialization_graph::Graph, + [] crate_inherent_impls: rustc_middle::ty::CrateInherentImpls, + [] hir_owner_nodes: rustc_hir::OwnerNodes<'tcx>, + [] token_stream: rustc_ast::tokenstream::TokenStream, + [] maybe_owner: rustc_middle::hir::ProjectedMaybeOwner<'tcx>, + [] owner_info: rustc_middle::hir::ProjectedOwnerInfo<'tcx>, + [] parenting: rustc_hir::def_id::LocalDefIdMap, + [] trait_candidates: rustc_hir::ItemLocalMap<&'tcx [rustc_hir::TraitCandidate<'tcx>]>, + [] delayed_lints: rustc_data_structures::steal::Steal, +} #[inline] fn decode_arena_allocatable<'tcx, D, C, T>(decoder: &mut D) -> &'tcx T @@ -159,8 +157,6 @@ where decoder.interner().arena.alloc_from_iter(values) } -/// Implements [`RefDecodable`] for `T` (and `[T]`), by decoding to `T` and -/// then moving the value or values into an arena allocation. macro_rules! impl_ref_decodable_into_arena { ( $( @@ -185,6 +181,11 @@ macro_rules! impl_ref_decodable_into_arena { } } +// For each of these types, implements `RefDecodable` for `T` (and `[T]`) by +// decoding to `T` and then moving the value or values into an arena allocation. +// +// Types in this list must be `ArenaAllocatable`, either because they are `Copy` +// or because they are listed in the `declare_arena!` invocation. impl_ref_decodable_into_arena! { // tidy-alphabetical-start (rustc_middle::middle::exported_symbols::ExportedSymbol<'tcx>, rustc_middle::middle::exported_symbols::SymbolExportInfo), diff --git a/compiler/rustc_middle/src/ty/codec.rs b/compiler/rustc_middle/src/ty/codec.rs index 0b2a1c55cfcf5..33047bf3e67b4 100644 --- a/compiler/rustc_middle/src/ty/codec.rs +++ b/compiler/rustc_middle/src/ty/codec.rs @@ -94,6 +94,9 @@ impl<'tcx, E: TyEncoder<'tcx>> EncodableWithShorthand<'tcx, E> for ty::Predicate /// /// `Decodable` can still be implemented in cases where `Decodable` is required /// by a trait bound. +/// +/// Implementations of this trait will typically allocate into an arena or interner, +/// e.g. see `impl_ref_decodable_into_arena!`. pub trait RefDecodable<'tcx, D: TyDecoder<'tcx>>: PointeeSized { fn decode(d: &mut D) -> &'tcx Self; } From 01cef43abdc6876586fb903d1dcee27f32edade8 Mon Sep 17 00:00:00 2001 From: Zalathar Date: Wed, 29 Jul 2026 17:39:27 +1000 Subject: [PATCH 06/12] Remove the `[]` prefix from `declare_arena!` entries --- compiler/rustc_arena/src/lib.rs | 2 +- compiler/rustc_hir/src/arena.rs | 10 +-- compiler/rustc_middle/src/arena.rs | 122 ++++++++++++++--------------- 3 files changed, 67 insertions(+), 67 deletions(-) diff --git a/compiler/rustc_arena/src/lib.rs b/compiler/rustc_arena/src/lib.rs index d75f23eedd26c..3e9012f2d3871 100644 --- a/compiler/rustc_arena/src/lib.rs +++ b/compiler/rustc_arena/src/lib.rs @@ -621,7 +621,7 @@ pub macro declare_arena( // This allows values of non-copy type $ty to be allocated in the arena. // The field names must be distinct, but have no further significance. $( - [] $name:ident: $ty:ty, + $name:ident: $ty:ty, )* ) { #[derive(Default)] diff --git a/compiler/rustc_hir/src/arena.rs b/compiler/rustc_hir/src/arena.rs index 8ccd2c9320216..6b99f21353e22 100644 --- a/compiler/rustc_hir/src/arena.rs +++ b/compiler/rustc_hir/src/arena.rs @@ -3,9 +3,9 @@ rustc_arena::declare_arena! { // HIR types - [] asm_template: rustc_ast::InlineAsmTemplatePiece, - [] attribute: crate::Attribute, - [] owner_info: crate::OwnerInfo<'tcx>, - [] macro_def: rustc_ast::MacroDef, - [] delegation_info: crate::DelegationInfo, + asm_template: rustc_ast::InlineAsmTemplatePiece, + attribute: crate::Attribute, + owner_info: crate::OwnerInfo<'tcx>, + macro_def: rustc_ast::MacroDef, + delegation_info: crate::DelegationInfo, } diff --git a/compiler/rustc_middle/src/arena.rs b/compiler/rustc_middle/src/arena.rs index 5449bfe214b0b..ef943d70c3ecf 100644 --- a/compiler/rustc_middle/src/arena.rs +++ b/compiler/rustc_middle/src/arena.rs @@ -11,33 +11,33 @@ use crate::ty::{Ty, TyCtxt}; // `impl_ref_decodable_into_arena!`. rustc_arena::declare_arena! { - [] layout: rustc_abi::LayoutData, - [] proxy_coroutine_layout: rustc_middle::mir::CoroutineLayout<'tcx>, - [] fn_abi: rustc_target::callconv::FnAbi<'tcx, Ty<'tcx>>, - [] adt_def: rustc_middle::ty::AdtDefData, - [] steal_thir: rustc_data_structures::steal::Steal>, - [] steal_mir: rustc_data_structures::steal::Steal>, - [] mir: rustc_middle::mir::Body<'tcx>, - [] steal_promoted: + layout: rustc_abi::LayoutData, + proxy_coroutine_layout: rustc_middle::mir::CoroutineLayout<'tcx>, + fn_abi: rustc_target::callconv::FnAbi<'tcx, Ty<'tcx>>, + adt_def: rustc_middle::ty::AdtDefData, + steal_thir: rustc_data_structures::steal::Steal>, + steal_mir: rustc_data_structures::steal::Steal>, + mir: rustc_middle::mir::Body<'tcx>, + steal_promoted: rustc_data_structures::steal::Steal< rustc_index::IndexVec< rustc_middle::mir::Promoted, rustc_middle::mir::Body<'tcx> > >, - [] promoted: + promoted: rustc_index::IndexVec< rustc_middle::mir::Promoted, rustc_middle::mir::Body<'tcx> >, - [] typeck_results: rustc_middle::ty::TypeckResults<'tcx>, - [] borrowck_result: + typeck_results: rustc_middle::ty::TypeckResults<'tcx>, + borrowck_result: rustc_data_structures::fx::FxIndexMap< rustc_hir::def_id::LocalDefId, rustc_middle::ty::DefinitionSiteHiddenType<'tcx>, >, - [] resolver: rustc_data_structures::steal::Steal>, - [] index_ast: + resolver: rustc_data_structures::steal::Steal>, + index_ast: rustc_index::IndexVec< rustc_span::def_id::LocalDefId, rustc_data_structures::steal::Steal<( @@ -45,96 +45,96 @@ rustc_arena::declare_arena! { rustc_ast::AstOwner )> >, - [] crate_alone: rustc_data_structures::steal::Steal, - [] crate_for_resolver: rustc_data_structures::steal::Steal<(rustc_ast::Crate, rustc_ast::AttrVec)>, - [] resolutions: rustc_middle::ty::ResolverGlobalCtxt, - [] const_allocs: rustc_middle::mir::interpret::Allocation, - [] region_scope_tree: rustc_middle::middle::region::ScopeTree, + crate_alone: rustc_data_structures::steal::Steal, + crate_for_resolver: rustc_data_structures::steal::Steal<(rustc_ast::Crate, rustc_ast::AttrVec)>, + resolutions: rustc_middle::ty::ResolverGlobalCtxt, + const_allocs: rustc_middle::mir::interpret::Allocation, + region_scope_tree: rustc_middle::middle::region::ScopeTree, // Required for the incremental on-disk cache - [] mir_keys: rustc_hir::def_id::DefIdSet, - [] dropck_outlives: + mir_keys: rustc_hir::def_id::DefIdSet, + dropck_outlives: rustc_middle::infer::canonical::Canonical<'tcx, rustc_middle::infer::canonical::QueryResponse<'tcx, rustc_middle::traits::query::DropckOutlivesResult<'tcx> > >, - [] normalize_canonicalized_projection: + normalize_canonicalized_projection: rustc_middle::infer::canonical::Canonical<'tcx, rustc_middle::infer::canonical::QueryResponse<'tcx, rustc_middle::traits::query::NormalizationResult<'tcx> > >, - [] implied_outlives_bounds: + implied_outlives_bounds: rustc_middle::infer::canonical::Canonical<'tcx, rustc_middle::infer::canonical::QueryResponse<'tcx, Vec> > >, - [] dtorck_constraint: rustc_middle::traits::query::DropckConstraint<'tcx>, - [] candidate_step: rustc_middle::traits::query::CandidateStep<'tcx>, - [] autoderef_bad_ty: rustc_middle::traits::query::MethodAutoderefBadTy<'tcx>, - [] query_region_constraints: rustc_middle::infer::canonical::QueryRegionConstraints<'tcx>, - [] type_op_subtype: + dtorck_constraint: rustc_middle::traits::query::DropckConstraint<'tcx>, + candidate_step: rustc_middle::traits::query::CandidateStep<'tcx>, + autoderef_bad_ty: rustc_middle::traits::query::MethodAutoderefBadTy<'tcx>, + query_region_constraints: rustc_middle::infer::canonical::QueryRegionConstraints<'tcx>, + type_op_subtype: rustc_middle::infer::canonical::Canonical<'tcx, rustc_middle::infer::canonical::QueryResponse<'tcx, ()> >, - [] type_op_normalize_poly_fn_sig: + type_op_normalize_poly_fn_sig: rustc_middle::infer::canonical::Canonical<'tcx, rustc_middle::infer::canonical::QueryResponse<'tcx, rustc_middle::ty::PolyFnSig<'tcx>> >, - [] type_op_normalize_fn_sig: + type_op_normalize_fn_sig: rustc_middle::infer::canonical::Canonical<'tcx, rustc_middle::infer::canonical::QueryResponse<'tcx, rustc_middle::ty::FnSig<'tcx>> >, - [] type_op_normalize_clause: + type_op_normalize_clause: rustc_middle::infer::canonical::Canonical<'tcx, rustc_middle::infer::canonical::QueryResponse<'tcx, rustc_middle::ty::Clause<'tcx>> >, - [] type_op_normalize_ty: + type_op_normalize_ty: rustc_middle::infer::canonical::Canonical<'tcx, rustc_middle::infer::canonical::QueryResponse<'tcx, Ty<'tcx>> >, - [] inspect_probe: rustc_middle::traits::solve::inspect::Probe>, - [] effective_visibilities: rustc_middle::middle::privacy::EffectiveVisibilities, - [] upvars_mentioned: rustc_data_structures::fx::FxIndexMap, - [] dyn_compatibility_violations: rustc_middle::traits::DynCompatibilityViolation, - [] codegen_unit: rustc_middle::mono::CodegenUnit<'tcx>, - [] attribute: rustc_hir::Attribute, - [] name_set: rustc_data_structures::unord::UnordSet, - [] autodiff_item: rustc_hir::attrs::AutoDiffItem, - [] ordered_name_set: rustc_data_structures::fx::FxIndexSet, - [] stable_order_of_exportable_impls: + inspect_probe: rustc_middle::traits::solve::inspect::Probe>, + effective_visibilities: rustc_middle::middle::privacy::EffectiveVisibilities, + upvars_mentioned: rustc_data_structures::fx::FxIndexMap, + dyn_compatibility_violations: rustc_middle::traits::DynCompatibilityViolation, + codegen_unit: rustc_middle::mono::CodegenUnit<'tcx>, + attribute: rustc_hir::Attribute, + name_set: rustc_data_structures::unord::UnordSet, + autodiff_item: rustc_hir::attrs::AutoDiffItem, + ordered_name_set: rustc_data_structures::fx::FxIndexSet, + stable_order_of_exportable_impls: rustc_data_structures::fx::FxIndexMap, // Note that this deliberately duplicates items in the `rustc_hir::arena`, // since we need to allocate this type on both the `rustc_hir` arena // (during lowering) and the `rustc_middle` arena (for decoding MIR) - [] asm_template: rustc_ast::InlineAsmTemplatePiece, - [] used_trait_imports: rustc_data_structures::unord::UnordSet, - [] is_late_bound_map: rustc_data_structures::fx::FxIndexSet, - [] impl_source: rustc_middle::traits::ImplSource<'tcx, ()>, + asm_template: rustc_ast::InlineAsmTemplatePiece, + used_trait_imports: rustc_data_structures::unord::UnordSet, + is_late_bound_map: rustc_data_structures::fx::FxIndexSet, + impl_source: rustc_middle::traits::ImplSource<'tcx, ()>, - [] dep_kind_vtable: rustc_middle::dep_graph::DepKindVTable<'tcx>, + dep_kind_vtable: rustc_middle::dep_graph::DepKindVTable<'tcx>, - [] trait_impl_trait_tys: + trait_impl_trait_tys: rustc_data_structures::unord::UnordMap< rustc_hir::def_id::DefId, rustc_middle::ty::EarlyBinder<'tcx, Ty<'tcx>> >, - [] external_constraints: rustc_middle::traits::solve::ExternalConstraintsData>, - [] doc_link_resolutions: rustc_hir::def::DocLinkResMap, - [] stripped_cfg_items: rustc_hir::attrs::StrippedCfgItem, - [] mod_child: rustc_middle::metadata::ModChild, - [] features: rustc_feature::Features, - [] specialization_graph: rustc_middle::traits::specialization_graph::Graph, - [] crate_inherent_impls: rustc_middle::ty::CrateInherentImpls, - [] hir_owner_nodes: rustc_hir::OwnerNodes<'tcx>, - [] token_stream: rustc_ast::tokenstream::TokenStream, - [] maybe_owner: rustc_middle::hir::ProjectedMaybeOwner<'tcx>, - [] owner_info: rustc_middle::hir::ProjectedOwnerInfo<'tcx>, - [] parenting: rustc_hir::def_id::LocalDefIdMap, - [] trait_candidates: rustc_hir::ItemLocalMap<&'tcx [rustc_hir::TraitCandidate<'tcx>]>, - [] delayed_lints: rustc_data_structures::steal::Steal, + external_constraints: rustc_middle::traits::solve::ExternalConstraintsData>, + doc_link_resolutions: rustc_hir::def::DocLinkResMap, + stripped_cfg_items: rustc_hir::attrs::StrippedCfgItem, + mod_child: rustc_middle::metadata::ModChild, + features: rustc_feature::Features, + specialization_graph: rustc_middle::traits::specialization_graph::Graph, + crate_inherent_impls: rustc_middle::ty::CrateInherentImpls, + hir_owner_nodes: rustc_hir::OwnerNodes<'tcx>, + token_stream: rustc_ast::tokenstream::TokenStream, + maybe_owner: rustc_middle::hir::ProjectedMaybeOwner<'tcx>, + owner_info: rustc_middle::hir::ProjectedOwnerInfo<'tcx>, + parenting: rustc_hir::def_id::LocalDefIdMap, + trait_candidates: rustc_hir::ItemLocalMap<&'tcx [rustc_hir::TraitCandidate<'tcx>]>, + delayed_lints: rustc_data_structures::steal::Steal, } #[inline] From c977f6b080ecdc013d13e4920c900125462f950a Mon Sep 17 00:00:00 2001 From: Ada Alakbarova Date: Wed, 29 Jul 2026 18:17:55 +0200 Subject: [PATCH 07/12] misc: use visitor macros to reduce boilerplate --- .../rustc_type_ir/src/region_constraint.rs | 34 +++++-------------- 1 file changed, 8 insertions(+), 26 deletions(-) diff --git a/compiler/rustc_type_ir/src/region_constraint.rs b/compiler/rustc_type_ir/src/region_constraint.rs index e42e96901b74d..a7f7311e2e064 100644 --- a/compiler/rustc_type_ir/src/region_constraint.rs +++ b/compiler/rustc_type_ir/src/region_constraint.rs @@ -53,7 +53,7 @@ use crate::{ AliasTy, Binder, BoundRegion, BoundVar, BoundVariableKind, DebruijnIndex, FallibleTypeFolder, InferCtxtLike, Interner, IsRigid, OutlivesPredicate, Region, RegionKind, TyKind, TypeFoldable, TypeFolder, TypeVisitable, TypeVisitor, TypingMode, UniverseIndex, Variance, VisitorResult, - max_universe, set_aliases_to_non_rigid, + max_universe, set_aliases_to_non_rigid, try_visit, walk_visitable_list, }; #[derive_where(Clone, Debug; I: Interner)] @@ -219,44 +219,26 @@ impl TypeFoldable for RegionConstraint { impl TypeVisitable for RegionConstraint { fn visit_with>(&self, f: &mut F) -> F::Result { - use core::ops::ControlFlow::*; - use RegionConstraint::*; match self { Ambiguity => (), RegionOutlives(a, b) => { - if let b @ Break(_) = a.visit_with(f).branch() { - return F::Result::from_branch(b); - }; - if let b @ Break(_) = b.visit_with(f).branch() { - return F::Result::from_branch(b); - }; + try_visit!(a.visit_with(f)); + try_visit!(b.visit_with(f)); } AliasTyOutlivesViaEnv(outlives) => { - return outlives.visit_with(f); + try_visit!(outlives.visit_with(f)); } PlaceholderTyOutlives(a, b) => { - if let b @ Break(_) = a.visit_with(f).branch() { - return F::Result::from_branch(b); - }; - if let b @ Break(_) = b.visit_with(f).branch() { - return F::Result::from_branch(b); - }; + try_visit!(a.visit_with(f)); + try_visit!(b.visit_with(f)); } And(and) => { - for a in and { - if let b @ Break(_) = a.visit_with(f).branch() { - return F::Result::from_branch(b); - }; - } + walk_visitable_list!(f, and); } Or(or) => { - for a in or { - if let b @ Break(_) = a.visit_with(f).branch() { - return F::Result::from_branch(b); - }; - } + walk_visitable_list!(f, or); } }; From afcea5902b6b0696dcb882e753783de05a4b16cb Mon Sep 17 00:00:00 2001 From: Ada Alakbarova Date: Wed, 29 Jul 2026 18:11:19 +0200 Subject: [PATCH 08/12] derive `GenericTypeVisitable` for `RegionConstraint` Required for rust-analyzer, see https://rust-lang.zulipchat.com/#narrow/channel/185405-t-compiler.2Frust-analyzer/topic/Updating.20next-solver/near/613430602 --- compiler/rustc_type_ir/src/region_constraint.rs | 8 +++++--- 1 file changed, 5 insertions(+), 3 deletions(-) diff --git a/compiler/rustc_type_ir/src/region_constraint.rs b/compiler/rustc_type_ir/src/region_constraint.rs index a7f7311e2e064..8f738e4d6f6f9 100644 --- a/compiler/rustc_type_ir/src/region_constraint.rs +++ b/compiler/rustc_type_ir/src/region_constraint.rs @@ -51,9 +51,10 @@ use crate::inherent::*; use crate::relate::{Relate, RelateResult, TypeRelation, VarianceDiagInfo}; use crate::{ AliasTy, Binder, BoundRegion, BoundVar, BoundVariableKind, DebruijnIndex, FallibleTypeFolder, - InferCtxtLike, Interner, IsRigid, OutlivesPredicate, Region, RegionKind, TyKind, TypeFoldable, - TypeFolder, TypeVisitable, TypeVisitor, TypingMode, UniverseIndex, Variance, VisitorResult, - max_universe, set_aliases_to_non_rigid, try_visit, walk_visitable_list, + GenericTypeVisitable, InferCtxtLike, Interner, IsRigid, OutlivesPredicate, Region, RegionKind, + TyKind, TypeFoldable, TypeFolder, TypeVisitable, TypeVisitor, TypingMode, UniverseIndex, + Variance, VisitorResult, max_universe, set_aliases_to_non_rigid, try_visit, + walk_visitable_list, }; #[derive_where(Clone, Debug; I: Interner)] @@ -91,6 +92,7 @@ impl Assumptions { } #[derive_where(Clone, Hash, PartialEq, Debug; I: Interner)] +#[derive(GenericTypeVisitable)] pub enum RegionConstraint { Ambiguity, RegionOutlives(Region, Region), From 952cbef562d85c1f245a488e57040346f582e70a Mon Sep 17 00:00:00 2001 From: Ada Alakbarova Date: Wed, 29 Jul 2026 21:21:43 +0200 Subject: [PATCH 09/12] A few more "predicate"-to-"clause" renamings Follow-up to https://github.com/rust-lang/rust/pull/159990. This should cover all the files that I didn't get to reviewing in that PR. --- .../src/outlives/implicit_infer.rs | 1 + .../rustc_hir_analysis/src/outlives/utils.rs | 1 + .../src/traits/dyn_compatibility.rs | 28 +++++++++---------- .../rustc_trait_selection/src/traits/mod.rs | 10 +++---- .../traits/query/type_op/ascribe_user_type.rs | 2 +- .../src/traits/select/confirmation.rs | 2 +- .../src/traits/vtable.rs | 5 ++-- .../src/normalize_projection_ty.rs | 4 +-- compiler/rustc_ty_utils/src/sig_types.rs | 4 +-- compiler/rustc_type_ir/src/elaborate.rs | 4 +-- src/librustdoc/clean/simplify.rs | 6 ++-- .../src/implied_bounds_in_impls.rs | 12 ++++---- .../clippy_lints/src/large_stack_frames.rs | 2 +- .../clippy_lints/src/missing_const_for_fn.rs | 6 ++-- .../src/missing_const_for_thread_local.rs | 2 +- .../clippy_lints/src/needless_maybe_sized.rs | 4 +-- .../clippy_lints/src/redundant_clone.rs | 2 +- .../clippy/clippy_utils/src/eager_or_lazy.rs | 2 +- src/tools/clippy/clippy_utils/src/ty/mod.rs | 7 +++-- .../item-collection/drop-glue-eager.rs | 10 +++---- .../generic_struct_field_projection.rs | 2 +- 21 files changed, 62 insertions(+), 54 deletions(-) diff --git a/compiler/rustc_hir_analysis/src/outlives/implicit_infer.rs b/compiler/rustc_hir_analysis/src/outlives/implicit_infer.rs index 8780d877dde50..eaf1c32374df6 100644 --- a/compiler/rustc_hir_analysis/src/outlives/implicit_infer.rs +++ b/compiler/rustc_hir_analysis/src/outlives/implicit_infer.rs @@ -246,6 +246,7 @@ fn insert_required_predicates_to_be_wf<'tcx>( /// will give us `U: 'static` and `U: Outer`. The latter we /// can ignore, but we will want to process `U: 'static`, /// applying the instantiation as above. +// FIXME: change this function's signature and docs to mention clauses instead of predicates #[tracing::instrument(level = "debug", skip(tcx))] fn check_explicit_predicates<'tcx>( tcx: TyCtxt<'tcx>, diff --git a/compiler/rustc_hir_analysis/src/outlives/utils.rs b/compiler/rustc_hir_analysis/src/outlives/utils.rs index 0157703532268..b2a5575584b42 100644 --- a/compiler/rustc_hir_analysis/src/outlives/utils.rs +++ b/compiler/rustc_hir_analysis/src/outlives/utils.rs @@ -11,6 +11,7 @@ pub(crate) type RequiredPredicates<'tcx> = FxIndexMap( tcx: TyCtxt<'tcx>, arg: GenericArg<'tcx>, diff --git a/compiler/rustc_trait_selection/src/traits/dyn_compatibility.rs b/compiler/rustc_trait_selection/src/traits/dyn_compatibility.rs index 76a9956619dae..512a8d91338bc 100644 --- a/compiler/rustc_trait_selection/src/traits/dyn_compatibility.rs +++ b/compiler/rustc_trait_selection/src/traits/dyn_compatibility.rs @@ -40,7 +40,7 @@ pub fn hir_ty_lowering_dyn_compatibility_violations( ) -> Vec { debug_assert!(tcx.generics_of(trait_def_id).has_self); elaborate::supertrait_def_ids(tcx, trait_def_id) - .map(|def_id| predicates_reference_self(tcx, def_id, true)) + .map(|def_id| clauses_reference_self(tcx, def_id, true)) .filter(|spans| !spans.is_empty()) .map(DynCompatibilityViolation::SupertraitSelf) .collect() @@ -98,7 +98,7 @@ fn dyn_compatibility_violations_for_trait( violations.push(DynCompatibilityViolation::ExplicitlyDynIncompatible([span].into())); } - let spans = predicates_reference_self(tcx, trait_def_id, false); + let spans = clauses_reference_self(tcx, trait_def_id, false); if !spans.is_empty() { violations.push(DynCompatibilityViolation::SupertraitSelf(spans)); } @@ -106,11 +106,11 @@ fn dyn_compatibility_violations_for_trait( if !spans.is_empty() { violations.push(DynCompatibilityViolation::SupertraitSelf(spans)); } - let spans = super_predicates_have_non_lifetime_binders(tcx, trait_def_id); + let spans = super_clauses_have_non_lifetime_binders(tcx, trait_def_id); if !spans.is_empty() { violations.push(DynCompatibilityViolation::SupertraitNonLifetimeBinder(spans)); } - let spans = super_predicates_are_unconditionally_const(tcx, trait_def_id); + let spans = super_clauses_are_unconditionally_const(tcx, trait_def_id); if !spans.is_empty() { violations.push(DynCompatibilityViolation::SupertraitConst(spans)); } @@ -168,7 +168,7 @@ fn get_sized_bounds(tcx: TyCtxt<'_>, trait_def_id: DefId) -> SmallVec<[Span; 1]> .unwrap_or_else(SmallVec::new) } -fn predicates_reference_self( +fn clauses_reference_self( tcx: TyCtxt<'_>, trait_def_id: DefId, supertraits_only: bool, @@ -183,7 +183,7 @@ fn predicates_reference_self( .iter() .map(|&(clause, sp)| (clause.instantiate_supertrait(tcx, trait_ref), sp)) .filter_map(|(clause, sp)| { - // Super predicates cannot allow self projections, since they're + // Super clauses cannot allow self projections, since they're // impossible to make into existential bounds without eager resolution // or something. // e.g. `trait A: B`. @@ -278,29 +278,29 @@ fn predicate_references_self<'tcx>( } } -fn super_predicates_have_non_lifetime_binders( +fn super_clauses_have_non_lifetime_binders( tcx: TyCtxt<'_>, trait_def_id: DefId, ) -> SmallVec<[Span; 1]> { tcx.explicit_super_clauses_of(trait_def_id) .iter_identity_copied() .map(Unnormalized::skip_norm_wip) - .filter_map(|(pred, span)| pred.has_non_region_bound_vars().then_some(span)) + .filter_map(|(clause, span)| clause.has_non_region_bound_vars().then_some(span)) .collect() } /// Checks for `const Trait` supertraits. We're okay with `[const] Trait`, /// supertraits since for a non-const instantiation of that trait, the /// conditionally-const supertrait is also not required to be const. -fn super_predicates_are_unconditionally_const( +fn super_clauses_are_unconditionally_const( tcx: TyCtxt<'_>, trait_def_id: DefId, ) -> SmallVec<[Span; 1]> { tcx.explicit_super_clauses_of(trait_def_id) .iter_identity_copied() .map(Unnormalized::skip_norm_wip) - .filter_map(|(pred, span)| { - if let ty::ClauseKind::HostEffect(_) = pred.kind().skip_binder() { + .filter_map(|(clause, span)| { + if let ty::ClauseKind::HostEffect(_) = clause.kind().skip_binder() { Some(span) } else { None @@ -326,7 +326,7 @@ fn generics_require_sized_self(tcx: TyCtxt<'_>, def_id: DefId) -> bool { .into_iter() .map(Unnormalized::skip_norm_wip) .collect(); - elaborate(tcx, clauses).any(|pred| match pred.kind().skip_binder() { + elaborate(tcx, clauses).any(|clause| match clause.kind().skip_binder() { ty::ClauseKind::Trait(ref trait_pred) => { trait_pred.def_id() == sized_def_id && trait_pred.self_ty().is_param(0) } @@ -726,9 +726,9 @@ fn receiver_is_dispatchable<'tcx>( let meta_sized_predicate = { let meta_sized_did = tcx.require_lang_item(LangItem::MetaSized, DUMMY_SP); - ty::TraitRef::new(tcx, meta_sized_did, [unsized_self_ty]).upcast(tcx) + ty::TraitRef::new(tcx, meta_sized_did, [unsized_self_ty]) }; - clauses.push(meta_sized_predicate); + clauses.push(meta_sized_predicate.upcast(tcx)); normalize_param_env_or_error( tcx, diff --git a/compiler/rustc_trait_selection/src/traits/mod.rs b/compiler/rustc_trait_selection/src/traits/mod.rs index f1b22f46d57b4..f27bef8d5c475 100644 --- a/compiler/rustc_trait_selection/src/traits/mod.rs +++ b/compiler/rustc_trait_selection/src/traits/mod.rs @@ -482,7 +482,7 @@ pub fn normalize_param_env_or_error<'tcx>( // then we normalize the `TypeOutlives` bounds inside the normalized parameter environment. // // This works fairly well because trait matching does not actually care about param-env - // TypeOutlives predicates - these are normally used by regionck. + // TypeOutlives clauses - these are normally used by regionck. let outlives_clauses: Vec<_> = clauses .extract_if(.., |clause| { matches!(clause.kind().skip_binder(), ty::ClauseKind::TypeOutlives(..)) @@ -490,7 +490,7 @@ pub fn normalize_param_env_or_error<'tcx>( .collect(); debug!( - "normalize_param_env_or_error: predicates=(non-outlives={:?}, outlives={:?})", + "normalize_param_env_or_error: clauses=(non-outlives={:?}, outlives={:?})", clauses, outlives_clauses ); let Ok(non_outlives_clauses) = @@ -503,9 +503,9 @@ pub fn normalize_param_env_or_error<'tcx>( debug!("normalize_param_env_or_error: non-outlives clauses={:?}", non_outlives_clauses); - // Not sure whether it is better to include the unnormalized TypeOutlives predicates + // Not sure whether it is better to include the unnormalized TypeOutlives clauses // here. I believe they should not matter, because we are ignoring TypeOutlives param-env - // predicates here anyway. Keeping them here anyway because it seems safer. + // clauses here anyway. Keeping them here anyway because it seems safer. let outlives_env = non_outlives_clauses.iter().chain(&outlives_clauses).cloned(); let outlives_env = ty::ParamEnv::new(tcx.mk_clauses_from_iter(outlives_env)); let Ok(outlives_clauses) = do_normalize_clauses(tcx, cause, outlives_env, outlives_clauses) @@ -780,7 +780,7 @@ fn replace_param_and_infer_args_with_placeholder<'tcx>( } /// Normalizes the clauses and checks whether they hold in an empty environment. If this -/// returns true, then either normalize encountered an error or one of the predicates did not +/// returns true, then either normalize encountered an error or one of the clauses did not /// hold. Used when creating vtables to check for unsatisfiable methods. This should not be /// used during analysis. pub fn impossible_clauses<'tcx>(tcx: TyCtxt<'tcx>, clauses: Vec>) -> bool { diff --git a/compiler/rustc_trait_selection/src/traits/query/type_op/ascribe_user_type.rs b/compiler/rustc_trait_selection/src/traits/query/type_op/ascribe_user_type.rs index 4daffc6e1e0da..e8814c56c5016 100644 --- a/compiler/rustc_trait_selection/src/traits/query/type_op/ascribe_user_type.rs +++ b/compiler/rustc_trait_selection/src/traits/query/type_op/ascribe_user_type.rs @@ -126,7 +126,7 @@ fn relate_mir_and_user_args<'tcx>( ocx.eq(&cause, param_env, mir_ty, ty)?; - // Prove the predicates coming along with `def_id`. + // Prove the clauses coming along with `def_id`. // // Also, normalize the `instantiated_clauses` // because otherwise we wind up with duplicate "type diff --git a/compiler/rustc_trait_selection/src/traits/select/confirmation.rs b/compiler/rustc_trait_selection/src/traits/select/confirmation.rs index 22fb714cfd33c..4b083d9d59452 100644 --- a/compiler/rustc_trait_selection/src/traits/select/confirmation.rs +++ b/compiler/rustc_trait_selection/src/traits/select/confirmation.rs @@ -541,7 +541,7 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> { for supertrait in tcx .explicit_super_clauses_of(trait_predicate.def_id()) .iter_instantiated_copied(tcx, trait_predicate.trait_ref.args) - .map(|pred| pred.unzip().0) + .map(|clause| clause.unzip().0) { let normalized_supertrait = normalize_with_depth_to( self, diff --git a/compiler/rustc_trait_selection/src/traits/vtable.rs b/compiler/rustc_trait_selection/src/traits/vtable.rs index 7113169555d10..77d7a39a6eb77 100644 --- a/compiler/rustc_trait_selection/src/traits/vtable.rs +++ b/compiler/rustc_trait_selection/src/traits/vtable.rs @@ -125,8 +125,9 @@ fn prepare_vtable_segments_inner<'tcx, T>( .explicit_super_clauses_of(inner_most_trait_ref.def_id) .iter_identity_copied() .map(Unnormalized::skip_norm_wip) - .filter_map(move |(pred, _)| { - pred.instantiate_supertrait(tcx, ty::Binder::dummy(inner_most_trait_ref)) + .filter_map(move |(clause, _)| { + clause + .instantiate_supertrait(tcx, ty::Binder::dummy(inner_most_trait_ref)) .as_trait_clause() }) .map(move |pred| { diff --git a/compiler/rustc_traits/src/normalize_projection_ty.rs b/compiler/rustc_traits/src/normalize_projection_ty.rs index c6f759fb7937d..96d5f4fb398e0 100644 --- a/compiler/rustc_traits/src/normalize_projection_ty.rs +++ b/compiler/rustc_traits/src/normalize_projection_ty.rs @@ -102,12 +102,12 @@ fn normalize_canonicalized_free_alias<'tcx>( |ocx, ParamEnvAnd { param_env, value: goal }| { let def_id = goal.expect_free_def_id(); let obligations = - tcx.clauses_of(def_id).instantiate_own(tcx, goal.args).map(|(predicate, span)| { + tcx.clauses_of(def_id).instantiate_own(tcx, goal.args).map(|(clause, span)| { traits::Obligation::new( tcx, ObligationCause::dummy_with_span(span), param_env, - predicate.skip_norm_wip(), + clause.skip_norm_wip(), ) }); ocx.register_obligations(obligations); diff --git a/compiler/rustc_ty_utils/src/sig_types.rs b/compiler/rustc_ty_utils/src/sig_types.rs index b010b6ec9144b..3a08114768cab 100644 --- a/compiler/rustc_ty_utils/src/sig_types.rs +++ b/compiler/rustc_ty_utils/src/sig_types.rs @@ -34,8 +34,8 @@ pub fn walk_types<'tcx, V: SpannedTypeVisitor<'tcx>>( visitor.visit(ty.span, tcx.type_of(item).instantiate_identity().skip_norm_wip()) ); } - for (pred, span) in tcx.explicit_clauses_of(item).instantiate_identity(tcx) { - try_visit!(visitor.visit(span, pred.skip_norm_wip())); + for (clause, span) in tcx.explicit_clauses_of(item).instantiate_identity(tcx) { + try_visit!(visitor.visit(span, clause.skip_norm_wip())); } V::Result::output() }; diff --git a/compiler/rustc_type_ir/src/elaborate.rs b/compiler/rustc_type_ir/src/elaborate.rs index 0f050b0bed894..1460a481b79a5 100644 --- a/compiler/rustc_type_ir/src/elaborate.rs +++ b/compiler/rustc_type_ir/src/elaborate.rs @@ -165,8 +165,8 @@ impl> Elaborator { ) }; - // Get predicates implied by the trait, or only super predicates if we only care - // about self predicates. + // Get clauses implied by the trait, or only super clauses if we only care + // about self clauses. match self.mode { Filter::All => self.extend_deduped( cx.explicit_implied_clauses_of(data.def_id().into()) diff --git a/src/librustdoc/clean/simplify.rs b/src/librustdoc/clean/simplify.rs index 3b00e2b3ac48b..a3732fb727dbd 100644 --- a/src/librustdoc/clean/simplify.rs +++ b/src/librustdoc/clean/simplify.rs @@ -113,11 +113,11 @@ fn trait_is_same_or_supertrait(tcx: TyCtxt<'_>, child: DefId, trait_: DefId) -> if child == trait_ { return true; } - let predicates = tcx.explicit_super_clauses_of(child); - predicates + let clauses = tcx.explicit_super_clauses_of(child); + clauses .iter_identity_copied() .map(Unnormalized::skip_norm_wip) - .filter_map(|(pred, _)| Some(pred.as_trait_clause()?.def_id())) + .filter_map(|(clause, _)| Some(clause.as_trait_clause()?.def_id())) .any(|did| trait_is_same_or_supertrait(tcx, did, trait_)) } diff --git a/src/tools/clippy/clippy_lints/src/implied_bounds_in_impls.rs b/src/tools/clippy/clippy_lints/src/implied_bounds_in_impls.rs index 04a7c6a74e3c7..2d835b2da97ed 100644 --- a/src/tools/clippy/clippy_lints/src/implied_bounds_in_impls.rs +++ b/src/tools/clippy/clippy_lints/src/implied_bounds_in_impls.rs @@ -216,9 +216,9 @@ fn is_same_generics<'tcx>( struct ImplTraitBound<'tcx> { /// The span of the bound in the `impl Trait` type span: Span, - /// The predicates defined in the trait referenced by this bound. This also contains the actual + /// The clauses defined in the trait referenced by this bound. This also contains the actual /// supertrait bounds - predicates: &'tcx [(ty::Clause<'tcx>, Span)], + clauses: &'tcx [(ty::Clause<'tcx>, Span)], /// The `DefId` of the trait being referenced by this bound trait_def_id: DefId, /// The generic arguments on the `impl Trait` bound @@ -241,13 +241,13 @@ fn collect_supertrait_bounds<'tcx>(cx: &LateContext<'tcx>, bounds: GenericBounds && let [.., path] = poly_trait.trait_ref.path.segments && poly_trait.bound_generic_params.is_empty() && let Some(trait_def_id) = path.res.opt_def_id() - && let predicates = cx.tcx.explicit_super_clauses_of(trait_def_id).skip_binder() + && let clauses = cx.tcx.explicit_super_clauses_of(trait_def_id).skip_binder() // If the trait has no supertrait, there is no need to collect anything from that bound - && !predicates.is_empty() + && !clauses.is_empty() { Some(ImplTraitBound { span: bound.span(), - predicates, + clauses, trait_def_id, args: path.args.map_or([].as_slice(), |p| p.args), constraints: path.args.map_or([].as_slice(), |p| p.constraints), @@ -268,7 +268,7 @@ fn find_bound_in_supertraits<'a, 'tcx>( bounds: &'a [ImplTraitBound<'tcx>], ) -> Option<&'a ImplTraitBound<'tcx>> { bounds.iter().find(|bound| { - bound.predicates.iter().any(|(clause, _)| { + bound.clauses.iter().any(|(clause, _)| { if let ClauseKind::Trait(tr) = clause.kind().skip_binder() && tr.def_id() == trait_def_id { diff --git a/src/tools/clippy/clippy_lints/src/large_stack_frames.rs b/src/tools/clippy/clippy_lints/src/large_stack_frames.rs index bf4d37ad570e0..878a5bc7f8666 100644 --- a/src/tools/clippy/clippy_lints/src/large_stack_frames.rs +++ b/src/tools/clippy/clippy_lints/src/large_stack_frames.rs @@ -147,7 +147,7 @@ impl<'tcx> LateLintPass<'tcx> for LargeStackFrames { local_def_id: LocalDefId, ) { let def_id = local_def_id.to_def_id(); - // Building MIR for `fn`s with unsatisfiable preds results in ICE. + // Building MIR for `fn`s with unsatisfiable clauses results in ICE. if fn_has_unsatisfiable_clauses(cx, def_id) { return; } diff --git a/src/tools/clippy/clippy_lints/src/missing_const_for_fn.rs b/src/tools/clippy/clippy_lints/src/missing_const_for_fn.rs index d032d53b69902..82f5961729aad 100644 --- a/src/tools/clippy/clippy_lints/src/missing_const_for_fn.rs +++ b/src/tools/clippy/clippy_lints/src/missing_const_for_fn.rs @@ -2,7 +2,9 @@ use clippy_config::Conf; use clippy_utils::diagnostics::span_lint_and_then; use clippy_utils::msrvs::{self, Msrv}; use clippy_utils::qualify_min_const_fn::is_min_const_fn; -use clippy_utils::{fn_has_unsatisfiable_clauses, is_entrypoint_fn, is_from_proc_macro, is_in_test, trait_ref_of_method}; +use clippy_utils::{ + fn_has_unsatisfiable_clauses, is_entrypoint_fn, is_from_proc_macro, is_in_test, trait_ref_of_method, +}; use rustc_abi::ExternAbi; use rustc_errors::Applicability; use rustc_hir::def_id::CRATE_DEF_ID; @@ -103,7 +105,7 @@ impl<'tcx> LateLintPass<'tcx> for MissingConstForFn { return; } - // Building MIR for `fn`s with unsatisfiable preds results in ICE. + // Building MIR for `fn`s with unsatisfiable clauses results in ICE. if fn_has_unsatisfiable_clauses(cx, def_id.to_def_id()) { return; } diff --git a/src/tools/clippy/clippy_lints/src/missing_const_for_thread_local.rs b/src/tools/clippy/clippy_lints/src/missing_const_for_thread_local.rs index a7be1e4760230..d02b7fa68b75e 100644 --- a/src/tools/clippy/clippy_lints/src/missing_const_for_thread_local.rs +++ b/src/tools/clippy/clippy_lints/src/missing_const_for_thread_local.rs @@ -89,7 +89,7 @@ fn is_unreachable(cx: &LateContext<'_>, expr: &Expr<'_>) -> bool { #[inline] fn initializer_can_be_made_const(cx: &LateContext<'_>, defid: rustc_span::def_id::DefId, msrv: Msrv) -> bool { - // Building MIR for `fn`s with unsatisfiable preds results in ICE. + // Building MIR for `fn`s with unsatisfiable clauses results in ICE. if !fn_has_unsatisfiable_clauses(cx, defid) && let mir = cx.tcx.optimized_mir(defid) && let Ok(()) = is_min_const_fn(cx, mir, msrv) diff --git a/src/tools/clippy/clippy_lints/src/needless_maybe_sized.rs b/src/tools/clippy/clippy_lints/src/needless_maybe_sized.rs index b8e40cbf05049..079f5a4929dc7 100644 --- a/src/tools/clippy/clippy_lints/src/needless_maybe_sized.rs +++ b/src/tools/clippy/clippy_lints/src/needless_maybe_sized.rs @@ -92,13 +92,13 @@ fn path_to_sized_bound(cx: &LateContext<'_>, trait_bound: &PolyTraitRef<'_>) -> return true; } - for (predicate, _) in cx + for (clause, _) in cx .tcx .explicit_super_clauses_of(trait_def_id) .iter_identity_copied() .map(Unnormalized::skip_norm_wip) { - if let ClauseKind::Trait(trait_predicate) = predicate.kind().skip_binder() + if let ClauseKind::Trait(trait_predicate) = clause.kind().skip_binder() && trait_predicate.polarity == PredicatePolarity::Positive && !path.contains(&trait_predicate.def_id()) { diff --git a/src/tools/clippy/clippy_lints/src/redundant_clone.rs b/src/tools/clippy/clippy_lints/src/redundant_clone.rs index e2fddfd50279c..579f9b8daffd5 100644 --- a/src/tools/clippy/clippy_lints/src/redundant_clone.rs +++ b/src/tools/clippy/clippy_lints/src/redundant_clone.rs @@ -73,7 +73,7 @@ impl<'tcx> LateLintPass<'tcx> for RedundantClone { _: Span, def_id: LocalDefId, ) { - // Building MIR for `fn`s with unsatisfiable preds results in ICE. + // Building MIR for `fn`s with unsatisfiable clauses results in ICE. if fn_has_unsatisfiable_clauses(cx, def_id.to_def_id()) { return; } diff --git a/src/tools/clippy/clippy_utils/src/eager_or_lazy.rs b/src/tools/clippy/clippy_utils/src/eager_or_lazy.rs index 9e9ae945ee16f..59fe5f4964822 100644 --- a/src/tools/clippy/clippy_utils/src/eager_or_lazy.rs +++ b/src/tools/clippy/clippy_utils/src/eager_or_lazy.rs @@ -78,7 +78,7 @@ fn fn_eagerness(tcx: TyCtxt<'_>, fn_id: DefId, name: Symbol, have_one_arg: bool) .kind(), ty::Param(_) ) - }) && all_clauses_of(tcx, fn_id).all(|(pred, _)| match pred.kind().skip_binder() { + }) && all_clauses_of(tcx, fn_id).all(|(clause, _)| match clause.kind().skip_binder() { ty::ClauseKind::Trait(pred) => tcx.trait_def(pred.trait_ref.def_id).is_marker, _ => true, }) && subs.types().all(|x| matches!(x.peel_refs().kind(), ty::Param(_))) diff --git a/src/tools/clippy/clippy_utils/src/ty/mod.rs b/src/tools/clippy/clippy_utils/src/ty/mod.rs index 1ce756da41afc..ac3c76df6086f 100644 --- a/src/tools/clippy/clippy_utils/src/ty/mod.rs +++ b/src/tools/clippy/clippy_utils/src/ty/mod.rs @@ -616,7 +616,7 @@ fn is_uninit_value_valid_for_ty_fallback<'tcx>(cx: &LateContext<'tcx>, ty: Ty<'t } } -/// Gets an iterator over all predicates which apply to the given item. +/// Gets an iterator over all clauses which apply to the given item. pub fn all_clauses_of(tcx: TyCtxt<'_>, id: DefId) -> impl Iterator, Span)> { let mut next_id = Some(id); iter::from_fn(move || { @@ -719,7 +719,10 @@ pub fn ty_sig<'tcx>(cx: &LateContext<'tcx>, ty: Ty<'tcx>) -> Option Some(ExprFnSig::Sig( - cx.tcx.fn_sig(id).instantiate(cx.tcx, subs.no_bound_vars().unwrap()).skip_norm_wip(), + cx.tcx + .fn_sig(id) + .instantiate(cx.tcx, subs.no_bound_vars().unwrap()) + .skip_norm_wip(), Some(id), )), ty::Alias( diff --git a/tests/codegen-units/item-collection/drop-glue-eager.rs b/tests/codegen-units/item-collection/drop-glue-eager.rs index 7039dbbbe679a..0863cb6e5d671 100644 --- a/tests/codegen-units/item-collection/drop-glue-eager.rs +++ b/tests/codegen-units/item-collection/drop-glue-eager.rs @@ -47,14 +47,14 @@ struct StructWithDropAndLt<'a> { // Make sure we don't ICE when checking impossible clauses for the struct. // Regression test for . -//~ MONO_ITEM fn std::ptr::drop_glue::> - shim(Some(StructWithLtAndPredicate<'_>)) -struct StructWithLtAndPredicate<'a: 'a> { +//~ MONO_ITEM fn std::ptr::drop_glue::> - shim(Some(StructWithLtAndClause<'_>)) +struct StructWithLtAndClause<'a: 'a> { x: &'a i32, } // We should be able to monomorphize drops for struct with lifetimes. -impl<'a> Drop for StructWithLtAndPredicate<'a> { - //~ MONO_ITEM fn as std::ops::Drop>::drop - //~ MONO_ITEM fn as std::ops::Drop>::pin_drop +impl<'a> Drop for StructWithLtAndClause<'a> { + //~ MONO_ITEM fn as std::ops::Drop>::drop + //~ MONO_ITEM fn as std::ops::Drop>::pin_drop fn drop(&mut self) {} } diff --git a/tests/ui/privacy/generic_struct_field_projection.rs b/tests/ui/privacy/generic_struct_field_projection.rs index a6a5f6332abe4..46b061465af10 100644 --- a/tests/ui/privacy/generic_struct_field_projection.rs +++ b/tests/ui/privacy/generic_struct_field_projection.rs @@ -7,7 +7,7 @@ //! in the outlives bounds of `Struct`. While this is trivially provable, privacy //! only sees `Foo` and `Trait` and determines that `Foo` is private and then errors. //! So now we invoke `explicit_clauses_of` to make sure we only care about user-written -//! predicates. +//! clauses. //@ check-pass From b60abe4fbff88e09b5ed3d3250eb4c1106efc57c Mon Sep 17 00:00:00 2001 From: Yukang Date: Thu, 30 Jul 2026 10:27:47 +0800 Subject: [PATCH 10/12] Fix ICE for parsing issue with unexpected closing brace --- compiler/rustc_parse/src/parser/stmt.rs | 7 ++++--- ...visibility-before-close-brace-issue-160171.rs | 7 +++++++ ...bility-before-close-brace-issue-160171.stderr | 16 ++++++++++++++++ 3 files changed, 27 insertions(+), 3 deletions(-) create mode 100644 tests/ui/parser/visibility-before-close-brace-issue-160171.rs create mode 100644 tests/ui/parser/visibility-before-close-brace-issue-160171.stderr diff --git a/compiler/rustc_parse/src/parser/stmt.rs b/compiler/rustc_parse/src/parser/stmt.rs index 067101a6446a1..6339532af530c 100644 --- a/compiler/rustc_parse/src/parser/stmt.rs +++ b/compiler/rustc_parse/src/parser/stmt.rs @@ -168,10 +168,11 @@ impl<'a> Parser<'a> { // Do not attempt to parse an expression if we're done here. self.error_outer_attrs(attrs)?; self.mk_stmt(lo, StmtKind::Empty) - } else if self.token == token::CloseBrace { - self.error_outer_attrs(attrs)?; - self.dcx().span_bug(self.token.span, "don't parse a statement if you see `}`"); } else { + if self.token == token::CloseBrace { + self.error_outer_attrs(attrs.clone())?; + } + // Remainder are line-expr stmts. This is similar to the `parse_stmt_path_start` case // above. let restrictions = diff --git a/tests/ui/parser/visibility-before-close-brace-issue-160171.rs b/tests/ui/parser/visibility-before-close-brace-issue-160171.rs new file mode 100644 index 0000000000000..88cca176a5547 --- /dev/null +++ b/tests/ui/parser/visibility-before-close-brace-issue-160171.rs @@ -0,0 +1,7 @@ +//! Regression test for https://github.com/rust-lang/rust/issues/160171. +//! A misplaced `pub` before a block's closing brace must not ICE. + +fn main() { + pub + //~^ ERROR visibility `pub` is not followed by an item +} //~ ERROR expected expression, found `}` diff --git a/tests/ui/parser/visibility-before-close-brace-issue-160171.stderr b/tests/ui/parser/visibility-before-close-brace-issue-160171.stderr new file mode 100644 index 0000000000000..3fa1a7092d7d5 --- /dev/null +++ b/tests/ui/parser/visibility-before-close-brace-issue-160171.stderr @@ -0,0 +1,16 @@ +error: visibility `pub` is not followed by an item + --> $DIR/visibility-before-close-brace-issue-160171.rs:5:5 + | +LL | pub + | ^^^ the visibility + | + = help: you likely meant to define an item, e.g., `pub fn foo() {}` + +error: expected expression, found `}` + --> $DIR/visibility-before-close-brace-issue-160171.rs:7:1 + | +LL | } + | ^ expected expression + +error: aborting due to 2 previous errors + From f54409bae7b07c2c76f6dcfbd587367a76d287f9 Mon Sep 17 00:00:00 2001 From: Zalathar Date: Thu, 30 Jul 2026 20:30:44 +1000 Subject: [PATCH 11/12] Remove method `Subcommand::kind` Every caller can either get the kind from `builder.kind`, or directly match against variants of `Subcommand`. `Builder::new` is now the sole mapping from `Subcommand` to `Kind`. --- src/bootstrap/src/core/build_steps/check.rs | 4 ++-- src/bootstrap/src/core/builder/tests.rs | 7 +++---- src/bootstrap/src/core/config/flags.rs | 21 --------------------- src/bootstrap/src/core/sanity.rs | 4 ++-- 4 files changed, 7 insertions(+), 29 deletions(-) diff --git a/src/bootstrap/src/core/build_steps/check.rs b/src/bootstrap/src/core/build_steps/check.rs index 1bb925f726a16..2fc72a42b0e54 100644 --- a/src/bootstrap/src/core/build_steps/check.rs +++ b/src/bootstrap/src/core/build_steps/check.rs @@ -88,7 +88,7 @@ impl CommandLineStep for Std { Mode::Std, SourceType::InTree, target, - builder.config.cmd.kind(), + builder.kind, ); std_cargo(builder, target, &mut cargo, &self.crates); @@ -98,7 +98,7 @@ impl CommandLineStep for Std { } let _guard = builder.msg( - builder.config.cmd.kind(), + builder.kind, format_args!("library artifacts{}", crate_description(&self.crates)), Mode::Std, build_compiler, diff --git a/src/bootstrap/src/core/builder/tests.rs b/src/bootstrap/src/core/builder/tests.rs index 2385b5b4ccab2..7cf6009914f60 100644 --- a/src/bootstrap/src/core/builder/tests.rs +++ b/src/bootstrap/src/core/builder/tests.rs @@ -24,10 +24,9 @@ fn configure_with_args(cmd: &[&str], host: &[&str], target: &[&str]) -> Config { } fn run_build(paths: &[PathBuf], config: Config) -> Cache { - let kind = config.cmd.kind(); let build = Build::new(config); let builder = Builder::new(&build); - builder.run_step_descriptions(&Builder::get_step_descriptions(kind), paths); + builder.run_step_descriptions(&Builder::get_step_descriptions(builder.kind), paths); builder.cache } @@ -3232,10 +3231,10 @@ impl ConfigBuilder { fn run(self) -> Cache { let config = self.create_config(); - let kind = config.cmd.kind(); let build = Build::new(config); let builder = Builder::new(&build); - builder.run_step_descriptions(&Builder::get_step_descriptions(kind), &builder.paths); + builder + .run_step_descriptions(&Builder::get_step_descriptions(builder.kind), &builder.paths); builder.cache } diff --git a/src/bootstrap/src/core/config/flags.rs b/src/bootstrap/src/core/config/flags.rs index 385600c38062b..fba3a9fe74705 100644 --- a/src/bootstrap/src/core/config/flags.rs +++ b/src/bootstrap/src/core/config/flags.rs @@ -549,27 +549,6 @@ impl Default for Subcommand { } impl Subcommand { - pub fn kind(&self) -> Kind { - match self { - Subcommand::Bench { .. } => Kind::Bench, - Subcommand::Build { .. } => Kind::Build, - Subcommand::Check { .. } => Kind::Check, - Subcommand::Clippy { .. } => Kind::Clippy, - Subcommand::Doc { .. } => Kind::Doc, - Subcommand::Fix => Kind::Fix, - Subcommand::Format { .. } => Kind::Format, - Subcommand::Test { .. } => Kind::Test, - Subcommand::Miri { .. } => Kind::Miri, - Subcommand::Clean { .. } => Kind::Clean, - Subcommand::Dist => Kind::Dist, - Subcommand::Install => Kind::Install, - Subcommand::Run { .. } => Kind::Run, - Subcommand::Setup { .. } => Kind::Setup, - Subcommand::Vendor { .. } => Kind::Vendor, - Subcommand::Perf { .. } => Kind::Perf, - } - } - pub fn compiletest_rustc_args(&self) -> Vec<&str> { match *self { Subcommand::Test { ref compiletest_rustc_args, .. } => { diff --git a/src/bootstrap/src/core/sanity.rs b/src/bootstrap/src/core/sanity.rs index 51ece21324c3b..400d0715a4738 100644 --- a/src/bootstrap/src/core/sanity.rs +++ b/src/bootstrap/src/core/sanity.rs @@ -14,7 +14,7 @@ use std::ffi::{OsStr, OsString}; use std::path::PathBuf; use std::{env, fs}; -use crate::builder::{Builder, Kind}; +use crate::builder::Builder; use crate::core::build_steps::tool; use crate::core::config::{CompilerBuiltins, DebuggerPath, Target}; use crate::utils::exec::command; @@ -80,7 +80,7 @@ pub fn check(build: &mut Build) { let mut skip_target_sanity = env::var_os("BOOTSTRAP_SKIP_TARGET_SANITY").is_some_and(|s| s == "1" || s == "true"); - skip_target_sanity |= build.config.cmd.kind() == Kind::Check; + skip_target_sanity |= matches!(build.config.cmd, Subcommand::Check { .. }); // Skip target sanity checks when we are doing anything with mir-opt tests or Miri let skipped_paths = [OsStr::new("mir-opt"), OsStr::new("miri")]; From 84af593aa800ddf2f58da4a0a2a0407621c96ed7 Mon Sep 17 00:00:00 2001 From: Yuki Okushi Date: Tue, 28 Jul 2026 07:22:47 +0900 Subject: [PATCH 12/12] std: make positioned I/O unsupported on VxWorks --- library/std/src/sys/fd/unix.rs | 36 ++++++++++++++++++++++------------ 1 file changed, 23 insertions(+), 13 deletions(-) diff --git a/library/std/src/sys/fd/unix.rs b/library/std/src/sys/fd/unix.rs index a96df3972be6a..d35a001bb6bab 100644 --- a/library/std/src/sys/fd/unix.rs +++ b/library/std/src/sys/fd/unix.rs @@ -19,6 +19,27 @@ use libc::off_t as off64_t; use libc::off64_t; cfg_select! { + target_os = "vxworks" => { + // VxWorks does not have pread/pwrite. + // See . + pub unsafe fn pread64( + _fd: libc::c_int, + _buf: *mut libc::c_void, + _count: libc::size_t, + _offset: off64_t, + ) -> libc::ssize_t { + -1 + } + + pub unsafe fn pwrite64( + _fd: libc::c_int, + _buf: *const libc::c_void, + _count: libc::size_t, + _offset: off64_t, + ) -> libc::ssize_t { + -1 + } + } any( all(target_os = "linux", not(target_env = "musl")), target_os = "android", @@ -27,9 +48,11 @@ cfg_select! { // Prefer explicit pread64 for 64-bit offset independently of libc // #[cfg(gnu_file_offset_bits64)]. use libc::pread64; + use libc::pwrite64; } _ => { use libc::pread as pread64; + use libc::pwrite as pwrite64; } } @@ -398,19 +421,6 @@ impl FileDesc { } pub fn write_at(&self, buf: &[u8], offset: u64) -> io::Result { - #[cfg(not(any( - all(target_os = "linux", not(target_env = "musl")), - target_os = "android", - target_os = "hurd" - )))] - use libc::pwrite as pwrite64; - #[cfg(any( - all(target_os = "linux", not(target_env = "musl")), - target_os = "android", - target_os = "hurd" - ))] - use libc::pwrite64; - unsafe { cvt(pwrite64( self.as_raw_fd(),