Skip to content
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
39 commits
Select commit Hold shift + click to select a range
2cc26bf
Remove rustc_legacy_const_generics from LoongArch64 SIMD
heiher Sep 9, 2026
9da2dbd
Stabilize LoongArch64 SIMD intrinsics
heiher Sep 9, 2026
a4aac2f
Use "latest" symlink for icx path
adamgemmell Oct 19, 2026
1077a78
Remove use of is_powerpc64_feature_detected
adamgemmell Oct 22, 2026
8bee029
Don't let riscv32gc-unknown-linux-gnu (tier 3) block CI on failure
adamgemmell Oct 22, 2026
2a66a81
Merge pull request #2259 from adamgemmell/dev/adagem01/icx-ver-bump
folkertdev Oct 22, 2026
3c5eefd
Merge pull request #2221 from heiher/stabilize-loong64-simd
folkertdev Oct 22, 2026
192c29c
perf: emit field names as a concatenated string in derive(Debug) for …
panstromek Oct 22, 2026
bea7af9
Add test for debug output for big struct
panstromek Oct 22, 2026
194a9a5
Use string contatenation strategy for fieldN helpers as well
panstromek Oct 22, 2026
db15c6a
Concat struct name together with field names
panstromek Oct 22, 2026
b540852
doc: cleanup comment
panstromek Oct 23, 2026
f3f485e
doc: cleanup comment
panstromek Oct 23, 2026
635700c
perf: shrink unnecessary capacity
panstromek Oct 23, 2026
9e5308c
ref: use thin_vec! macro avoid managing the capacity manually
panstromek Oct 23, 2026
9e32779
perf: avoid allocating more capacity for tuples
panstromek Oct 23, 2026
88f395a
perf: reduce unnecessary capacity
panstromek Oct 23, 2026
4526f83
cln: remove args_per_field, it's now always 1 in place where it gets …
panstromek Oct 23, 2026
9dcaa68
ref: rename
panstromek Oct 23, 2026
b99c49b
perf: avoid allocating expression for name for cases where it's not used
panstromek Oct 23, 2026
3cd9cd0
test: bless macro stats test
panstromek Oct 26, 2026
4719ede
ref: put names before field values in debug helpers
panstromek Oct 25, 2026
5221654
Move lang item collection to the resolver
oli-obk Jul 9, 2026
e360750
Instantiate a response in pieces
nnethercote Oct 9, 2026
78a5d5e
Optimize `unify_query_var_values`
nnethercote Oct 9, 2026
8eb0c38
Special-case canonical bound vars in `unify_query_var_values`
nnethercote Oct 9, 2026
eb07e9d
Introduce `IsIdentity` type
nnethercote Oct 12, 2026
7242cbe
Add an early return to `instantiate_and_apply_query_response`
nnethercote Oct 12, 2026
474c761
Introduce `Canonicalized` and other clarifications
nnethercote Oct 14, 2026
a95082d
Prepare for merging from rust-lang/rust
invalid-email-address Oct 27, 2026
cf5da2b
Merge ref '16d1ffac17ad' from rust-lang/rust
invalid-email-address Oct 27, 2026
ed7d26d
Run `cargo fmt`
invalid-email-address Oct 27, 2026
6574cf3
Merge pull request #2246 from rust-lang/rustc-pull
tgross35 Oct 27, 2026
ac07049
Avoid stdlib's `impl Hash for Discriminant` for stable hashing
Zalathar Oct 26, 2026
0674501
Rollup merge of #165032 - folkertdev:stdarch-sync-2026-10-27, r=folke…
JonathanBrouwer Oct 27, 2026
054f842
Rollup merge of #163525 - oli-obk:resolver_lang_items, r=petrochenkov
JonathanBrouwer Oct 27, 2026
638ee0b
Rollup merge of #164234 - nnethercote:diesel-opts-2, r=lcnr
JonathanBrouwer Oct 27, 2026
00cb532
Rollup merge of #164726 - panstromek:debug-concat-more, r=nnethercote
JonathanBrouwer Oct 27, 2026
e4e2027
Rollup merge of #164953 - Zalathar:discriminant, r=oli-obk
JonathanBrouwer Oct 27, 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
3 changes: 2 additions & 1 deletion Cargo.lock
Original file line number Diff line number Diff line change
Expand Up @@ -4661,7 +4661,6 @@ dependencies = [
"rustc_ast_lowering",
"rustc_attr_ir",
"rustc_attr_parsing",
"rustc_crate_store",
"rustc_data_structures",
"rustc_errors",
"rustc_feature",
Expand Down Expand Up @@ -4786,6 +4785,7 @@ dependencies = [
"rustc_ast_pretty",
"rustc_attr_ir",
"rustc_attr_parsing",
"rustc_crate_store",
"rustc_data_structures",
"rustc_errors",
"rustc_expand",
Expand Down Expand Up @@ -4905,6 +4905,7 @@ dependencies = [
"rustc_data_structures",
"rustc_hashes",
"rustc_hir",
"rustc_macros",
"rustc_middle",
"rustc_session",
"rustc_span",
Expand Down
82 changes: 46 additions & 36 deletions compiler/rustc_builtin_macros/src/deriving/debug.rs
Original file line number Diff line number Diff line change
Expand Up @@ -75,26 +75,26 @@ fn show_substructure(
_ => cx.dcx().span_bug(span, "unexpected substructure in `derive(Debug)`"),
};

let name = cx.expr_str(span, ident.name);
let expr_name = || cx.expr_str(span, ident.name);
let fmt = cx.expr_name(span, sym::f);

// Fieldless enums have been special-cased earlier
if fmt_detail == FmtDebug::Shallow {
let fn_path_write_str = cx.std_path(span, &[sym::fmt, sym::Formatter, sym::write_str]);
let expr = cx.expr_call_global(span, fn_path_write_str, thin_vec![fmt, name]);
let expr = cx.expr_call_global(span, fn_path_write_str, thin_vec![fmt, expr_name()]);
return BlockOrExpr::new_expr(expr);
}

// Struct and tuples are similar enough that we use the same code for both,
// with some extra pieces for structs due to the field names.
let (is_struct, args_per_field) = match vdata {
let is_struct = match vdata {
ast::VariantData::Unit(..) => {
// Special fast path for unit variants.
assert!(fields.is_empty());
(false, 0)
false
}
ast::VariantData::Tuple(..) => (false, 1),
ast::VariantData::Struct { .. } => (true, 2),
ast::VariantData::Tuple(..) => false,
ast::VariantData::Struct { .. } => true,
};

// The number of fields that can be handled without an array.
Expand All @@ -114,7 +114,7 @@ fn show_substructure(
if fields.is_empty() {
// Special case for no fields.
let fn_path_write_str = cx.std_path(span, &[sym::fmt, sym::Formatter, sym::write_str]);
let expr = cx.expr_call_global(span, fn_path_write_str, thin_vec![fmt, name]);
let expr = cx.expr_call_global(span, fn_path_write_str, thin_vec![fmt, expr_name()]);
BlockOrExpr::new_expr(expr)
} else if fields.len() <= CUTOFF {
// Few enough fields that we can use a specific-length method.
Expand All @@ -125,44 +125,54 @@ fn show_substructure(
};
let fn_path_debug = cx.std_path(span, &[sym::fmt, sym::Formatter, Symbol::intern(&debug)]);

let mut args = ThinVec::with_capacity(2 + fields.len() * args_per_field);
args.extend([fmt, name]);
for (i, field) in fields.into_iter().enumerate() {
if is_struct {
let name = cx.expr_str(field.span, field.name.unwrap().name);
args.push(name);
let mut args = ThinVec::with_capacity(2 + fields.len());
args.extend([fmt]);

if is_struct {
let mut names = String::new();
names.push_str(ident.name.as_str());

for field in fields.iter() {
names.push(' ');
names.push_str(field.name.unwrap().name.as_str());
}

let name_expr = cx.expr_str(span, Symbol::intern(&names));
args.push(name_expr);
} else {
args.push(expr_name());
};

for (i, field) in fields.into_iter().enumerate() {
let field = expr_for_field(field, i);
args.push(field);
}
let expr = cx.expr_call_global(span, fn_path_debug, args);
BlockOrExpr::new_expr(expr)
} else {
// Enough fields that we must use the any-length method.
let mut name_exprs = ThinVec::with_capacity(fields.len());
let mut names = String::new();
if is_struct {
names.push_str(ident.name.as_str());
}
let mut value_exprs = ThinVec::with_capacity(fields.len());

for (i, field) in fields.into_iter().enumerate() {
if is_struct {
name_exprs.push(cx.expr_str(field.span, field.name.unwrap().name));
names.push(' ');
names.push_str(field.name.unwrap().name.as_str());
}

let field = expr_for_field(field, i);
value_exprs.push(field);
}

// `let names: &'static _ = &["field1", "field2"];`
// `let names: &'static _ = "StructName field1 field2"`
let names_let = is_struct.then(|| {
let lt_static = Some(cx.lifetime_static(span));
let ty_static_ref = cx.ty_ref(span, cx.ty_infer(span), lt_static, ast::Mutability::Not);
cx.stmt_let_ty(
span,
false,
sym::names,
Some(ty_static_ref),
cx.expr_array_ref(span, name_exprs),
)
let names_expr = cx.expr_str(span, Symbol::intern(&names));
cx.stmt_let_ty(span, false, sym::names, Some(ty_static_ref), names_expr)
});

// `let values: &[&dyn Debug] = &[&&self.field1, &&self.field2];`
Expand All @@ -186,7 +196,7 @@ fn show_substructure(
cx.expr_array_ref(span, value_exprs),
);

// `fmt::Formatter::debug_struct_fields_finish(fmt, name, names, values)` or
// `fmt::Formatter::debug_struct_fields_finish(fmt, names, values)` or
// `fmt::Formatter::debug_tuple_fields_finish(fmt, name, values)`
let sym_debug = if is_struct {
sym::debug_struct_fields_finish
Expand All @@ -195,20 +205,20 @@ fn show_substructure(
};
let fn_path_debug_internal = cx.std_path(span, &[sym::fmt, sym::Formatter, sym_debug]);

let mut args = ThinVec::with_capacity(4);
args.push(fmt);
args.push(name);
if is_struct {
args.push(cx.expr_name(span, sym::names));
}
args.push(cx.expr_name(span, sym::values));
let args = thin_vec![
fmt,
if is_struct { cx.expr_name(span, sym::names) } else { expr_name() },
cx.expr_name(span, sym::values)
];

let expr = cx.expr_call_global(span, fn_path_debug_internal, args);

let mut stmts = ThinVec::with_capacity(2);
if is_struct {
stmts.push(names_let.unwrap());
}
stmts.push(values_let);
let stmts = if is_struct {
thin_vec![names_let.unwrap(), values_let]
} else {
thin_vec![values_let]
};

BlockOrExpr::new_mixed(stmts, Some(expr))
}
}
Expand Down
36 changes: 26 additions & 10 deletions compiler/rustc_data_structures/src/stable_hash.rs
Original file line number Diff line number Diff line change
@@ -1,6 +1,5 @@
use std::hash::{BuildHasher, Hash, Hasher};
use std::marker::PhantomData;
use std::mem;
use std::num::NonZero;

use rustc_index::bit_set::{self, DenseBitSet};
Expand Down Expand Up @@ -533,10 +532,20 @@ where
{
#[inline]
fn stable_hash<Hcx: StableHashCtxt>(&self, hcx: &mut Hcx, hasher: &mut StableHasher) {
mem::discriminant(self).stable_hash(hcx, hasher);
#[derive(StableHash)]
enum Tag {
Ok,
Err,
}
match *self {
Ok(ref x) => x.stable_hash(hcx, hasher),
Err(ref x) => x.stable_hash(hcx, hasher),
Ok(ref x) => {
Tag::Ok.stable_hash(hcx, hasher);
x.stable_hash(hcx, hasher);
}
Err(ref x) => {
Tag::Err.stable_hash(hcx, hasher);
x.stable_hash(hcx, hasher);
}
}
}
}
Expand All @@ -551,12 +560,19 @@ where
}
}

impl<T> StableHash for ::std::mem::Discriminant<T> {
#[inline]
fn stable_hash<Hcx: StableHashCtxt>(&self, _: &mut Hcx, hasher: &mut StableHasher) {
::std::hash::Hash::hash(self, hasher);
}
}
/// There is no way to stable-hash a `Discriminant` without leaking unstable
/// details of how the host compiler chooses and hashes discriminants.
///
/// That would be bad, because stable hashes must be consistent between
/// the stage1 compiler (built with the bootstrap compiler/stdlib)
/// and the stage2 compiler (built with the in-tree compiler/stdlib).
///
/// See <https://github.com/rust-lang/rust/issues/164734> for more context.
///
/// If you need to manually stable-hash a discriminant, instead derive `StableHash`
/// on a dedicated "tag" enum, and then hash the appropriate tag for each variant.
/// For an example, see the impl of `StableHash for Result`.
impl<T> !StableHash for std::mem::Discriminant<T> {}

impl<T> StableHash for ::std::range::RangeInclusive<T>
where
Expand Down
2 changes: 1 addition & 1 deletion compiler/rustc_infer/src/infer/canonical/instantiate.rs
Original file line number Diff line number Diff line change
Expand Up @@ -52,7 +52,7 @@ impl<'tcx, V> Canonical<'tcx, V> {
/// Instantiate the values from `var_values` into `value`. `var_values`
/// must be values for the set of canonical variables that appear in
/// `value`.
pub(super) fn instantiate_value<'tcx, T>(
pub fn instantiate_value<'tcx, T>(
tcx: TyCtxt<'tcx>,
var_values: &CanonicalVarValues<'tcx>,
value: T,
Expand Down
2 changes: 1 addition & 1 deletion compiler/rustc_infer/src/infer/canonical/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -21,7 +21,7 @@
//!
//! [c]: https://rust-lang.github.io/chalk/book/canonical_queries/canonicalization.html

pub use instantiate::CanonicalExt;
pub use instantiate::{CanonicalExt, instantiate_value};
use rustc_index::IndexVec;
pub use rustc_middle::infer::canonical::*;
use rustc_middle::ty::{self, GenericArg, Ty, TyCtxt, TypeFoldable};
Expand Down
1 change: 1 addition & 0 deletions compiler/rustc_interface/src/passes.rs
Original file line number Diff line number Diff line change
Expand Up @@ -900,6 +900,7 @@ pub static DEFAULT_QUERY_PROVIDERS: LazyLock<Providers> = LazyLock::new(|| {
providers.queries.analysis = analysis;
providers.queries.resolver_for_lowering_raw = resolver_for_lowering_raw;
providers.queries.stripped_cfg_items = |tcx, _| &tcx.resolutions(()).stripped_cfg_items[..];
providers.queries.get_lang_items = |tcx, ()| &tcx.resolutions(()).lang_items;
providers.queries.resolutions = |tcx, ()| tcx.resolver_for_lowering_raw(()).2;
providers.queries.early_lint_checks = early_lint_checks;
providers.queries.env_var_os = env_var_os;
Expand Down
43 changes: 39 additions & 4 deletions compiler/rustc_macros/src/stable_hash.rs
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
use proc_macro2::Ident;
use quote::quote;
use quote::{ToTokens, quote};

struct Attributes {
ignore: bool,
Expand Down Expand Up @@ -96,9 +96,44 @@ fn stable_hash_derive_with_mode(

fn stable_hash_discriminant(s: &mut synstructure::Structure<'_>) -> proc_macro2::TokenStream {
match s.ast().data {
syn::Data::Enum(_) => quote! {
::std::mem::discriminant(self).stable_hash(__hcx, __hasher);
},
syn::Data::Enum(_) => {
// For stable hashing, use a fake discriminant based on the syntactic
// ordering of enum variants, not the actual runtime discriminant.
// This helps to keep stable hashes consistent between stage1 and stage2.
let n_variants = s.variants().len();

// If this enum has no variants (and is therefore uninhabited),
// matching on `self` will cause the compiler to realise that all
// subsequent code is unreachable, triggering unhelpful warnings.
if n_variants == 0 {
return quote! {};
}

let mut match_arms = proc_macro2::TokenStream::new();

// Use a u8 discriminant, as it's measurably faster than usize.
// If support for larger enums is needed, take care to still use u8
// when possible, to avoid regressions.
assert!(
n_variants <= 256,
"deriving StableHash for an enum with more than 256 variants is unsupported \
(was: {n_variants})"
);
for (discriminant, variant) in (0u8..).zip(s.variants()) {
let pat = variant.pat();

quote! {
#pat => #discriminant.stable_hash(__hcx, __hasher),
}
.to_tokens(&mut match_arms);
}

quote! {
match *self {
#match_arms
}
}
}
syn::Data::Struct(_) => quote! {},
syn::Data::Union(_) => panic!("cannot derive on union"),
}
Expand Down
1 change: 1 addition & 0 deletions compiler/rustc_middle/src/infer/canonical.rs
Original file line number Diff line number Diff line change
Expand Up @@ -34,6 +34,7 @@ use crate::ty::{self, GenericArg, GenericArgsRef, List, Ty, TyCtxt, TypeFlags, T

pub type CanonicalQueryInput<'tcx, V> = ir::CanonicalQueryInput<TyCtxt<'tcx>, V>;
pub type Canonical<'tcx, V> = ir::Canonical<TyCtxt<'tcx>, V>;
pub type Canonicalized<V> = ir::Canonicalized<V>;
pub type CanonicalVarKind<'tcx> = ir::CanonicalVarKind<TyCtxt<'tcx>>;
pub type CanonicalVarValues<'tcx> = ir::CanonicalVarValues<TyCtxt<'tcx>>;
pub type CanonicalVarKinds<'tcx> = &'tcx List<CanonicalVarKind<'tcx>>;
Expand Down
3 changes: 2 additions & 1 deletion compiler/rustc_middle/src/middle/resolve.rs
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@

use rustc_ast::node_id::NodeMap;
use rustc_ast::{self as ast, NodeId};
use rustc_attr_ir::StrippedCfgItem;
use rustc_attr_ir::{LanguageItems, StrippedCfgItem};
use rustc_data_structures::fx::{FxIndexMap, FxIndexSet};
use rustc_data_structures::steal::Steal;
use rustc_data_structures::unord::{UnordMap, UnordSet};
Expand Down Expand Up @@ -197,6 +197,7 @@ pub struct ResolverGlobalCtxt {
pub delegation_infos: FxIndexMap<LocalDefId, DelegationInfo>,
pub delegation_inherent_fn_map:
FxIndexMap<LocalDefId, FxIndexMap<Ident, DelegationInherentFnKind>>,
pub lang_items: LanguageItems,
}

#[derive(Debug)]
Expand Down
1 change: 0 additions & 1 deletion compiler/rustc_middle/src/queries.rs
Original file line number Diff line number Diff line change
Expand Up @@ -2295,7 +2295,6 @@ rustc_queries! {
/// Returns the lang items defined in all crates by loading them from metadata of dependencies
/// and collecting the ones from the current crate.
query get_lang_items(_: ()) -> &'tcx LanguageItems {
arena_cache
eval_always
desc { "calculating the lang items map" }
}
Expand Down
Loading
Loading