Skip to content
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
25 commits
Select commit Hold shift + click to select a range
84140cf
gate defaulted type consts with associated_type_defaults
LaneAsade Feb 8, 2026
751b7d5
Build: Add `stdenv.cc.cc.lib` to Nix dependencies
PaulDance May 16, 2025
7df7485
Add build.rustdoc option to bootstrap config
blkerby Feb 20, 2026
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
b7c28a8
Index expressions rendered the index: subexpression as the id, instea…
AlexCeleste Feb 21, 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
bde075b
Fix ICE when an associated type or const is wrongly marked as `final`
makai410 Feb 22, 2026
76d36b8
Rollup merge of #149366 - cjgillot:gvn-primitive, r=RalfJung
JonathanBrouwer Feb 22, 2026
dcba588
Rollup merge of #152779 - nnethercote:clarify-aspects-of-query-macros…
JonathanBrouwer Feb 22, 2026
1ed945a
Rollup merge of #152958 - nnethercote:rustc_queries-fixes, r=oli-obk
JonathanBrouwer Feb 22, 2026
60caefc
Rollup merge of #152385 - LaneAsade:gate-type-const-defaults, r=BoxyUwU
JonathanBrouwer Feb 22, 2026
4646f7b
Rollup merge of #152708 - PaulDance:patches/nix-stdenv.cc.cc.lib, r=c…
JonathanBrouwer Feb 22, 2026
8c5b8b1
Rollup merge of #152921 - blkerby:bootstrap-rustdoc-config, r=Kobzol
JonathanBrouwer Feb 22, 2026
c55577a
Rollup merge of #152926 - makai410:final-on-assoc-type, r=fmease
JonathanBrouwer Feb 22, 2026
63935ec
Rollup merge of #152927 - AlexCeleste:thir-missing-index-subexpressio…
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
5 changes: 5 additions & 0 deletions bootstrap.example.toml
Original file line number Diff line number Diff line change
Expand Up @@ -302,6 +302,11 @@
# If you set this, you likely want to set `cargo` as well.
#build.rustc = "/path/to/rustc"

# Use this rustdoc binary as the stage0 snapshot rustdoc.
# If unspecified, then the binary "rustdoc" (with platform-specific extension, e.g. ".exe")
# in the same directory as "rustc" will be used.
#build.rustdoc = "/path/to/rustdoc"

# Instead of downloading the src/stage0 version of rustfmt specified,
# use this rustfmt binary instead as the stage0 snapshot rustfmt.
#build.rustfmt = "/path/to/rustfmt"
Expand Down
15 changes: 12 additions & 3 deletions compiler/rustc_ast_lowering/src/item.rs
Original file line number Diff line number Diff line change
Expand Up @@ -1085,9 +1085,18 @@ impl<'hir> LoweringContext<'_, 'hir> {
}
};

let (defaultness, _) = self.lower_defaultness(i.kind.defaultness(), has_value, || {
hir::Defaultness::Default { has_value }
});
let defaultness = match i.kind.defaultness() {
// We do not yet support `final` on trait associated items other than functions.
// Even though we reject `final` on non-functions during AST validation, we still
// need to stop propagating it here because later compiler passes do not expect
// and cannot handle such items.
Defaultness::Final(..) if !matches!(i.kind, AssocItemKind::Fn(..)) => {
Defaultness::Implicit
}
defaultness => defaultness,
};
let (defaultness, _) = self
.lower_defaultness(defaultness, has_value, || hir::Defaultness::Default { has_value });

let item = hir::TraitItem {
owner_id: trait_item_def_id,
Expand Down
13 changes: 12 additions & 1 deletion compiler/rustc_ast_passes/src/feature_gate.rs
Original file line number Diff line number Diff line change
Expand Up @@ -427,7 +427,7 @@ impl<'a> Visitor<'a> for PostExpansionVisitor<'a> {
false
}
ast::AssocItemKind::Const(box ast::ConstItem {
rhs_kind: ast::ConstItemRhsKind::TypeConst { .. },
rhs_kind: ast::ConstItemRhsKind::TypeConst { rhs },
..
}) => {
// Make sure this is only allowed if the feature gate is enabled.
Expand All @@ -438,6 +438,17 @@ impl<'a> Visitor<'a> for PostExpansionVisitor<'a> {
i.span,
"associated `type const` are unstable"
);
// Make sure associated `type const` defaults in traits are only allowed
// if the feature gate is enabled.
// #![feature(associated_type_defaults)]
if ctxt == AssocCtxt::Trait && rhs.is_some() {
gate!(
&self,
associated_type_defaults,
i.span,
"associated type defaults are unstable"
);
}
false
}
_ => false,
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