Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
24 commits
Select commit Hold shift + click to select a range
e063776
Fix LegacyKeyValueFormat report from docker build: powerpc
homersimpsons Mar 4, 2026
2e65734
feat: reimplement `hash_map!` macro
m4rch3n1ng Mar 24, 2026
eee01dd
Add `IoSplit` diagnostic item for `std::io::Split`
vitkyrka Mar 26, 2026
1f17857
std_detect on AArch64 Darwin: Detect FEAT_SVE_B16B16
pthariensflame Mar 28, 2026
024acdd
Fix ambiguous parsing in bootstrap.py
Mark-Simulacrum Mar 28, 2026
27242aa
Panic in Hermit clock_gettime
stepancheg Mar 28, 2026
64ee85d
update zulip link in `std` documentation
fee1-dead Mar 29, 2026
69b6d26
fix invalid type suggestion for item nested in function
chenyukang Mar 29, 2026
51816ef
don't drop arguments' temporaries in `dbg!`
dianne Mar 19, 2026
9fd2c9e
Add regression test for recursive lazy type alias normalization ICE
jeanibarz Mar 29, 2026
c67380d
rustdoc: add test showing cfg pretty-printing of all targets
scrabsha Mar 19, 2026
9f09448
rustdoc: add missing target_{os,arch,env} values for cfg pretty printer
scrabsha Mar 19, 2026
7d1b41c
update diagnostic for variables moved by `dbg!`
dianne Mar 29, 2026
2a18b88
Rollup merge of #154074 - dianne:dbg-temp-scopes, r=Mark-Simulacrum
JonathanBrouwer Mar 29, 2026
880c9e0
Rollup merge of #154328 - scrabsha:push-tkozopuzoorz, r=lolbinarycat
JonathanBrouwer Mar 29, 2026
883eda3
Rollup merge of #154540 - chenyukang:yukang-fix-146786-unusable-path-…
JonathanBrouwer Mar 29, 2026
59e6f0d
Rollup merge of #154549 - jeanibarz:fix/add-test-152633, r=chenyukang
JonathanBrouwer Mar 29, 2026
db19e88
Rollup merge of #153373 - homersimpsons:chore/fix-LegacyKeyValueForma…
JonathanBrouwer Mar 29, 2026
880fe19
Rollup merge of #154322 - m4rch3n1ng:hash-map-macro, r=Mark-Simulacrum
JonathanBrouwer Mar 29, 2026
46dcf27
Rollup merge of #154416 - vitkyrka:split-diag, r=Noratrieb
JonathanBrouwer Mar 29, 2026
ab05593
Rollup merge of #154486 - pthariensflame:patch-1, r=Mark-Simulacrum
JonathanBrouwer Mar 29, 2026
0d7708d
Rollup merge of #154508 - Mark-Simulacrum:fix-ambiguous-parse, r=jiey…
JonathanBrouwer Mar 29, 2026
95acbdf
Rollup merge of #154518 - stepancheg:hermit-panic, r=Mark-Simulacrum
JonathanBrouwer Mar 29, 2026
de649f4
Rollup merge of #154530 - fee1-dead-contrib:push-syplyyvkpsol, r=Nora…
JonathanBrouwer Mar 29, 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
40 changes: 25 additions & 15 deletions compiler/rustc_borrowck/src/diagnostics/conflict_errors.rs
Original file line number Diff line number Diff line change
Expand Up @@ -588,8 +588,6 @@ impl<'infcx, 'tcx> MirBorrowckCtxt<'_, 'infcx, 'tcx> {
}

// for dbg!(x) which may take ownership, suggest dbg!(&x) instead
// but here we actually do not check whether the macro name is `dbg!`
// so that we may extend the scope a bit larger to cover more cases
fn suggest_ref_for_dbg_args(
&self,
body: &hir::Expr<'_>,
Expand All @@ -603,29 +601,41 @@ impl<'infcx, 'tcx> MirBorrowckCtxt<'_, 'infcx, 'tcx> {
});
let Some(var_info) = var_info else { return };
let arg_name = var_info.name;
struct MatchArgFinder {
expr_span: Span,
match_arg_span: Option<Span>,
struct MatchArgFinder<'tcx> {
tcx: TyCtxt<'tcx>,
move_span: Span,
arg_name: Symbol,
match_arg_span: Option<Span> = None,
}
impl Visitor<'_> for MatchArgFinder {
impl Visitor<'_> for MatchArgFinder<'_> {
fn visit_expr(&mut self, e: &hir::Expr<'_>) {
// dbg! is expanded into a match pattern, we need to find the right argument span
if let hir::ExprKind::Match(expr, ..) = &e.kind
&& let hir::ExprKind::Path(hir::QPath::Resolved(
_,
path @ Path { segments: [seg], .. },
)) = &expr.kind
&& seg.ident.name == self.arg_name
&& self.expr_span.source_callsite().contains(expr.span)
if let hir::ExprKind::Match(scrutinee, ..) = &e.kind
&& let hir::ExprKind::Tup(args) = scrutinee.kind
&& e.span.macro_backtrace().any(|expn| {
expn.macro_def_id.is_some_and(|macro_def_id| {
self.tcx.is_diagnostic_item(sym::dbg_macro, macro_def_id)
})
})
{
self.match_arg_span = Some(path.span);
for arg in args {
if let hir::ExprKind::Path(hir::QPath::Resolved(
_,
path @ Path { segments: [seg], .. },
)) = &arg.kind
&& seg.ident.name == self.arg_name
&& self.move_span.source_equal(arg.span)
{
self.match_arg_span = Some(path.span);
return;
}
}
}
hir::intravisit::walk_expr(self, e);
}
}

let mut finder = MatchArgFinder { expr_span: move_span, match_arg_span: None, arg_name };
let mut finder = MatchArgFinder { tcx: self.infcx.tcx, move_span, arg_name, .. };
finder.visit_expr(body);
if let Some(macro_arg_span) = finder.match_arg_span {
err.span_suggestion_verbose(
Expand Down
4 changes: 2 additions & 2 deletions compiler/rustc_hir_analysis/src/collect/type_of.rs
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@ use rustc_errors::{Applicability, StashKey, Suggestions};
use rustc_hir::def_id::{DefId, LocalDefId};
use rustc_hir::intravisit::VisitorExt;
use rustc_hir::{self as hir, AmbigArg, HirId};
use rustc_middle::ty::print::with_forced_trimmed_paths;
use rustc_middle::ty::print::{with_forced_trimmed_paths, with_types_for_suggestion};
use rustc_middle::ty::util::IntTypeExt;
use rustc_middle::ty::{self, DefiningScopeKind, IsSuggestable, Ty, TyCtxt, TypeVisitableExt};
use rustc_middle::{bug, span_bug};
Expand Down Expand Up @@ -451,7 +451,7 @@ fn infer_placeholder_type<'tcx>(
err.span_suggestion(
ty_span,
format!("provide a type for the {kind}"),
format!("{colon} {ty}"),
with_types_for_suggestion!(format!("{colon} {ty}")),
Applicability::MachineApplicable,
);
} else {
Expand Down
17 changes: 15 additions & 2 deletions compiler/rustc_middle/src/ty/print/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -133,8 +133,15 @@ pub trait Printer<'tcx>: Sized {
self.print_path_with_generic_args(|p| p.print_def_path(def_id, parent_args), &[kind.into()])
}

// Defaults (should not be overridden):
fn reset_path(&mut self) -> Result<(), PrintError> {
Ok(())
}

fn should_omit_parent_def_path(&self, _parent_def_id: DefId) -> bool {
false
}

// Defaults (should not be overridden):
#[instrument(skip(self), level = "debug")]
fn default_print_def_path(
&mut self,
Expand Down Expand Up @@ -210,9 +217,15 @@ pub trait Printer<'tcx>: Sized {
&& self.tcx().generics_of(parent_def_id).parent_count == 0;
}

let omit_parent = matches!(key.disambiguated_data.data, DefPathData::TypeNs(..))
&& self.should_omit_parent_def_path(parent_def_id);

self.print_path_with_simple(
|p: &mut Self| {
if trait_qualify_parent {
if omit_parent {
p.reset_path()?;
Ok(())
} else if trait_qualify_parent {
let trait_ref = ty::TraitRef::new(
p.tcx(),
parent_def_id,
Expand Down
13 changes: 13 additions & 0 deletions compiler/rustc_middle/src/ty/print/pretty.rs
Original file line number Diff line number Diff line change
Expand Up @@ -2224,6 +2224,19 @@ impl<'tcx> Printer<'tcx> for FmtPrinter<'_, 'tcx> {
self.tcx
}

fn reset_path(&mut self) -> Result<(), PrintError> {
self.empty_path = true;
Ok(())
}

fn should_omit_parent_def_path(&self, parent_def_id: DefId) -> bool {
RTN_MODE.with(|mode| mode.get()) == RtnMode::ForSuggestion
&& matches!(
self.tcx().def_key(parent_def_id).disambiguated_data.data,
DefPathData::ValueNs(..) | DefPathData::Closure | DefPathData::AnonConst
)
}

fn print_def_path(
&mut self,
def_id: DefId,
Expand Down
1 change: 1 addition & 0 deletions compiler/rustc_span/src/symbol.rs
Original file line number Diff line number Diff line change
Expand Up @@ -746,6 +746,7 @@ symbols! {
custom_mir,
custom_test_frameworks,
d32,
dbg_macro,
dead_code,
dealloc,
debug,
Expand Down
1 change: 1 addition & 0 deletions library/std/src/io/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -3348,6 +3348,7 @@ impl SizeHint for &[u8] {
/// [`split`]: BufRead::split
#[stable(feature = "rust1", since = "1.0.0")]
#[derive(Debug)]
#[cfg_attr(not(test), rustc_diagnostic_item = "IoSplit")]
pub struct Split<B> {
buf: B,
delim: u8,
Expand Down
8 changes: 5 additions & 3 deletions library/std/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -94,8 +94,8 @@
//! pull-requests for your suggested changes.
//!
//! Contributions are appreciated! If you see a part of the docs that can be
//! improved, submit a PR, or chat with us first on [Zulip][rust-zulip]
//! #docs.
//! improved, submit a PR, or chat with us first on [Zulip][t-libs-zulip]
//! #t-libs.
//!
//! # A Tour of The Rust Standard Library
//!
Expand Down Expand Up @@ -209,7 +209,7 @@
//! [multithreading]: thread
//! [other]: #what-is-in-the-standard-library-documentation
//! [primitive types]: ../book/ch03-02-data-types.html
//! [rust-zulip]: https://rust-lang.zulipchat.com/
//! [t-libs-zulip]: https://rust-lang.zulipchat.com/#narrow/channel/219381-t-libs/
//! [array]: prim@array
//! [slice]: prim@slice

Expand Down Expand Up @@ -337,6 +337,8 @@
#![feature(formatting_options)]
#![feature(funnel_shifts)]
#![feature(generic_atomic)]
#![feature(hash_map_internals)]
#![feature(hash_map_macro)]
#![feature(hasher_prefixfree_extras)]
#![feature(hashmap_internals)]
#![feature(hint_must_use)]
Expand Down
158 changes: 119 additions & 39 deletions library/std/src/macros.rs
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,9 @@
//! library.
// ignore-tidy-dbg

#[cfg(test)]
mod tests;

#[doc = include_str!("../../core/src/macros/panic.md")]
#[macro_export]
#[rustc_builtin_macro(std_panic)]
Expand Down Expand Up @@ -359,19 +362,16 @@ macro_rules! dbg {
};
}

/// Internal macro that processes a list of expressions and produces a chain of
/// nested `match`es, one for each expression, before finally calling `eprint!`
/// with the collected information and returning all the evaluated expressions
/// in a tuple.
/// Internal macro that processes a list of expressions, binds their results
/// with `match`, calls `eprint!` with the collected information, and returns
/// all the evaluated expressions in a tuple.
///
/// E.g. `dbg_internal!(() () (1, 2))` expands into
/// ```rust, ignore
/// match 1 {
/// tmp_1 => match 2 {
/// tmp_2 => {
/// eprint!("...", &tmp_1, &tmp_2, /* some other arguments */);
/// (tmp_1, tmp_2)
/// }
/// match (1, 2) {
/// (tmp_1, tmp_2) => {
/// eprint!("...", &tmp_1, &tmp_2, /* some other arguments */);
/// (tmp_1, tmp_2)
/// }
/// }
/// ```
Expand All @@ -380,37 +380,117 @@ macro_rules! dbg {
#[doc(hidden)]
#[rustc_macro_transparency = "semiopaque"]
pub macro dbg_internal {
(($($piece:literal),+) ($($processed:expr => $bound:expr),+) ()) => {{
$crate::eprint!(
$crate::concat!($($piece),+),
$(
$crate::stringify!($processed),
// The `&T: Debug` check happens here (not in the format literal desugaring)
// to avoid format literal related messages and suggestions.
&&$bound as &dyn $crate::fmt::Debug
),+,
// The location returned here is that of the macro invocation, so
// it will be the same for all expressions. Thus, label these
// arguments so that they can be reused in every piece of the
// formatting template.
file=$crate::file!(),
line=$crate::line!(),
column=$crate::column!()
);
// Comma separate the variables only when necessary so that this will
// not yield a tuple for a single expression, but rather just parenthesize
// the expression.
($($bound),+)
}},
(($($piece:literal),*) ($($processed:expr => $bound:expr),*) ($val:expr $(,$rest:expr)*)) => {
(($($piece:literal),+) ($($processed:expr => $bound:ident),+) ()) => {
// Use of `match` here is intentional because it affects the lifetimes
// of temporaries - https://stackoverflow.com/a/48732525/1063961
match $val {
tmp => $crate::macros::dbg_internal!(
($($piece,)* "[{file}:{line}:{column}] {} = {:#?}\n")
($($processed => $bound,)* $val => tmp)
($($rest),*)
),
// Always put the arguments in a tuple to avoid an unused parens lint on the pattern.
match ($($processed,)+) {
($($bound,)+) => {
$crate::eprint!(
$crate::concat!($($piece),+),
$(
$crate::stringify!($processed),
// The `&T: Debug` check happens here (not in the format literal desugaring)
// to avoid format literal related messages and suggestions.
&&$bound as &dyn $crate::fmt::Debug
),+,
// The location returned here is that of the macro invocation, so
// it will be the same for all expressions. Thus, label these
// arguments so that they can be reused in every piece of the
// formatting template.
file=$crate::file!(),
line=$crate::line!(),
column=$crate::column!()
);
// Comma separate the variables only when necessary so that this will
// not yield a tuple for a single expression, but rather just parenthesize
// the expression.
($($bound),+)

}
}
},
(($($piece:literal),*) ($($processed:expr => $bound:ident),*) ($val:expr $(,$rest:expr)*)) => {
$crate::macros::dbg_internal!(
($($piece,)* "[{file}:{line}:{column}] {} = {:#?}\n")
($($processed => $bound,)* $val => tmp)
($($rest),*)
)
},
}

#[doc(hidden)]
#[macro_export]
#[allow_internal_unstable(hash_map_internals)]
#[unstable(feature = "hash_map_internals", issue = "none")]
macro_rules! repetition_utils {
(@count $($tokens:tt),*) => {{
[$($crate::repetition_utils!(@replace $tokens => ())),*].len()
}};

(@replace $x:tt => $y:tt) => { $y }
}

/// Creates a [`HashMap`] containing the arguments.
///
/// `hash_map!` allows specifying the entries that make
/// up the [`HashMap`] where the key and value are separated by a `=>`.
///
/// The entries are separated by commas with a trailing comma being allowed.
///
/// It is semantically equivalent to using repeated [`HashMap::insert`]
/// on a newly created hashmap.
///
/// `hash_map!` will attempt to avoid repeated reallocations by
/// using [`HashMap::with_capacity`].
///
/// # Examples
///
/// ```rust
/// #![feature(hash_map_macro)]
/// use std::hash_map;
///
/// let map = hash_map! {
/// "key" => "value",
/// "key1" => "value1"
/// };
///
/// assert_eq!(map.get("key"), Some(&"value"));
/// assert_eq!(map.get("key1"), Some(&"value1"));
/// assert!(map.get("brrrrrrooooommm").is_none());
/// ```
///
/// And with a trailing comma
///
///```rust
/// #![feature(hash_map_macro)]
/// use std::hash_map;
///
/// let map = hash_map! {
/// "key" => "value", // notice the ,
/// };
///
/// assert_eq!(map.get("key"), Some(&"value"));
/// ```
///
/// The key and value are moved into the HashMap.
///
/// [`HashMap`]: crate::collections::HashMap
/// [`HashMap::insert`]: crate::collections::HashMap::insert
/// [`HashMap::with_capacity`]: crate::collections::HashMap::with_capacity
#[macro_export]
#[allow_internal_unstable(hash_map_internals)]
#[unstable(feature = "hash_map_macro", issue = "144032")]
macro_rules! hash_map {
() => {{
$crate::collections::HashMap::new()
}};

( $( $key:expr => $value:expr ),* $(,)? ) => {{
let mut map = $crate::collections::HashMap::with_capacity(
const { $crate::repetition_utils!(@count $($key),*) }
);
$( map.insert($key, $value); )*
map
}}
}
13 changes: 13 additions & 0 deletions library/std/src/macros/tests.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
// ignore-tidy-dbg

/// Test for <https://github.com/rust-lang/rust/issues/153850>:
/// `dbg!` shouldn't drop arguments' temporaries.
#[test]
fn no_dropping_temps() {
fn temp() {}

*dbg!(&temp());
*dbg!(&temp(), 1).0;
*dbg!(0, &temp()).1;
*dbg!(0, &temp(), 2).1;
}
2 changes: 1 addition & 1 deletion library/std/src/sys/time/hermit.rs
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@ use crate::time::Duration;

fn clock_gettime(clock: hermit_abi::clockid_t) -> Timespec {
let mut t = hermit_abi::timespec { tv_sec: 0, tv_nsec: 0 };
let _ = unsafe { hermit_abi::clock_gettime(clock, &raw mut t) };
unsafe { hermit_abi::clock_gettime(clock, &raw mut t) }.unwrap();
Timespec::new(t.tv_sec, t.tv_nsec.into()).unwrap()
}

Expand Down
Loading
Loading