Skip to content
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
23 commits
Select commit Hold shift + click to select a range
79b3963
Add Steal::risky_hack_borrow_mut
Lysxia Nov 4, 2025
8075c98
Add test for success path
osamakader Nov 6, 2025
09385f9
use bare_rustc to keep host toolchain
osamakader Nov 7, 2025
244eef6
a few small clippy fixes
hkBst Nov 7, 2025
1c1923f
tests: skip rustdoc test-builder success path when cross-compiling
osamakader Nov 8, 2025
a5814a5
Move `parse_cfg_select` to `rustc_builtin_macros`
JonathanBrouwer Nov 9, 2025
c111ccc
Add more tests for `cfg_select` parsing
JonathanBrouwer Nov 8, 2025
90f36af
Port `cfg_select!` to the new attribute parsing system
JonathanBrouwer Nov 8, 2025
c5f2eb6
rustc_target: hide TargetOptions::vendor
tamird Nov 9, 2025
f1bbe59
tests: skip rustdoc test-builder success path for remote client
osamakader Nov 9, 2025
3d44aca
Fix a typo in the documentation for the strict_shr function
reddevilmidzy Nov 10, 2025
6bfb876
Implement DynSend and DynSync for std::panic::Location.
zachs18 Nov 10, 2025
5ee331f
fix doc comment
luca3s Nov 10, 2025
1839cdb
Remove unneeded `allow(rustc::potential_query_instability)`
GuillaumeGomez Nov 10, 2025
bf361f6
Rollup merge of #148480 - Lysxia:steal-mut, r=davidtwco
ChrisDenton Nov 10, 2025
ddd3ab9
Rollup merge of #148608 - osamakader:doc-test-builder, r=GuillaumeGomez
ChrisDenton Nov 10, 2025
ea367ce
Rollup merge of #148667 - hkBst:clippy-fix-14, r=Kivooeo
ChrisDenton Nov 10, 2025
46207f7
Rollup merge of #148712 - JonathanBrouwer:cfg_select, r=jdonszelmann
ChrisDenton Nov 10, 2025
abf6082
Rollup merge of #148760 - tamird:avoid-vendor-logic, r=madsmtm
ChrisDenton Nov 10, 2025
6c0871f
Rollup merge of #148775 - reddevilmidzy:fix-typo, r=joboet
ChrisDenton Nov 10, 2025
ab6822e
Rollup merge of #148779 - zachs18:panic-location-dynsendsync, r=nneth…
ChrisDenton Nov 10, 2025
1e025c0
Rollup merge of #148781 - GuillaumeGomez:rm-unneeded-attr, r=yotamofek
ChrisDenton Nov 10, 2025
ed0ccfc
Rollup merge of #148791 - luca3s:fix-doc-comment, r=lqd
ChrisDenton Nov 10, 2025
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
6 changes: 3 additions & 3 deletions compiler/rustc_ast_lowering/src/index.rs
Original file line number Diff line number Diff line change
Expand Up @@ -125,9 +125,9 @@ impl<'a, 'hir> NodeCollector<'a, 'hir> {
}

impl<'a, 'hir> Visitor<'hir> for NodeCollector<'a, 'hir> {
/// Because we want to track parent items and so forth, enable
/// deep walking so that we walk nested items in the context of
/// their outer items.
// Because we want to track parent items and so forth, enable
// deep walking so that we walk nested items in the context of
// their outer items.

fn visit_nested_item(&mut self, item: ItemId) {
debug!("visit_nested_item: {:?}", item);
Expand Down
89 changes: 89 additions & 0 deletions compiler/rustc_attr_parsing/src/attributes/cfg_select.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,89 @@
use rustc_ast::token::Token;
use rustc_ast::tokenstream::TokenStream;
use rustc_ast::{AttrStyle, NodeId, token};
use rustc_feature::{AttributeTemplate, Features};
use rustc_hir::AttrPath;
use rustc_hir::attrs::CfgEntry;
use rustc_parse::exp;
use rustc_parse::parser::Parser;
use rustc_session::Session;
use rustc_span::{ErrorGuaranteed, Ident, Span};

use crate::parser::MetaItemOrLitParser;
use crate::{AttributeParser, ParsedDescription, ShouldEmit, parse_cfg_entry};

pub enum CfgSelectPredicate {
Cfg(CfgEntry),
Wildcard(Token),
}

#[derive(Default)]
pub struct CfgSelectBranches {
/// All the conditional branches.
pub reachable: Vec<(CfgEntry, TokenStream, Span)>,
/// The first wildcard `_ => { ... }` branch.
pub wildcard: Option<(Token, TokenStream, Span)>,
/// All branches after the first wildcard, including further wildcards.
/// These branches are kept for formatting.
pub unreachable: Vec<(CfgSelectPredicate, TokenStream, Span)>,
}

pub fn parse_cfg_select(
p: &mut Parser<'_>,
sess: &Session,
features: Option<&Features>,
lint_node_id: NodeId,
) -> Result<CfgSelectBranches, ErrorGuaranteed> {
let mut branches = CfgSelectBranches::default();

while p.token != token::Eof {
if p.eat_keyword(exp!(Underscore)) {
let underscore = p.prev_token;
p.expect(exp!(FatArrow)).map_err(|e| e.emit())?;

let tts = p.parse_delimited_token_tree().map_err(|e| e.emit())?;
let span = underscore.span.to(p.token.span);

match branches.wildcard {
None => branches.wildcard = Some((underscore, tts, span)),
Some(_) => {
branches.unreachable.push((CfgSelectPredicate::Wildcard(underscore), tts, span))
}
}
} else {
let meta = MetaItemOrLitParser::parse_single(p, ShouldEmit::ErrorsAndLints)
.map_err(|diag| diag.emit())?;
let cfg_span = meta.span();
let cfg = AttributeParser::parse_single_args(
sess,
cfg_span,
cfg_span,
AttrStyle::Inner,
AttrPath {
segments: vec![Ident::from_str("cfg_select")].into_boxed_slice(),
span: cfg_span,
},
ParsedDescription::Macro,
cfg_span,
lint_node_id,
features,
ShouldEmit::ErrorsAndLints,
&meta,
parse_cfg_entry,
&AttributeTemplate::default(),
)?;

p.expect(exp!(FatArrow)).map_err(|e| e.emit())?;

let tts = p.parse_delimited_token_tree().map_err(|e| e.emit())?;
let span = cfg_span.to(p.token.span);

match branches.wildcard {
None => branches.reachable.push((cfg, tts, span)),
Some(_) => branches.unreachable.push((CfgSelectPredicate::Cfg(cfg), tts, span)),
}
}
}

Ok(branches)
}
1 change: 1 addition & 0 deletions compiler/rustc_attr_parsing/src/attributes/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -33,6 +33,7 @@ pub(crate) mod allow_unstable;
pub(crate) mod body;
pub(crate) mod cfg;
pub(crate) mod cfg_old;
pub(crate) mod cfg_select;
pub(crate) mod codegen_attrs;
pub(crate) mod confusables;
pub(crate) mod crate_level;
Expand Down
1 change: 1 addition & 0 deletions compiler/rustc_attr_parsing/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -106,6 +106,7 @@ pub use attributes::cfg::{
CFG_TEMPLATE, EvalConfigResult, eval_config_entry, parse_cfg, parse_cfg_attr, parse_cfg_entry,
};
pub use attributes::cfg_old::*;
pub use attributes::cfg_select::*;
pub use attributes::util::{is_builtin_attr, is_doc_alias_attrs_contain_symbol, parse_version};
pub use context::{Early, Late, OmitDoc, ShouldEmit};
pub use interface::AttributeParser;
Expand Down
74 changes: 40 additions & 34 deletions compiler/rustc_builtin_macros/src/cfg_select.rs
Original file line number Diff line number Diff line change
@@ -1,19 +1,21 @@
use rustc_ast::tokenstream::TokenStream;
use rustc_attr_parsing as attr;
use rustc_attr_parsing::{
CfgSelectBranches, CfgSelectPredicate, EvalConfigResult, ShouldEmit, parse_cfg_select,
};
use rustc_expand::base::{DummyResult, ExpandResult, ExtCtxt, MacroExpanderResult};
use rustc_parse::parser::cfg_select::{CfgSelectBranches, CfgSelectPredicate, parse_cfg_select};
use rustc_span::{Ident, Span, sym};

use crate::errors::{CfgSelectNoMatches, CfgSelectUnreachable};

/// Selects the first arm whose predicate evaluates to true.
fn select_arm(ecx: &ExtCtxt<'_>, branches: CfgSelectBranches) -> Option<(TokenStream, Span)> {
for (cfg, tt, arm_span) in branches.reachable {
if attr::cfg_matches(
&cfg,
if let EvalConfigResult::True = attr::eval_config_entry(
&ecx.sess,
&cfg,
ecx.current_expansion.lint_node_id,
Some(ecx.ecfg.features),
ShouldEmit::ErrorsAndLints,
) {
return Some((tt, arm_span));
}
Expand All @@ -27,37 +29,41 @@ pub(super) fn expand_cfg_select<'cx>(
sp: Span,
tts: TokenStream,
) -> MacroExpanderResult<'cx> {
ExpandResult::Ready(match parse_cfg_select(&mut ecx.new_parser_from_tts(tts)) {
Ok(branches) => {
if let Some((underscore, _, _)) = branches.wildcard {
// Warn for every unreachable predicate. We store the fully parsed branch for rustfmt.
for (predicate, _, _) in &branches.unreachable {
let span = match predicate {
CfgSelectPredicate::Wildcard(underscore) => underscore.span,
CfgSelectPredicate::Cfg(cfg) => cfg.span(),
};
let err = CfgSelectUnreachable { span, wildcard_span: underscore.span };
ecx.dcx().emit_warn(err);
ExpandResult::Ready(
match parse_cfg_select(
&mut ecx.new_parser_from_tts(tts),
ecx.sess,
Some(ecx.ecfg.features),
ecx.current_expansion.lint_node_id,
) {
Ok(branches) => {
if let Some((underscore, _, _)) = branches.wildcard {
// Warn for every unreachable predicate. We store the fully parsed branch for rustfmt.
for (predicate, _, _) in &branches.unreachable {
let span = match predicate {
CfgSelectPredicate::Wildcard(underscore) => underscore.span,
CfgSelectPredicate::Cfg(cfg) => cfg.span(),
};
let err = CfgSelectUnreachable { span, wildcard_span: underscore.span };
ecx.dcx().emit_warn(err);
}
}
}

if let Some((tts, arm_span)) = select_arm(ecx, branches) {
return ExpandResult::from_tts(
ecx,
tts,
sp,
arm_span,
Ident::with_dummy_span(sym::cfg_select),
);
} else {
// Emit a compiler error when none of the predicates matched.
let guar = ecx.dcx().emit_err(CfgSelectNoMatches { span: sp });
DummyResult::any(sp, guar)
if let Some((tts, arm_span)) = select_arm(ecx, branches) {
return ExpandResult::from_tts(
ecx,
tts,
sp,
arm_span,
Ident::with_dummy_span(sym::cfg_select),
);
} else {
// Emit a compiler error when none of the predicates matched.
let guar = ecx.dcx().emit_err(CfgSelectNoMatches { span: sp });
DummyResult::any(sp, guar)
}
}
}
Err(err) => {
let guar = err.emit();
DummyResult::any(sp, guar)
}
})
Err(guar) => DummyResult::any(sp, guar),
},
)
}
4 changes: 2 additions & 2 deletions compiler/rustc_codegen_cranelift/src/abi/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -916,8 +916,8 @@ pub(crate) fn codegen_call_with_unwind_action(
pub(crate) fn lib_call_arg_param(tcx: TyCtxt<'_>, ty: Type, is_signed: bool) -> AbiParam {
let param = AbiParam::new(ty);
if ty.is_int() && u64::from(ty.bits()) < tcx.data_layout.pointer_size().bits() {
match (&tcx.sess.target.arch, tcx.sess.target.vendor.as_ref()) {
(Arch::X86_64, _) | (Arch::AArch64, "apple") => match (ty, is_signed) {
match (&tcx.sess.target.arch, tcx.sess.target.is_like_darwin) {
(Arch::X86_64, _) | (Arch::AArch64, true) => match (ty, is_signed) {
(types::I8 | types::I16, true) => param.sext(),
(types::I8 | types::I16, false) => param.uext(),
_ => param,
Expand Down
8 changes: 3 additions & 5 deletions compiler/rustc_codegen_cranelift/src/codegen_f16_f128.rs
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@ use crate::prelude::*;

pub(crate) fn f16_to_f32(fx: &mut FunctionCx<'_, '_, '_>, value: Value) -> Value {
let (value, arg_ty) =
if fx.tcx.sess.target.vendor == "apple" && fx.tcx.sess.target.arch == Arch::X86_64 {
if fx.tcx.sess.target.is_like_darwin && fx.tcx.sess.target.arch == Arch::X86_64 {
(
fx.bcx.ins().bitcast(types::I16, MemFlags::new(), value),
lib_call_arg_param(fx.tcx, types::I16, false),
Expand All @@ -22,8 +22,7 @@ fn f16_to_f64(fx: &mut FunctionCx<'_, '_, '_>, value: Value) -> Value {
}

pub(crate) fn f32_to_f16(fx: &mut FunctionCx<'_, '_, '_>, value: Value) -> Value {
let ret_ty = if fx.tcx.sess.target.vendor == "apple" && fx.tcx.sess.target.arch == Arch::X86_64
{
let ret_ty = if fx.tcx.sess.target.is_like_darwin && fx.tcx.sess.target.arch == Arch::X86_64 {
types::I16
} else {
types::F16
Expand All @@ -38,8 +37,7 @@ pub(crate) fn f32_to_f16(fx: &mut FunctionCx<'_, '_, '_>, value: Value) -> Value
}

fn f64_to_f16(fx: &mut FunctionCx<'_, '_, '_>, value: Value) -> Value {
let ret_ty = if fx.tcx.sess.target.vendor == "apple" && fx.tcx.sess.target.arch == Arch::X86_64
{
let ret_ty = if fx.tcx.sess.target.is_like_darwin && fx.tcx.sess.target.arch == Arch::X86_64 {
types::I16
} else {
types::F16
Expand Down
2 changes: 1 addition & 1 deletion compiler/rustc_codegen_ssa/src/back/link.rs
Original file line number Diff line number Diff line change
Expand Up @@ -1819,7 +1819,7 @@ fn self_contained_components(
LinkSelfContainedDefault::InferredForMusl => sess.crt_static(Some(crate_type)),
LinkSelfContainedDefault::InferredForMingw => {
sess.host == sess.target
&& sess.target.vendor != "uwp"
&& sess.target.abi != "uwp"
&& detect_self_contained_mingw(sess, linker)
}
}
Expand Down
4 changes: 2 additions & 2 deletions compiler/rustc_codegen_ssa/src/back/linker.rs
Original file line number Diff line number Diff line change
Expand Up @@ -83,7 +83,7 @@ pub(crate) fn get_linker<'a>(
// To comply with the Windows App Certification Kit,
// MSVC needs to link with the Store versions of the runtime libraries (vcruntime, msvcrt, etc).
let t = &sess.target;
if matches!(flavor, LinkerFlavor::Msvc(..)) && t.vendor == "uwp" {
if matches!(flavor, LinkerFlavor::Msvc(..)) && t.abi == "uwp" {
if let Some(ref tool) = msvc_tool {
let original_path = tool.path();
if let Some(root_lib_path) = original_path.ancestors().nth(4) {
Expand Down Expand Up @@ -134,7 +134,7 @@ pub(crate) fn get_linker<'a>(

// FIXME: Move `/LIBPATH` addition for uwp targets from the linker construction
// to the linker args construction.
assert!(cmd.get_args().is_empty() || sess.target.vendor == "uwp");
assert!(cmd.get_args().is_empty() || sess.target.abi == "uwp");
match flavor {
LinkerFlavor::Unix(Cc::No) if sess.target.os == "l4re" => {
Box::new(L4Bender::new(cmd, sess)) as Box<dyn Linker>
Expand Down
2 changes: 1 addition & 1 deletion compiler/rustc_codegen_ssa/src/common.rs
Original file line number Diff line number Diff line change
Expand Up @@ -171,7 +171,7 @@ pub fn asm_const_to_str<'tcx>(
}

pub fn is_mingw_gnu_toolchain(target: &Target) -> bool {
target.vendor == "pc" && target.os == "windows" && target.env == "gnu" && target.abi.is_empty()
target.os == "windows" && target.env == "gnu" && target.abi.is_empty()
}

pub fn i686_decorated_name(
Expand Down
8 changes: 4 additions & 4 deletions compiler/rustc_data_structures/src/marker.rs
Original file line number Diff line number Diff line change
Expand Up @@ -53,13 +53,13 @@ impl !DynSend for std::env::VarsOs {}

macro_rules! already_send {
($([$ty: ty])*) => {
$(unsafe impl DynSend for $ty where $ty: Send {})*
$(unsafe impl DynSend for $ty where Self: Send {})*
};
}

// These structures are already `Send`.
already_send!(
[std::backtrace::Backtrace][std::io::Stdout][std::io::Stderr][std::io::Error][std::fs::File]
[std::backtrace::Backtrace][std::io::Stdout][std::io::Stderr][std::io::Error][std::fs::File][std::panic::Location<'_>]
[rustc_arena::DroplessArena][jobserver_crate::Client][jobserver_crate::HelperThread]
[crate::memmap::Mmap][crate::profiling::SelfProfiler][crate::owned_slice::OwnedSlice]
);
Expand Down Expand Up @@ -127,14 +127,14 @@ impl !DynSync for std::env::VarsOs {}

macro_rules! already_sync {
($([$ty: ty])*) => {
$(unsafe impl DynSync for $ty where $ty: Sync {})*
$(unsafe impl DynSync for $ty where Self: Sync {})*
};
}

// These structures are already `Sync`.
already_sync!(
[std::sync::atomic::AtomicBool][std::sync::atomic::AtomicUsize][std::sync::atomic::AtomicU8]
[std::sync::atomic::AtomicU32][std::backtrace::Backtrace][std::io::Error][std::fs::File]
[std::sync::atomic::AtomicU32][std::backtrace::Backtrace][std::io::Error][std::fs::File][std::panic::Location<'_>]
[jobserver_crate::Client][jobserver_crate::HelperThread][crate::memmap::Mmap]
[crate::profiling::SelfProfiler][crate::owned_slice::OwnedSlice]
);
Expand Down
14 changes: 11 additions & 3 deletions compiler/rustc_data_structures/src/steal.rs
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
use crate::stable_hasher::{HashStable, StableHasher};
use crate::sync::{MappedReadGuard, ReadGuard, RwLock};
use crate::sync::{MappedReadGuard, MappedWriteGuard, ReadGuard, RwLock, WriteGuard};

/// The `Steal` struct is intended to used as the value for a query.
/// Specifically, we sometimes have queries (*cough* MIR *cough*)
Expand Down Expand Up @@ -40,9 +40,17 @@ impl<T> Steal<T> {
ReadGuard::map(borrow, |opt| opt.as_ref().unwrap())
}

/// An escape hatch for rustc drivers to mutate `Steal` caches.
///
/// Use at your own risk. This can badly break incremental compilation
/// and anything else that relies on the immutability of query caches.
#[track_caller]
pub fn get_mut(&mut self) -> &mut T {
self.value.get_mut().as_mut().expect("attempt to read from stolen value")
pub fn risky_hack_borrow_mut(&self) -> MappedWriteGuard<'_, T> {
let borrow = self.value.borrow_mut();
if borrow.is_none() {
panic!("attempted to read from stolen value: {}", std::any::type_name::<T>());
}
WriteGuard::map(borrow, |opt| opt.as_mut().unwrap())
}

#[track_caller]
Expand Down
7 changes: 1 addition & 6 deletions compiler/rustc_errors/src/emitter.rs
Original file line number Diff line number Diff line change
Expand Up @@ -2322,11 +2322,6 @@ impl HumanEmitter {
show_code_change
{
for part in parts {
let snippet = if let Ok(snippet) = sm.span_to_snippet(part.span) {
snippet
} else {
String::new()
};
let span_start_pos = sm.lookup_char_pos(part.span.lo()).col_display;
let span_end_pos = sm.lookup_char_pos(part.span.hi()).col_display;

Expand Down Expand Up @@ -2402,7 +2397,7 @@ impl HumanEmitter {
// LL - REMOVED <- row_num - 2 - (newlines - first_i - 1)
// LL + NEWER
// | <- row_num

let snippet = sm.span_to_snippet(part.span).unwrap_or_default();
let newlines = snippet.lines().count();
if newlines > 0 && row_num > newlines {
// Account for removals where the part being removed spans multiple
Expand Down
12 changes: 12 additions & 0 deletions compiler/rustc_hir/src/attrs/data_structures.rs
Original file line number Diff line number Diff line change
Expand Up @@ -194,6 +194,18 @@ pub enum CfgEntry {
Version(Option<RustcVersion>, Span),
}

impl CfgEntry {
pub fn span(&self) -> Span {
let (CfgEntry::All(_, span)
| CfgEntry::Any(_, span)
| CfgEntry::Not(_, span)
| CfgEntry::Bool(_, span)
| CfgEntry::NameValue { span, .. }
| CfgEntry::Version(_, span)) = self;
*span
}
}

/// Possible values for the `#[linkage]` attribute, allowing to specify the
/// linkage type for a `MonoItem`.
///
Expand Down
Loading
Loading