Skip to content
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
19 commits
Select commit Hold shift + click to select a range
751b7d5
Build: Add `stdenv.cc.cc.lib` to Nix dependencies
PaulDance May 16, 2025
ae4fd17
Streamline query modifier macros.
nnethercote Feb 17, 2026
eefb116
Reindent `define_callbacks` and `define_feedable`.
nnethercote Feb 17, 2026
5142af7
Remove `$attr` from `QueryArenas`/`QueryCaches`.
nnethercote Feb 18, 2026
bc1b6b8
Reduce `$K` and `$V` usage in query macros.
nnethercote Feb 19, 2026
eb2d00a
Stabilize `cfg_select`
folkertdev Feb 7, 2026
3f1dc9e
Try harder to evaluate constants.
cjgillot Nov 6, 2025
a170c11
Constants of primitive types are always deterministic.
cjgillot Nov 6, 2025
d35719b
Bless incremental.
cjgillot Nov 28, 2025
4712cc3
Move methods to gvn.rs.
cjgillot Dec 16, 2025
b0986e9
Use may_have_provenance.
cjgillot Jan 10, 2026
46ccd82
Fix bad key names in a couple of queries.
nnethercote Feb 20, 2026
cb08314
Remove explicit `tcx` bindings from query `desc`s.
nnethercote Feb 20, 2026
ecb778f
Remove explicit `tcx` bindings from `query` entries.
nnethercote Feb 20, 2026
5951515
Rollup merge of #149366 - cjgillot:gvn-primitive, r=RalfJung
JonathanBrouwer Feb 22, 2026
0fa27ff
Rollup merge of #152779 - nnethercote:clarify-aspects-of-query-macros…
JonathanBrouwer Feb 22, 2026
1c4c353
Rollup merge of #152958 - nnethercote:rustc_queries-fixes, r=oli-obk
JonathanBrouwer Feb 22, 2026
b014cb8
Rollup merge of #149783 - folkertdev:stabilize-cfg-select, r=Jonathan…
JonathanBrouwer Feb 22, 2026
807a5c8
Rollup merge of #152708 - PaulDance:patches/nix-stdenv.cc.cc.lib, r=c…
JonathanBrouwer Feb 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
22 changes: 8 additions & 14 deletions compiler/rustc_attr_parsing/src/attributes/cfg_select.rs
Original file line number Diff line number Diff line change
Expand Up @@ -128,20 +128,14 @@ pub fn parse_cfg_select(
}
}

if let Some(features) = features
&& features.enabled(sym::cfg_select)
{
let it = branches
.reachable
.iter()
.map(|(entry, _, _)| CfgSelectPredicate::Cfg(entry.clone()))
.chain(branches.wildcard.as_ref().map(|(t, _, _)| CfgSelectPredicate::Wildcard(*t)))
.chain(
branches.unreachable.iter().map(|(entry, _, _)| CfgSelectPredicate::clone(entry)),
);

lint_unreachable(p, it, lint_node_id);
}
let it = branches
.reachable
.iter()
.map(|(entry, _, _)| CfgSelectPredicate::Cfg(entry.clone()))
.chain(branches.wildcard.as_ref().map(|(t, _, _)| CfgSelectPredicate::Wildcard(*t)))
.chain(branches.unreachable.iter().map(|(entry, _, _)| CfgSelectPredicate::clone(entry)));

lint_unreachable(p, it, lint_node_id);

Ok(branches)
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -17,8 +17,8 @@ index 1e336bf..35e6f54 100644
@@ -2,4 +2,3 @@
// tidy-alphabetical-start
-#![cfg_attr(target_has_atomic = "128", feature(integer_atomics))]
#![cfg_attr(test, feature(cfg_select))]
#![feature(array_ptr_get)]
#![feature(array_try_from_fn)]
diff --git a/coretests/tests/atomic.rs b/coretests/tests/atomic.rs
index b735957..ea728b6 100644
--- a/coretests/tests/atomic.rs
Expand Down
2 changes: 1 addition & 1 deletion compiler/rustc_data_structures/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -11,14 +11,14 @@
#![allow(rustc::default_hash_types)]
#![allow(rustc::potential_query_instability)]
#![cfg_attr(bootstrap, feature(assert_matches))]
#![cfg_attr(bootstrap, feature(cfg_select))]
#![cfg_attr(bootstrap, feature(cold_path))]
#![cfg_attr(test, feature(test))]
#![deny(unsafe_op_in_unsafe_fn)]
#![feature(allocator_api)]
#![feature(ascii_char)]
#![feature(ascii_char_variants)]
#![feature(auto_traits)]
#![feature(cfg_select)]
#![feature(const_default)]
#![feature(const_trait_impl)]
#![feature(dropck_eyepatch)]
Expand Down
2 changes: 2 additions & 0 deletions compiler/rustc_feature/src/accepted.rs
Original file line number Diff line number Diff line change
Expand Up @@ -102,6 +102,8 @@ declare_features! (
(accepted, cfg_doctest, "1.40.0", Some(62210)),
/// Enables `#[cfg(panic = "...")]` config key.
(accepted, cfg_panic, "1.60.0", Some(77443)),
/// Provides a native way to easily manage multiple conditional flags without having to rewrite each clause multiple times.
(accepted, cfg_select, "CURRENT_RUSTC_VERSION", Some(115585)),
/// Allows `cfg(target_abi = "...")`.
(accepted, cfg_target_abi, "1.78.0", Some(80970)),
/// Allows `cfg(target_feature = "...")`.
Expand Down
2 changes: 0 additions & 2 deletions compiler/rustc_feature/src/unstable.rs
Original file line number Diff line number Diff line change
Expand Up @@ -388,8 +388,6 @@ declare_features! (
(unstable, cfg_sanitize, "1.41.0", Some(39699)),
/// Allows `cfg(sanitizer_cfi_generalize_pointers)` and `cfg(sanitizer_cfi_normalize_integers)`.
(unstable, cfg_sanitizer_cfi, "1.77.0", Some(89653)),
/// Provides a native way to easily manage multiple conditional flags without having to rewrite each clause multiple times.
(unstable, cfg_select, "CURRENT_RUSTC_VERSION", Some(115585)),
/// Allows `cfg(target(abi = "..."))`.
(unstable, cfg_target_compact, "1.63.0", Some(96901)),
/// Allows `cfg(target_has_atomic_load_store = "...")`.
Expand Down
2 changes: 0 additions & 2 deletions compiler/rustc_lint_defs/src/builtin.rs
Original file line number Diff line number Diff line change
Expand Up @@ -864,7 +864,6 @@ declare_lint! {
/// ### Example
///
/// ```rust
/// #![feature(cfg_select)]
/// cfg_select! {
/// _ => (),
/// windows => (),
Expand All @@ -882,7 +881,6 @@ declare_lint! {
pub UNREACHABLE_CFG_SELECT_PREDICATES,
Warn,
"detects unreachable configuration predicates in the cfg_select macro",
@feature_gate = cfg_select;
}

declare_lint! {
Expand Down
45 changes: 12 additions & 33 deletions compiler/rustc_macros/src/query.rs
Original file line number Diff line number Diff line change
Expand Up @@ -103,13 +103,11 @@ impl<T: Parse> Parse for List<T> {

struct Desc {
modifier: Ident,
tcx_binding: Option<Ident>,
expr_list: Punctuated<Expr, Token![,]>,
}

struct CacheOnDiskIf {
modifier: Ident,
tcx_binding: Option<Pat>,
block: Block,
}

Expand Down Expand Up @@ -192,35 +190,16 @@ fn parse_query_modifiers(input: ParseStream<'_>) -> Result<QueryModifiers> {

if modifier == "desc" {
// Parse a description modifier like:
// `desc { |tcx| "foo {}", tcx.item_path(key) }`
// `desc { "foo {}", tcx.item_path(key) }`
let attr_content;
braced!(attr_content in input);
let tcx_binding = if attr_content.peek(Token![|]) {
attr_content.parse::<Token![|]>()?;
let tcx = attr_content.parse()?;
attr_content.parse::<Token![|]>()?;
Some(tcx)
} else {
None
};
let expr_list = attr_content.parse_terminated(Expr::parse, Token![,])?;
try_insert!(desc = Desc { modifier, tcx_binding, expr_list });
try_insert!(desc = Desc { modifier, expr_list });
} else if modifier == "cache_on_disk_if" {
// Parse a cache-on-disk modifier like:
//
// `cache_on_disk_if { true }`
// `cache_on_disk_if { key.is_local() }`
// `cache_on_disk_if(tcx) { tcx.is_typeck_child(key.to_def_id()) }`
let tcx_binding = if input.peek(token::Paren) {
let args;
parenthesized!(args in input);
let tcx = Pat::parse_single(&args)?;
Some(tcx)
} else {
None
};
// `cache_on_disk_if { tcx.is_typeck_child(key.to_def_id()) }`
let block = input.parse()?;
try_insert!(cache_on_disk_if = CacheOnDiskIf { modifier, tcx_binding, block });
try_insert!(cache_on_disk_if = CacheOnDiskIf { modifier, block });
} else if modifier == "arena_cache" {
try_insert!(arena_cache = modifier);
} else if modifier == "cycle_fatal" {
Expand Down Expand Up @@ -313,24 +292,24 @@ fn make_helpers_for_query(query: &Query, streams: &mut HelperTokenStreams) {
erased_name.set_span(Span::call_site());

// Generate a function to check whether we should cache the query to disk, for some key.
if let Some(CacheOnDiskIf { tcx_binding, block, .. }) = modifiers.cache_on_disk_if.as_ref() {
let tcx = tcx_binding.as_ref().map(|t| quote! { #t }).unwrap_or_else(|| quote! { _ });
// we're taking `key` by reference, but some rustc types usually prefer being passed by value
if let Some(CacheOnDiskIf { block, .. }) = modifiers.cache_on_disk_if.as_ref() {
// `pass_by_value`: some keys are marked with `rustc_pass_by_value`, but we take keys by
// reference here.
// FIXME: `pass_by_value` is badly named; `allow(rustc::pass_by_value)` actually means
// "allow pass by reference of `rustc_pass_by_value` types".
streams.cache_on_disk_if_fns_stream.extend(quote! {
#[allow(unused_variables, rustc::pass_by_value)]
#[inline]
pub fn #erased_name<'tcx>(#tcx: TyCtxt<'tcx>, #key_pat: &crate::queries::#name::Key<'tcx>) -> bool
pub fn #erased_name<'tcx>(tcx: TyCtxt<'tcx>, #key_pat: &#key_ty) -> bool
#block
});
}

let Desc { tcx_binding, expr_list, .. } = &modifiers.desc;
let tcx = tcx_binding.as_ref().map_or_else(|| quote! { _ }, |t| quote! { #t });
let Desc { expr_list, .. } = &modifiers.desc;

let desc = quote! {
#[allow(unused_variables)]
pub fn #erased_name<'tcx>(tcx: TyCtxt<'tcx>, key: #key_ty) -> String {
let (#tcx, #key_pat) = (tcx, key);
pub fn #erased_name<'tcx>(tcx: TyCtxt<'tcx>, #key_pat: #key_ty) -> String {
format!(#expr_list)
}
};
Expand Down
21 changes: 11 additions & 10 deletions compiler/rustc_middle/src/dep_graph/dep_node.rs
Original file line number Diff line number Diff line change
Expand Up @@ -324,11 +324,12 @@ impl StableOrd for WorkProductId {
const THIS_IMPLEMENTATION_HAS_BEEN_TRIPLE_CHECKED: () = ();
}

// Note: `$K` and `$V` are unused but present so this can be called by `rustc_with_all_queries`.
macro_rules! define_dep_nodes {
(
$(
$(#[$attr:meta])*
[$($modifiers:tt)*] fn $variant:ident($($K:tt)*) -> $V:ty,
[$($modifiers:tt)*] fn $variant:ident($K:ty) -> $V:ty,
)*
) => {

Expand Down Expand Up @@ -382,20 +383,20 @@ macro_rules! define_dep_nodes {
}

// Create various data structures for each query, and also for a few things
// that aren't queries.
// that aren't queries. The key and return types aren't used, hence the use of `()`.
rustc_with_all_queries!(define_dep_nodes![
/// We use this for most things when incr. comp. is turned off.
[] fn Null() -> (),
[] fn Null(()) -> (),
/// We use this to create a forever-red node.
[] fn Red() -> (),
[] fn Red(()) -> (),
/// We use this to create a side effect node.
[] fn SideEffect() -> (),
[] fn SideEffect(()) -> (),
/// We use this to create the anon node with zero dependencies.
[] fn AnonZeroDeps() -> (),
[] fn TraitSelect() -> (),
[] fn CompileCodegenUnit() -> (),
[] fn CompileMonoItem() -> (),
[] fn Metadata() -> (),
[] fn AnonZeroDeps(()) -> (),
[] fn TraitSelect(()) -> (),
[] fn CompileCodegenUnit(()) -> (),
[] fn CompileMonoItem(()) -> (),
[] fn Metadata(()) -> (),
]);

// WARNING: `construct` is generic and does not know that `CompileCodegenUnit` takes `Symbol`s as keys.
Expand Down
53 changes: 0 additions & 53 deletions compiler/rustc_middle/src/mir/consts.rs
Original file line number Diff line number Diff line change
Expand Up @@ -181,26 +181,6 @@ impl ConstValue {
Some(data.inner().inspect_with_uninit_and_ptr_outside_interpreter(start..end))
}

/// Check if a constant may contain provenance information. This is used by MIR opts.
/// Can return `true` even if there is no provenance.
pub fn may_have_provenance(&self, tcx: TyCtxt<'_>, size: Size) -> bool {
match *self {
ConstValue::ZeroSized | ConstValue::Scalar(Scalar::Int(_)) => return false,
ConstValue::Scalar(Scalar::Ptr(..)) => return true,
// It's hard to find out the part of the allocation we point to;
// just conservatively check everything.
ConstValue::Slice { alloc_id, meta: _ } => {
!tcx.global_alloc(alloc_id).unwrap_memory().inner().provenance().ptrs().is_empty()
}
ConstValue::Indirect { alloc_id, offset } => !tcx
.global_alloc(alloc_id)
.unwrap_memory()
.inner()
.provenance()
.range_empty(AllocRange::from(offset..offset + size), &tcx),
}
}

/// Check if a constant only contains uninitialized bytes.
pub fn all_bytes_uninit(&self, tcx: TyCtxt<'_>) -> bool {
let ConstValue::Indirect { alloc_id, .. } = self else {
Expand Down Expand Up @@ -474,39 +454,6 @@ impl<'tcx> Const<'tcx> {
let val = ConstValue::Scalar(s);
Self::Val(val, ty)
}

/// Return true if any evaluation of this constant always returns the same value,
/// taking into account even pointer identity tests.
pub fn is_deterministic(&self) -> bool {
// Some constants may generate fresh allocations for pointers they contain,
// so using the same constant twice can yield two different results.
// Notably, valtrees purposefully generate new allocations.
match self {
Const::Ty(_, c) => match c.kind() {
ty::ConstKind::Param(..) => true,
// A valtree may be a reference. Valtree references correspond to a
// different allocation each time they are evaluated. Valtrees for primitive
// types are fine though.
ty::ConstKind::Value(cv) => cv.ty.is_primitive(),
ty::ConstKind::Unevaluated(..) | ty::ConstKind::Expr(..) => false,
// This can happen if evaluation of a constant failed. The result does not matter
// much since compilation is doomed.
ty::ConstKind::Error(..) => false,
// Should not appear in runtime MIR.
ty::ConstKind::Infer(..)
| ty::ConstKind::Bound(..)
| ty::ConstKind::Placeholder(..) => bug!(),
},
Const::Unevaluated(..) => false,
Const::Val(
ConstValue::Slice { .. }
| ConstValue::ZeroSized
| ConstValue::Scalar(_)
| ConstValue::Indirect { .. },
_,
) => true,
}
}
}

/// An unevaluated (potentially generic) constant used in MIR.
Expand Down
Loading
Loading