Skip to content
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
20 commits
Select commit Hold shift + click to select a range
7cb6912
Remove a flaky `got_timeout` assert from two channel tests
Zalathar Mar 7, 2026
858b82d
Simplify find_attr! for HirId usage
mehdiakiki Mar 9, 2026
4eb9e66
Extend ASCII fast paths of `char` methods beyond ASCII
Jules-Bertholet Mar 16, 2024
e844c24
resolve namespaced crates with open modules
b-naber Feb 3, 2026
9a4b38c
Add new alias for Guillaume Gomez email address
GuillaumeGomez Mar 21, 2026
b31dc4a
diagnostics: avoid ICE for undeclared generic parameter in impl
Unique-Usman Mar 21, 2026
e0aed9c
Point to the tracking issue for #[diagnostic::on_move]
rperier Mar 21, 2026
8d07261
Add APIs for dealing with titlecase
Jules-Bertholet Mar 16, 2024
9b0be78
allow `incomplete_features` in most UI tests
cyrgani Mar 21, 2026
e19ad08
Use enums to clarify `DepNodeColorMap` color marking
Zalathar Mar 20, 2026
1fec51c
Remove `DepNodeColorMap::insert_red`
Zalathar Mar 22, 2026
7d1b019
Rollup merge of #122668 - Jules-Bertholet:titlecase, r=Mark-Simulacrum
Zalathar Mar 22, 2026
5e28578
Rollup merge of #153312 - b-naber:namespaced-crate-names-pt1, r=petro…
Zalathar Mar 22, 2026
3f7c96b
Rollup merge of #153534 - Zalathar:flaky-stress, r=Mark-Simulacrum
Zalathar Mar 22, 2026
74bb941
Rollup merge of #153582 - mehdiakiki:simplify-find-attr-hir-id, r=Jon…
Zalathar Mar 22, 2026
6a42545
Rollup merge of #154174 - cyrgani:incomplete-mcp, r=JonathanBrouwer
Zalathar Mar 22, 2026
bd5175f
Rollup merge of #154175 - GuillaumeGomez:mailmap, r=Mark-Simulacrum
Zalathar Mar 22, 2026
b7b5bd1
Rollup merge of #154182 - Unique-Usman:ua/constnotype2, r=estebank
Zalathar Mar 22, 2026
53a0032
Rollup merge of #154188 - rperier:diagnostic_on_move_point_to_the_tra…
Zalathar Mar 22, 2026
b7db424
Rollup merge of #154201 - Zalathar:try-set-color, r=nnethercote
Zalathar Mar 22, 2026
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions .mailmap
Original file line number Diff line number Diff line change
Expand Up @@ -262,6 +262,7 @@ Guillaume Gomez <guillaume1.gomez@gmail.com>
Guillaume Gomez <guillaume1.gomez@gmail.com> ggomez <ggomez@ggo.ifr.lan>
Guillaume Gomez <guillaume1.gomez@gmail.com> Guillaume Gomez <ggomez@ggo.ifr.lan>
Guillaume Gomez <guillaume1.gomez@gmail.com> Guillaume Gomez <guillaume.gomez@huawei.com>
Guillaume Gomez <guillaume1.gomez@gmail.com> Guillaume Gomez <contact@guillaume-gomez.fr>
gnzlbg <gonzalobg88@gmail.com> <gnzlbg@users.noreply.github.com>
hamidreza kalbasi <hamidrezakalbasi@protonmail.com>
Hanna Kruppe <hanna.kruppe@gmail.com> <robin.kruppe@gmail.com>
Expand Down
2 changes: 1 addition & 1 deletion compiler/rustc_const_eval/src/const_eval/fn_queries.rs
Original file line number Diff line number Diff line change
Expand Up @@ -37,7 +37,7 @@ fn constness(tcx: TyCtxt<'_>, def_id: LocalDefId) -> Constness {
}
}
Node::TraitItem(ti @ TraitItem { kind: TraitItemKind::Fn(..), .. }) => {
if find_attr!(tcx.hir_attrs(ti.hir_id()), RustcNonConstTraitMethod) {
if find_attr!(tcx, ti.hir_id(), RustcNonConstTraitMethod) {
Constness::NotConst
} else {
tcx.trait_def(tcx.local_parent(def_id)).constness
Expand Down
2 changes: 1 addition & 1 deletion compiler/rustc_feature/src/unstable.rs
Original file line number Diff line number Diff line change
Expand Up @@ -473,7 +473,7 @@ declare_features! (
/// Allows giving non-const impls custom diagnostic messages if attempted to be used as const
(unstable, diagnostic_on_const, "1.93.0", Some(143874)),
/// Allows giving on-move borrowck custom diagnostic messages for a type
(unstable, diagnostic_on_move, "CURRENT_RUSTC_VERSION", Some(150935)),
(unstable, diagnostic_on_move, "CURRENT_RUSTC_VERSION", Some(154181)),
/// Allows `#[doc(cfg(...))]`.
(unstable, doc_cfg, "1.21.0", Some(43781)),
/// Allows `#[doc(masked)]`.
Expand Down
26 changes: 19 additions & 7 deletions compiler/rustc_hir/src/attrs/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,15 @@ pub mod diagnostic;
mod encode_cross_crate;
mod pretty_printing;

/// A trait for types that can provide a list of attributes given a `TyCtxt`.
///
/// It allows `find_attr!` to accept either a `DefId`, `LocalDefId`, `OwnerId`, or `HirId`.
/// It is defined here with a generic `Tcx` because `rustc_hir` can't depend on `rustc_middle`.
/// The concrete implementations are in `rustc_middle`.
pub trait HasAttrs<'tcx, Tcx> {
fn get_attrs(self, tcx: &Tcx) -> &'tcx [crate::Attribute];
}

/// Finds attributes in sequences of attributes by pattern matching.
///
/// A little like `matches` but for attributes.
Expand All @@ -34,10 +43,12 @@ mod pretty_printing;
///
/// As a convenience, this macro can do that for you!
///
/// Instead of providing an attribute list, provide the `tcx` and a `DefId`.
/// Instead of providing an attribute list, provide the `tcx` and an id
/// (a `DefId`, `LocalDefId`, `OwnerId` or `HirId`).
///
/// ```rust,ignore (illustrative)
/// find_attr!(tcx, def_id, <pattern>)
/// find_attr!(tcx, hir_id, <pattern>)
/// ```
///
/// Another common case is finding attributes applied to the root of the current crate.
Expand All @@ -55,13 +66,14 @@ macro_rules! find_attr {
$crate::find_attr!($tcx.hir_krate_attrs(), $pattern $(if $guard)? => $e)
};

($tcx: expr, $def_id: expr, $pattern: pat $(if $guard: expr)?) => {
$crate::find_attr!($tcx, $def_id, $pattern $(if $guard)? => ()).is_some()
($tcx: expr, $id: expr, $pattern: pat $(if $guard: expr)?) => {
$crate::find_attr!($tcx, $id, $pattern $(if $guard)? => ()).is_some()
};
($tcx: expr, $def_id: expr, $pattern: pat $(if $guard: expr)? => $e: expr) => {{
#[allow(deprecated)] {
$crate::find_attr!($tcx.get_all_attrs($def_id), $pattern $(if $guard)? => $e)
}
($tcx: expr, $id: expr, $pattern: pat $(if $guard: expr)? => $e: expr) => {{
$crate::find_attr!(
$crate::attrs::HasAttrs::get_attrs($id, &$tcx),
$pattern $(if $guard)? => $e
)
}};


Expand Down
19 changes: 16 additions & 3 deletions compiler/rustc_hir/src/def.rs
Original file line number Diff line number Diff line change
Expand Up @@ -590,6 +590,13 @@ pub enum Res<Id = hir::HirId> {
/// **Belongs to the type namespace.**
ToolMod,

/// The resolution for an open module in a namespaced crate. E.g. `my_api`
/// in the namespaced crate `my_api::utils` when `my_api` isn't part of the
/// extern prelude.
///
/// **Belongs to the type namespace.**
OpenMod(Symbol),

// Macro namespace
/// An attribute that is *not* implemented via macro.
/// E.g., `#[inline]` and `#[rustfmt::skip]`, which are essentially directives,
Expand Down Expand Up @@ -838,6 +845,7 @@ impl<Id> Res<Id> {
| Res::SelfTyAlias { .. }
| Res::SelfCtor(..)
| Res::ToolMod
| Res::OpenMod(..)
| Res::NonMacroAttr(..)
| Res::Err => None,
}
Expand Down Expand Up @@ -869,6 +877,7 @@ impl<Id> Res<Id> {
Res::Local(..) => "local variable",
Res::SelfTyParam { .. } | Res::SelfTyAlias { .. } => "self type",
Res::ToolMod => "tool module",
Res::OpenMod(..) => "namespaced crate",
Res::NonMacroAttr(attr_kind) => attr_kind.descr(),
Res::Err => "unresolved item",
}
Expand All @@ -895,6 +904,7 @@ impl<Id> Res<Id> {
Res::SelfTyAlias { alias_to, is_trait_impl }
}
Res::ToolMod => Res::ToolMod,
Res::OpenMod(sym) => Res::OpenMod(sym),
Res::NonMacroAttr(attr_kind) => Res::NonMacroAttr(attr_kind),
Res::Err => Res::Err,
}
Expand All @@ -911,6 +921,7 @@ impl<Id> Res<Id> {
Res::SelfTyAlias { alias_to, is_trait_impl }
}
Res::ToolMod => Res::ToolMod,
Res::OpenMod(sym) => Res::OpenMod(sym),
Res::NonMacroAttr(attr_kind) => Res::NonMacroAttr(attr_kind),
Res::Err => Res::Err,
})
Expand All @@ -936,9 +947,11 @@ impl<Id> Res<Id> {
pub fn ns(&self) -> Option<Namespace> {
match self {
Res::Def(kind, ..) => kind.ns(),
Res::PrimTy(..) | Res::SelfTyParam { .. } | Res::SelfTyAlias { .. } | Res::ToolMod => {
Some(Namespace::TypeNS)
}
Res::PrimTy(..)
| Res::SelfTyParam { .. }
| Res::SelfTyAlias { .. }
| Res::ToolMod
| Res::OpenMod(..) => Some(Namespace::TypeNS),
Res::SelfCtor(..) | Res::Local(..) => Some(Namespace::ValueNS),
Res::NonMacroAttr(..) => Some(Namespace::MacroNS),
Res::Err => None,
Expand Down
1 change: 1 addition & 0 deletions compiler/rustc_hir_analysis/src/hir_ty_lowering/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -2830,6 +2830,7 @@ impl<'tcx> dyn HirTyLowerer<'tcx> + '_ {
| Res::SelfCtor(_)
| Res::Local(_)
| Res::ToolMod
| Res::OpenMod(..)
| Res::NonMacroAttr(_)
| Res::Err) => Const::new_error_with_message(
tcx,
Expand Down
4 changes: 2 additions & 2 deletions compiler/rustc_hir_typeck/src/loops.rs
Original file line number Diff line number Diff line change
Expand Up @@ -207,7 +207,7 @@ impl<'hir> Visitor<'hir> for CheckLoopVisitor<'hir> {
};

// A `#[const_continue]` must break to a block in a `#[loop_match]`.
if find_attr!(self.tcx.hir_attrs(e.hir_id), ConstContinue(_)) {
if find_attr!(self.tcx, e.hir_id, ConstContinue(_)) {
let Some(label) = break_destination.label else {
let span = e.span;
self.tcx.dcx().emit_fatal(ConstContinueBadLabel { span });
Expand Down Expand Up @@ -420,7 +420,7 @@ impl<'hir> CheckLoopVisitor<'hir> {
e: &'hir hir::Expr<'hir>,
body: &'hir hir::Block<'hir>,
) -> Option<Destination> {
if !find_attr!(self.tcx.hir_attrs(e.hir_id), LoopMatch(_)) {
if !find_attr!(self.tcx, e.hir_id, LoopMatch(_)) {
return None;
}

Expand Down
2 changes: 1 addition & 1 deletion compiler/rustc_interface/src/proc_macro_decls.rs
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@ fn proc_macro_decls_static(tcx: TyCtxt<'_>, (): ()) -> Option<LocalDefId> {
let mut decls = None;

for id in tcx.hir_free_items() {
if find_attr!(tcx.hir_attrs(id.hir_id()), RustcProcMacroDecls) {
if find_attr!(tcx, id.hir_id(), RustcProcMacroDecls) {
decls = Some(id.owner_id.def_id);
}
}
Expand Down
63 changes: 40 additions & 23 deletions compiler/rustc_middle/src/dep_graph/graph.rs
Original file line number Diff line number Diff line change
Expand Up @@ -164,9 +164,10 @@ impl DepGraph {
);
assert_eq!(red_node_index, DepNodeIndex::FOREVER_RED_NODE);
if prev_graph_node_count > 0 {
colors.insert_red(SerializedDepNodeIndex::from_u32(
DepNodeIndex::FOREVER_RED_NODE.as_u32(),
));
let prev_index =
const { SerializedDepNodeIndex::from_u32(DepNodeIndex::FOREVER_RED_NODE.as_u32()) };
let result = colors.try_set_color(prev_index, DesiredColor::Red);
assert_matches!(result, TrySetColorResult::Success);
}

DepGraph {
Expand Down Expand Up @@ -1415,28 +1416,29 @@ impl DepNodeColorMap {
if value <= DepNodeIndex::MAX_AS_U32 { Some(DepNodeIndex::from_u32(value)) } else { None }
}

/// This tries to atomically mark a node green and assign `index` as the new
/// index if `green` is true, otherwise it will try to atomicaly mark it red.
/// Atomically sets the color of a previous-session dep node to either green
/// or red, if it has not already been colored.
///
/// This returns `Ok` if `index` gets assigned or the node is marked red, otherwise it returns
/// the already allocated index in `Err` if it is green already. If it was already
/// red, `Err(None)` is returned.
/// If the node already has a color, the new color is ignored, and the
/// return value indicates the existing color.
#[inline(always)]
pub(super) fn try_mark(
pub(super) fn try_set_color(
&self,
prev_index: SerializedDepNodeIndex,
index: DepNodeIndex,
green: bool,
) -> Result<(), Option<DepNodeIndex>> {
let value = &self.values[prev_index];
match value.compare_exchange(
color: DesiredColor,
) -> TrySetColorResult {
match self.values[prev_index].compare_exchange(
COMPRESSED_UNKNOWN,
if green { index.as_u32() } else { COMPRESSED_RED },
match color {
DesiredColor::Red => COMPRESSED_RED,
DesiredColor::Green { index } => index.as_u32(),
},
Ordering::Relaxed,
Ordering::Relaxed,
) {
Ok(_) => Ok(()),
Err(v) => Err(if v == COMPRESSED_RED { None } else { Some(DepNodeIndex::from_u32(v)) }),
Ok(_) => TrySetColorResult::Success,
Err(COMPRESSED_RED) => TrySetColorResult::AlreadyRed,
Err(index) => TrySetColorResult::AlreadyGreen { index: DepNodeIndex::from_u32(index) },
}
}

Expand All @@ -1454,13 +1456,28 @@ impl DepNodeColorMap {
DepNodeColor::Unknown
}
}
}

#[inline]
pub(super) fn insert_red(&self, index: SerializedDepNodeIndex) {
let value = self.values[index].swap(COMPRESSED_RED, Ordering::Release);
// Sanity check for duplicate nodes
assert_eq!(value, COMPRESSED_UNKNOWN, "tried to color an already colored node as red");
}
/// The color that [`DepNodeColorMap::try_set_color`] should try to apply to a node.
#[derive(Clone, Copy, Debug)]
pub(super) enum DesiredColor {
/// Try to mark the node red.
Red,
/// Try to mark the node green, associating it with a current-session node index.
Green { index: DepNodeIndex },
}

/// Return value of [`DepNodeColorMap::try_set_color`], indicating success or failure,
/// and (on failure) what the existing color is.
#[derive(Clone, Copy, Debug)]
pub(super) enum TrySetColorResult {
/// The [`DesiredColor`] was freshly applied to the node.
Success,
/// Coloring failed because the node was already marked red.
AlreadyRed,
/// Coloring failed because the node was already marked green,
/// and corresponds to node `index` in the current-session dep graph.
AlreadyGreen { index: DepNodeIndex },
}

#[inline(never)]
Expand Down
25 changes: 14 additions & 11 deletions compiler/rustc_middle/src/dep_graph/serialized.rs
Original file line number Diff line number Diff line change
Expand Up @@ -58,7 +58,7 @@ use rustc_serialize::{Decodable, Decoder, Encodable, Encoder};
use rustc_session::Session;
use tracing::{debug, instrument};

use super::graph::{CurrentDepGraph, DepNodeColorMap};
use super::graph::{CurrentDepGraph, DepNodeColorMap, DesiredColor, TrySetColorResult};
use super::retained::RetainedDepGraph;
use super::{DepKind, DepNode, DepNodeIndex};
use crate::dep_graph::edges::EdgesVec;
Expand Down Expand Up @@ -905,13 +905,14 @@ impl GraphEncoder {
let mut local = self.status.local.borrow_mut();

let index = self.status.next_index(&mut *local);
let color = if is_green { DesiredColor::Green { index } } else { DesiredColor::Red };

// Use `try_mark` to avoid racing when `send_promoted` is called concurrently
// Use `try_set_color` to avoid racing when `send_promoted` is called concurrently
// on the same index.
match colors.try_mark(prev_index, index, is_green) {
Ok(()) => (),
Err(None) => panic!("dep node {:?} is unexpectedly red", prev_index),
Err(Some(dep_node_index)) => return dep_node_index,
match colors.try_set_color(prev_index, color) {
TrySetColorResult::Success => {}
TrySetColorResult::AlreadyRed => panic!("dep node {prev_index:?} is unexpectedly red"),
TrySetColorResult::AlreadyGreen { index } => return index,
}

self.status.bump_index(&mut *local);
Expand All @@ -923,7 +924,8 @@ impl GraphEncoder {
/// from the previous dep graph and expects all edges to already have a new dep node index
/// assigned.
///
/// This will also ensure the dep node is marked green if `Some` is returned.
/// Tries to mark the dep node green, and returns Some if it is now green,
/// or None if had already been concurrently marked red.
#[inline]
pub(crate) fn send_promoted(
&self,
Expand All @@ -935,10 +937,10 @@ impl GraphEncoder {
let mut local = self.status.local.borrow_mut();
let index = self.status.next_index(&mut *local);

// Use `try_mark_green` to avoid racing when `send_promoted` or `send_and_color`
// Use `try_set_color` to avoid racing when `send_promoted` or `send_and_color`
// is called concurrently on the same index.
match colors.try_mark(prev_index, index, true) {
Ok(()) => {
match colors.try_set_color(prev_index, DesiredColor::Green { index }) {
TrySetColorResult::Success => {
self.status.bump_index(&mut *local);
self.status.encode_promoted_node(
index,
Expand All @@ -949,7 +951,8 @@ impl GraphEncoder {
);
Some(index)
}
Err(dep_node_index) => dep_node_index,
TrySetColorResult::AlreadyRed => None,
TrySetColorResult::AlreadyGreen { index } => Some(index),
}
}

Expand Down
30 changes: 30 additions & 0 deletions compiler/rustc_middle/src/ty/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -2172,6 +2172,36 @@ impl<'tcx> TyCtxt<'tcx> {
}
}

// `HasAttrs` impls: allow `find_attr!(tcx, id, ...)` to work with both DefId-like types and HirId.

impl<'tcx> hir::attrs::HasAttrs<'tcx, TyCtxt<'tcx>> for DefId {
fn get_attrs(self, tcx: &TyCtxt<'tcx>) -> &'tcx [hir::Attribute] {
if let Some(did) = self.as_local() {
tcx.hir_attrs(tcx.local_def_id_to_hir_id(did))
} else {
tcx.attrs_for_def(self)
}
}
}

impl<'tcx> hir::attrs::HasAttrs<'tcx, TyCtxt<'tcx>> for LocalDefId {
fn get_attrs(self, tcx: &TyCtxt<'tcx>) -> &'tcx [hir::Attribute] {
tcx.hir_attrs(tcx.local_def_id_to_hir_id(self))
}
}

impl<'tcx> hir::attrs::HasAttrs<'tcx, TyCtxt<'tcx>> for hir::OwnerId {
fn get_attrs(self, tcx: &TyCtxt<'tcx>) -> &'tcx [hir::Attribute] {
hir::attrs::HasAttrs::get_attrs(self.def_id, tcx)
}
}

impl<'tcx> hir::attrs::HasAttrs<'tcx, TyCtxt<'tcx>> for hir::HirId {
fn get_attrs(self, tcx: &TyCtxt<'tcx>) -> &'tcx [hir::Attribute] {
tcx.hir_attrs(self)
}
}

pub fn provide(providers: &mut Providers) {
closure::provide(providers);
context::provide(providers);
Expand Down
2 changes: 1 addition & 1 deletion compiler/rustc_mir_build/src/builder/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -491,7 +491,7 @@ fn construct_fn<'tcx>(
};

if let Some((dialect, phase)) =
find_attr!(tcx.hir_attrs(fn_id), CustomMir(dialect, phase, _) => (dialect, phase))
find_attr!(tcx, fn_id, CustomMir(dialect, phase, _) => (dialect, phase))
{
return custom::build_custom_mir(
tcx,
Expand Down
4 changes: 2 additions & 2 deletions compiler/rustc_mir_build/src/thir/cx/expr.rs
Original file line number Diff line number Diff line change
Expand Up @@ -917,7 +917,7 @@ impl<'tcx> ThirBuildCx<'tcx> {
hir::ExprKind::Ret(v) => ExprKind::Return { value: v.map(|v| self.mirror_expr(v)) },
hir::ExprKind::Become(call) => ExprKind::Become { value: self.mirror_expr(call) },
hir::ExprKind::Break(dest, ref value) => {
if find_attr!(self.tcx.hir_attrs(expr.hir_id), ConstContinue(_)) {
if find_attr!(self.tcx, expr.hir_id, ConstContinue(_)) {
match dest.target_id {
Ok(target_id) => {
let (Some(value), Some(_)) = (value, dest.label) else {
Expand Down Expand Up @@ -982,7 +982,7 @@ impl<'tcx> ThirBuildCx<'tcx> {
match_source,
},
hir::ExprKind::Loop(body, ..) => {
if find_attr!(self.tcx.hir_attrs(expr.hir_id), LoopMatch(_)) {
if find_attr!(self.tcx, expr.hir_id, LoopMatch(_)) {
let dcx = self.tcx.dcx();

// Accept either `state = expr` or `state = expr;`.
Expand Down
Loading
Loading